Skip to content
Open
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
25 changes: 25 additions & 0 deletions src/pentesting-web/oauth-to-account-takeover.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,28 @@ The core guarantee of the Authorization Code grant is that **access tokens never

Any of these findings usually upgrades otherwise “low” bugs (like a CSP bypass or DOM XSS) into full API takeover because the attacker can simply read and replay the leaked bearer token.

### Frontend-only SSO gates: MSAL/OAuth login spoofing, `localStorage` identity injection, and pre-auth session bootstrap

Some SPAs use **MSAL/OIDC only as a client-side route guard**: the bundle checks `getAllAccounts()` (or equivalent), writes identity fields into `localStorage`, and renders the “private” UI. If the backend **doesn't validate the bearer token server-side** on every API call, patching the JavaScript is enough to expose protected routes and prove missing authorization.

Practical workflow during testing:

1. **Download the JS bundle before/around the SSO redirect**. Even when the browser immediately jumps to Microsoft login, React/Next/Vue assets often load first and disclose hidden routes, API names, storage keys, role strings, and session bootstrap endpoints.
2. **Patch the account-check logic locally** so the SPA believes one user is signed in (e.g. force the MSAL account lookup to return a non-empty list or short-circuit the redirect branch). This should only unlock client rendering; it must not grant server data by itself.
3. **Replay the underlying APIs without the real token**: remove the `Authorization` header, replace it with garbage, or call the endpoint directly outside the browser. If responses still succeed, the backend is not enforcing bearer-token validation.
4. **Treat browser storage as attacker-controlled**. If the app stores `username`, employee IDs, tenant/company IDs, `role`, `isAdmin`, or similar values in `localStorage`/`sessionStorage`, overwrite them with another valid user's values and reload. Any privilege change means the server is trusting client-supplied identity state.
5. **Inspect session bootstrap code**. A common follow-on bug is an unauthenticated `GET` that returns a session GUID / opaque session ID plus an expiry timestamp. If dropping those values into storage is enough to “complete” login, the session is being minted pre-auth and is not bound server-side to the authenticated identity.
6. **Check for static secrets shipped to the browser** such as `x-api-key`, AWS API Gateway keys, or encrypted constants that the same bundle later decrypts. These values are **public** once delivered to the client and cannot prove who the user is.

High-signal indicators:

- Sensitive APIs work with **no bearer token**, a **tampered bearer token**, or only a **browser-exposed static API key**.
- The SPA derives identity from `localStorage` and the API accepts those values as truth.
- Session creation happens through an **unauthenticated bootstrap endpoint** that returns a reusable GUID/opaque token.
- “Client-side encryption” is used to hide API keys, usernames, or session material inside the bundle. If the browser can decrypt it, the attacker can too.

For Microsoft Entra / MSAL-backed APIs, the resource server must validate at least the **signature**, **issuer**, **audience**, **expiration**, and then enforce the expected **scopes / app roles / tenant authorization** before returning any sensitive data.

### Everlasting Authorization Code

Authorization codes must be **short-lived, single-use, and replay-aware**. When assessing a flow, capture a `code` and:
Expand Down Expand Up @@ -428,6 +450,9 @@ In mobile OAuth implementations, apps use **custom URI schemes** to receive redi
- [Rapid7: CVE-2026-31381, CVE-2026-31382: Gainsight Assist Information Disclosure and Cross-Site Scripting (FIXED)](https://www.rapid7.com/blog/post/ve-cve-2026-31381-cve-2026-31382-gainsight-assist-information-disclosure-xss-fixed)
- [MDN: Window `pagereveal` event](https://developer.mozilla.org/en-US/docs/Web/API/Window/pagereveal_event)
- [How I Found a Critical OAuth Misconfiguration That Led to Account Takeover](https://medium.com/@iamshafayat/how-i-found-a-critical-oauth-misconfiguration-that-led-to-account-takeover-abfec43eaea6)
- [Exploiting vulnerabilities in Johnson & Johnson web apps](https://eaton-works.com/2026/06/24/jnj-webapp-hacks/)
- [Access tokens in the Microsoft identity platform](https://learn.microsoft.com/en-us/entra/identity-platform/access-tokens)
- [Protected web API: Verify scopes and app roles](https://learn.microsoft.com/en-us/entra/identity-platform/scenario-protected-web-api-verification-scope-app-roles)


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