account-takeover.md (17912B)
1 --- 2 title: "Account Takeover" 3 section: "Web Pentesting" 4 sectionSlug: "pentesting-web" 5 sourcePath: "src/pentesting-web/account-takeover.md" 6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/pentesting-web/account-takeover.md" 7 sha: "188de82beb54e70956b2952367a0af91d26758b8" 8 isIndex: false 9 modified: true 10 license: "CC-BY-NC-4.0" 11 --- 12 13 # Account Takeover 14 15 ## **Authorization Issue** 16 17 The email of an account should be attempted to be changed, and the confirmation process **must be examined**. If found to be **weak**, the email should be changed to that of the intended victim and then confirmed.<sup>[[2]](#references)</sup> 18 19 ## **Unicode Normalization Issue** 20 21 1. The account of the intended victim `victim@gmail.com` 22 2. An account should be created using Unicode\ 23 for example: `vićtim@gmail.com`<sup>[[2]](#references)</sup> 24 25 As explained in [**this talk**](https://www.youtube.com/watch?v=CiIyaZ3x49c), the previous attack could also be done abusing third party identity providers:<sup>[[10]](#references)</sup> 26 27 - Create an account in the third party identity with similar email to the victim using some unicode character (`vićtim@company.com`). 28 - The third party provider shouldn't verify the email 29 - If the identity provider verifies the email, maybe you can attack the domain part like: `victim@ćompany.com` and register that domain and hope that the identity provider generates the ascii version of the domain while the victim platform normalize the domain name. 30 - Login via this identity provider in the victim platform who should normalize the unicode character and allow you to access the victim account. 31 32 ### Unicode/email parser disagreement 33 34 Normalization bugs don't only happen in the UI. Also compare how the **DB collation**, the **SMTP server**, and any **OAuth/OIDC provider** interpret the same mailbox: 35 36 1. The application looks up the attacker-controlled email using a **permissive collation** and matches the victim row. 37 2. The reset token, magic link, or federated identity is later bound to the **raw attacker-controlled Unicode address** instead of the canonical email stored in the DB. 38 3. The attacker receives the artifact or is logged in as the victim. 39 40 Practical checks: 41 42 - Intercept forgot-password, email-change, and invite flows and replace the victim email with a **confusable / Unicode** variant you control. 43 - If social login is supported, repeat the same idea with the **email returned by the IdP** during the callback. 44 - If the backend sends the email **taken from user input** instead of the **canonical address stored in the database**, the flow is usually exploitable. 45 46 For further details, refer to the document on Unicode Normalization: 47 48 49 [Unicode Normalization](/hacktricks/pentesting-web/unicode-injection/unicode-normalization) 50 51 ## **Reusing Reset Token** 52 53 Should the target system allow the **reset link** (or an equivalent **magic link**) to be **reused**, efforts should be made to **find more reset links** using tools such as `gau`, `wayback`, or `scan.io`.<sup>[[2]](#references)</sup> Also verify whether the artifact still works **after an email change** or when redeemed from a **second browser/device**. 54 55 ## **Pre Account Takeover** 56 57 1. The victim's email should be used to sign up on the platform, and a password should be set (an attempt to confirm it should be made, although lacking access to the victim's emails might render this impossible). 58 2. One should wait until the victim signs up using OAuth and confirms the account. 59 3. It is hoped that the regular signup will be confirmed, allowing access to the victim's account.<sup>[[2]](#references)</sup> 60 61 ## **CORS Misconfiguration to Account Takeover** 62 63 If the page contains **CORS misconfigurations** you might be able to **steal sensitive information** from the user to **takeover his account** or make him change auth information for the same purpose:<sup>[[2]](#references)</sup> 64 65 66 [Cors Bypass](/hacktricks/pentesting-web/cors-bypass) 67 68 ## **CSRF to Account Takeover** 69 70 If the page is vulnerable to CSRF, you may be able to make the **user modify their password, email, or authentication settings** and then access the account:<sup>[[2]](#references)</sup> 71 72 73 [Csrf Cross Site Request Forgery](/hacktricks/pentesting-web/csrf-cross-site-request-forgery) 74 75 ## **XSS to Account Takeover** 76 77 If you find XSS in an application, you may be able to steal cookies, local-storage data, or page content that enables account takeover:<sup>[[2]](#references)</sup> 78 79 80 [Xss Cross Site Scripting](/hacktricks/pentesting-web/xss-cross-site-scripting/overview) 81 82 - Attribute-only reflected payloads on login pages can hook `document.onkeypress`, exfiltrate keystrokes through `new Image().src`, and steal credentials without submitting the form. See [Attribute-only login XSS behind WAFs](/hacktricks/pentesting-web/xss-cross-site-scripting/overview#attribute-only-login-xss-behind-wafs) for a practical workflow.<sup>[[1]](#references)</sup> 83 84 ## **Same Origin + Cookies** 85 86 If you find a limited XSS or a subdomain take over, you could play with the cookies (fixating them for example) to try to compromise the victim account:<sup>[[2]](#references)</sup> 87 88 89 [Hacking With Cookies](/hacktricks/pentesting-web/hacking-with-cookies/overview) 90 91 ## **Predictable SSO / bearer cookies and staged login replay** 92 93 Some cross-application SSO stacks treat a client-visible cookie as a **bearer secret** and use it directly as the **server-side cache key** for the authenticated identity. If the value is generated from **low-entropy data** such as `System.currentTimeMillis()`, a sequential ID, or an encoded timestamp with no MAC/signature, the attacker only needs to predict the victim's login window and replay candidate values.<sup>[[8]](#references)</sup> 94 95 Quick triage: 96 97 - Inspect post-login cookies for **13-digit timestamps**, **sequential values**, or trivially encoded IDs. 98 - Review **product-specific overrides**: the shared framework may use a safe UUID generator while one SSO subclass replaces it with a predictable value. 99 - If the SSO resolver only runs for tickets claiming to come from **another integrated application**, try a **mismatched app tag / source-product cookie** to force the cross-product branch. 100 101 Typical exploitation pattern: 102 103 1. Send a request to a protected endpoint with the candidate ticket and the alternate-app tag. 104 2. If the ticket resolves, the first request may only **stage the victim identity in a new server-side session** and return an auto-submitting login form. 105 3. Replay the returned form or its equivalent auth endpoint (`/j_security_check`, SAML/OIDC bridge, custom login handler, etc.) because this **second step often establishes the authenticated principal**. 106 4. Confirm the takeover with a follow-up protected request (`200`) versus the normal login redirect (`302`). 107 108 ```http 109 GET /protected.do HTTP/1.1 110 Host: target.tld 111 Cookie: CUSTOM_SSO_TICKET=<candidate>; CUSTOM_SSO_APP_TAG_NAME=<other-product> 112 ``` 113 114 Important constraints: 115 116 - The correct ticket may only work from the **victim's source IP**, shared NAT, internal foothold, or a path through a **trusted proxy**. Check whether proxy-trust settings let `X-Forwarded-For` override the recorded client IP. 117 - A **rolling throttle** on path + real source IP can make even a 1-second millisecond window (~1,000 candidates) slow to enumerate. Reuse the ideas in [Rate Limit Bypass](/hacktricks/pentesting-web/rate-limit-bypass), but remember that distributing guesses across random IPs will fail if only the victim's IP can produce a hit. 118 - Replacing predictable tokens with UUIDs stops unauthenticated guessing, but a separately stolen live cookie may still replay if the token remains a **pure bearer credential**. For generic cookie abuse patterns see [Cookies Hacking](/hacktricks/pentesting-web/hacking-with-cookies/overview). 119 120 Safe detection tip: send an **impossible historical token** plus the **mismatched app tag** to a protected path and look for **branch-specific cleanup `Set-Cookie` headers** (forced cookie deletion / logout). That proves the cross-application SSO replay path is reachable without resolving a real victim session, but it does **not** prove the generator is still predictable.<sup>[[9]](#references)</sup> 121 122 ## **Attacking Password Reset Mechanism** 123 124 125 [Reset Password](/hacktricks/pentesting-web/reset-password) 126 127 ## **Magic Links / Passwordless Login** 128 129 Passwordless email-login flows deserve the same scrutiny as reset-password flows:<sup>[[6]](#references)</sup> 130 131 - If the unauthenticated endpoint that creates the magic link accepts attacker-controlled `redirect_url`, `next`, `return_to`, or `callback` parameters, request a link for the victim and make the post-login redirect land on an attacker origin first. 132 - If the confirmation endpoint puts the token or session in the URL, fragment, or a browser-readable response, the attacker-controlled landing page can steal it and then bounce the victim back to the real application. 133 - On mobile, test **custom schemes**, **Branch/app.link-style deep links**, and **unverified App / Universal Links**. A malicious app can register the same handler and intercept the login token. 134 - Verify the link is **single-use** and **browser/app-bound**: open it from two browsers, two profiles, webmail vs native mail, and browser vs native app. 135 - If the same endpoint silently creates users, combine this with **pre-account takeover** and **email verification bypass** tests. 136 137 ```http 138 POST /api/auth/magic-link HTTP/1.1 139 Host: target.tld 140 Content-Type: application/json 141 142 {"email":"victim@target.tld","redirect_url":"https://attacker.tld/callback"} 143 ``` 144 145 ## Security-question resets that trust client-supplied usernames 146 If an "update security questions" flow takes a `username` parameter even though the caller is already authenticated, you can overwrite any account's recovery data (including admins) because the backend typically runs `UPDATE ... WHERE user_name = ?` with your untrusted value. The pattern is:<sup>[[4]](#references)</sup> 147 148 1. Log in with a throwaway user and capture the session cookie. 149 2. Submit the victim username plus new answers via the reset form. 150 3. Immediately authenticate through the security-question login endpoint using the answers you just injected to inherit the victim's privileges. 151 152 ```http 153 POST /reset.php HTTP/1.1 154 Host: file.era.htb 155 Cookie: PHPSESSID=<low-priv> 156 Content-Type: application/x-www-form-urlencoded 157 158 username=admin_ef01cab31aa&new_answer1=A&new_answer2=B&new_answer3=C 159 ``` 160 161 Anything gated by the victim's `$_SESSION` context (admin dashboards, dangerous stream-wrapper features, etc.) is now exposed without touching the real answers. 162 163 Enumerated usernames can then be targeted via the overwrite technique above or reused against ancillary services (FTP/SSH password spraying).<sup>[[4]](#references)</sup> 164 165 ## OAuth to Account takeover 166 167 168 [Oauth To Account Takeover](/hacktricks/pentesting-web/oauth-to-account-takeover) 169 170 ## **QR / Cross-Device Login Flows** 171 172 Desktop QR login, TV/device-code login, wallet login, and "approve on your phone" flows are now common ATO surfaces. Treat `qrId`, `device_code`, approval handles, and polling session identifiers like password-reset tokens.<sup>[[7]](#references)</sup> 173 174 Common weaknesses to test: 175 176 - **Unbound browser session**: approving the flow authenticates a different browser than the one that created it. 177 - **Reusable QR / device codes**: the same code authenticates multiple browsers ("double login"). 178 - **Predictable or attacker-controlled identifiers**: short, sequential, or client-generated `qrId` / `device_code` values can be brute-forced or replaced. 179 - **Weak approval context**: the mobile app doesn't show enough origin, device, or action details, making consent phishing and session swapping realistic. 180 181 Practical workflow: 182 183 1. Start the flow in the attacker browser and capture the polling/status endpoint. 184 2. Reuse the same `qrId` / `device_code` from a second browser or after the first login completes. 185 3. Swap browser/session identifiers between two accounts and check whether approval follows the **code** instead of the original session. 186 4. Try parallel polling/races and brute-forcing short QR identifiers. 187 5. If the platform supports wallet or passkey-based cross-device login, verify whether the handoff is rejected when the QR/device code is stale, already redeemed, or replayed from the wrong context. 188 189 From the defender side, current guidance is to require **short-lived one-time codes**, add **request-binding / extra confirmation data**, and where possible **prove device proximity**.<sup>[[7]](#references)</sup> 190 191 ## Host Header Injection 192 193 1. The Host header is modified following a password reset request initiation. 194 2. The `X-Forwarded-For` proxy header is altered to `attacker.com`. 195 3. The Host, Referrer, and Origin headers are simultaneously changed to `attacker.com`. 196 4. After initiating a password reset and then opting to resend the mail, all three of the aforementioned methods are employed.<sup>[[2]](#references)</sup> 197 198 ## Response Manipulation 199 200 If the client reduces an authentication decision to a simple Boolean, test changing `false` to `true` as well as the status/body variants below. A secure server must enforce the decision independently of the client response.<sup>[[2]](#references)</sup> 201 202 1. **Code Manipulation**: The status code is altered to `200 OK`. 203 2. **Code and Body Manipulation**: 204 - The status code is changed to `200 OK`. 205 - The response body is modified to `{"success":true}` or an empty object `{}`. 206 207 These manipulation techniques are effective in scenarios where JSON is utilized for data transmission and receipt.<sup>[[2]](#references)</sup> 208 209 ## Change email of current session 210 211 One disclosed workflow behaved as follows:<sup>[[3]](#references)</sup> 212 213 - The attacker requests an email change to an address they control. 214 - The attacker receives the email-change confirmation link. 215 - The attacker sends that link to the victim and convinces them to open it. 216 - The victim's authenticated session confirms the attacker's chosen email. 217 - The attacker resets the password and takes over the account. 218 219 220 ### Bypass email verification for Account Takeover 221 - The attacker logs in as `attacker@test.com` and verifies that email during signup. 222 - Attacker changes verified email to victim@test.com (no secondary verification on email change) 223 - Now the website allows victim@test.com to login and we have bypassed email verification of victim user. 224 225 ### Old Cookies 226 227 In one disclosed case, it was possible to log in, save the authenticated cookies, log out, and then log in again. Although the second login generated different cookies, the earlier cookies became valid again.<sup>[[11]](#references)</sup> 228 229 ### Trusted device cookies + batch API leakage 230 231 *Long-lived device identifiers that gate recovery can be stolen when a batch API lets you copy unreadable subresponses into writable sinks.*<sup>[[5]](#references)</sup> 232 233 - Identify a **trusted-device cookie** (`SameSite=None`, long-lived) used to relax recovery checks. 234 - Find a **first-party endpoint** that returns that device ID in JSON (e.g., an OAuth `code` exchange returning `machine_id`) but is not readable cross-origin. 235 - Use a **batch/chained API** that allows referencing earlier subresponses (`{result=name:$.path}`) and writing them to an attacker-visible sink (page post, upload-by-URL, etc.). Example with Facebook Graph API: 236 237 ```http 238 POST https://graph.facebook.com/ 239 batch=[ 240 {"method":"post","omit_response_on_success":0,"relative_url":"/oauth/access_token?client_id=APP_ID%26redirect_uri=REDIRECT_URI","body":"code=SINGLE_USE_CODE","name":"leaker"}, 241 {"method":"post","relative_url":"PAGE_ID/posts","body":"message={result=leaker:$.machine_id}"} 242 ] 243 access_token=PAGE_ACCESS_TOKEN&method=post 244 ``` 245 246 - Load the batch URL in a hidden `<iframe>` so the victim sends the trusted-device cookie; the JSON-path reference copies `machine_id` into the attacker-controlled post even though the OAuth response is unreadable to the page. 247 - Replay: set the stolen device cookie in a new session. Recovery now treats the browser as trusted, often exposing weaker “no email/phone” flows (e.g., automated document upload) to add an attacker email without the password or 2FA. 248 249 ## References 250 251 - [1] [Turning a harmless XSS behind a WAF into a realistic phishing vector](https://blog.hackcommander.com/posts/2025/12/28/turning-a-harmless-xss-behind-a-waf-into-a-realistic-phishing-vector/) 252 - [2] [Firing 8 Account Takeover Methods](https://infosecwriteups.com/firing-8-account-takeover-methods-77e892099050) 253 - [3] [One-click account take over](https://dynnyd20.medium.com/one-click-account-take-over-e500929656ea) 254 - [4] [0xdf – HTB Era: security-question IDOR & username oracle](https://0xdf.gitlab.io/2025/11/29/htb-era.html) 255 - [5] [Steal DATR Cookie](https://ysamm.com/uncategorized/2026/01/15/steal-dtsg-cookie.html) 256 - [6] [Dfns - The Magic Link Vulnerability](https://www.dfns.co/article/the-magic-link-vulnerability) 257 - [7] [USENIX Security 2025 - Demystifying the (In)Security of QR Code-based Login in Real-world Deployments](https://www.usenix.org/conference/usenixsecurity25/presentation/zhang-xin) 258 - [8] [Bishop Fox - A Millisecond of Predictability: Why CVE-2026-11374 Is Hard to Exploit](https://bishopfox.com/blog/millisecond-of-predictability-why-cve-2026-11374-hard-to-exploit) 259 - [9] [Bishop Fox - CVE-2026-11374 detection tool](https://github.com/BishopFox/CVE-2026-11374-check) 260 - [10] [Till Recollapse: Fuzzing the Web for Mysterious Vulnerabilities - Andre Baptista](https://www.youtube.com/watch?v=CiIyaZ3x49c) 261 - [11] [Uncovering the hidden vulnerability: how I found an authentication bypass on Shopify's Exchange](https://medium.com/@niraj1mahajan/uncovering-the-hidden-vulnerability-how-i-found-an-authentication-bypass-on-shopifys-exchange-cc2729ea31a9)