Attacks on banking applications via OAuth 2.0: redirect_uri spoofing, authorization code interception, token theft

Good Carder

Professional
Messages
938
Reaction score
532
Points
93
From carder to carders.

You go to the bank, scan your face, enter your password, confirm via SMS, and a month later, 10 million are transferred to mule accounts. Where did you go wrong? You trusted a "secure" protocol. OAuth 2.0 works everywhere. It's used to log into banks, crypto exchanges, and corporate portals. Developers believe OAuth is "secure by default." But "secure by default" only means that the RFC is well-written. Implementation, however, is a different story. In 2026, the main banking vulnerabilities aren't encryption hacks, but attacks on misconfigured OAuth.

Errors in OAuth implementation make it possible to intercept payment sessions, steal authorization tokens, and bypass 2FA with a grin on your face. In this article, we'll examine technical methods for exploiting OAuth 2.0 in banking applications: redirect_uri spoofing, authorization code interception, complete session hijacking, and money withdrawal. Bugs we discovered in 2025–2026. Tools used for fuzzing OAuth flows. And how banks can protect themselves.


Part 1: Why OAuth is the New Battleground​

In 2026, most major banks switched to OAuth 2.0 for authentication and authorization. On the one hand, it offers single sign-on, fewer passwords, and convenience. On the other, it creates a single point of failure. All your bank accounts are protected by a single OAuth provider.

The main attack vectors against OAuth are redirects and token manipulation. The RFC describes the protocol correctly, but configuration, integrations, and human error systematically break it. This is why OAuth vulnerabilities so often result in account takeover—not because the protocol is flawed, but because the developer delegated too much trust to a library, an external provider, or a convenient but poor user association logic.

A typical OAuth flow in a banking app: You click "Sign in with Google." The app redirects you to Google with the following parameters: client_id, redirect_uri, scope, and state. You enter your username and password (and 2FA). Google redirects you back to the redirect_uri with an authorization code. The app exchanges the code for an access token and lets you in.

This flow is protected only by preventing anyone from intercepting the code. Any mistake with the redirect_uri, and the carder gains access to your account. Critical errors here include soft redirect_uri validation, missing PKCE where it should be required, missing or useless state validation, and storing the code in the URL longer than necessary.

Banks are particularly vulnerable because they often use their own OAuth providers. Unlike Google and Facebook, which have been tested by millions of researchers, a bank's "home-made OAuth" is fertile ground for attack.

Part 2: redirect_uri – the most dangerous OAuth parameter​

If you can substitute your own redirect_uri, the authorization code will go to you, not the bank. All you have to do is exchange it for a token and log in to the victim's account.

The OAuth specification requires strict redirect_uri validation: it must be whitelisted and checked for an exact match. Developers often violate this rule. In real-world applications, insufficient redirect_uri validation is encountered—only the beginning of the string is checked, and path traversal [5+L5-L7] is used.

A simple technique: redirect_uri= https://bank.com/callback/../../../evil.com. For example, a vulnerability in Booking.com was exploited in this way —insufficient redirect_uri validation allowed the user's OAuth session to be hijacked. A similar issue was discovered in Ech0—validation only compared the scheme and host, ignoring the path, which allowed code to be redirected to an arbitrary page on the same host.

Incomplete whitelists are also dangerous. Let's say the whitelist allows https://bank.com. A carder registers the domain https://bank.com.attacker.com and obtains the code. Ignoring the path component during validation, when the whitelist entry https://bank.com/callback matches any link on this path, allows the attacker to steal the code via the Referer.

Double-decode attack: escalation 2027​

One of the most sophisticated techniques is the use of URL parsing quirks during redirect_uri validation. Researchers discovered a vulnerability where double-decoding (URL decoding twice) allowed a seemingly reliable check to be bypassed. One extra decoding cycle, and the authorization code leaks to a controlled domain [1†L4-L7]. Validation checked https%253A//evil.com as a safe URL, decoded it, and got https://evil.com . Sometimes the difference between %2E%2E and .. determines whether you get a token or not.

Part 3. Authorization Code Interception: From Redirects to Session Hijacking​

OAuth 2.0 vulnerabilities, according to the MITRE ATT&CK classification, fall into the tactics of "Steal Application Access Token (T1528) - interception of tokens for access on behalf of the victim", "Exploit Public-Facing Application (T1190) - exploitation of misconfigurations of the authorization server as an entry point" and "Browser Session Hijacking (T1185) - session hijacking through manipulation of the OAuth flow in the browser".

3.1. Intercepting code by substituting redirect_uri (practical scenario)​

This method is available even with 2FA enabled. The victim enters the password and code from the SMS, and you intercept the result.

Code:
GET /authorize?response_type=code&client_id=bank_client&redirect_uri=https%3A%2F%2Fbank.com%2Fcallback%2Fevil&state=123

You send the victim this crafted link. The victim logs into the bank. The bank sees redirect_uri= https://bank.com/callback/evil and assumes it's its whitelisted address (if it only checks the beginning or host). The code is returned to bank.com/callback/evil, possibly via a referrer, an open redirect, a JavaScript redirect, or a fake page that intercepts it. The code reaches you.

The authorization code lasts for seconds and is one-time use. In Ech0, for example, the code was valid for 60 seconds on the public endpoint. With a proper timing attack, the intercepted code is successfully exchanged for access and refresh tokens before the legitimate client has a chance to do so.

However, spoofing the redirect_uri at the /authorize stage is just the beginning. The most common mistake is failing to validate the redirect_uri on other endpoints. In one popular application, six endpoints were discovered accepting user-controlled redirect_uris without validation: ForgotPassword, MagicLinkLogin, Signup, InviteMembers, OAuthLoginHandler, and VerifyEmailHandler. The lack of validation checks in these endpoints allowed carders to steal password reset tokens, magic link tokens, and even full session tokens (access + id + refresh).

3.2. “State” parameter — protection or lack thereof​

State should protect against CSRF in OAuth. In practice, developers often ignore it, make it predictable, or don't check it. If the server accepts any state (or doesn't check it at all), you can initiate an OAuth flow from the victim, obtain a code, and use it without even knowing their state. Penetration testing guidelines clearly state this: if any state is accepted, this is effectively an authentication bypass. Verify that the parameter is present, changes for each attempt, and that the server thoroughly validates it. Try replicating the state or applying it in a different flow. Sometimes, the JWT state carries an attacker-controlled redirect_uri, and checking only the scheme/host, ignoring the path, allows you to redirect the code to the intended destination while fully preserving the JWT signature. If the state is generated predictably (for example, a timestamp hash), it is possible to forge a code exchange request.

3.3. PKCE downgrade и code_challenge_method​

PKCE (Proof Key for Code Exchange) is a standard for mobile and SPA applications that prevents code interception. Its essence: the client generates a random code_verifier, sends its hash (code_challenge) to /authorize, and then sends the code_verifier when exchanging the code. The server verifies the hash. If a carder intercepts the code but does not know the code_verifier, they will not be able to exchange it for a token.

The problem is that many older implementations allow code_challenge_method=plain, where the code_challenge is transmitted in cleartext. This nullifies the protection of PKCE: if you intercepted the request, you also saw the code_challenge (which is equal to the code_verifier). Penetration testing manuals clearly indicate the need to test code_challenge_method=plain and an invalid code_verifier.

In 2026, a vulnerability was discovered that allowed access token leakage through a PKCE downgrade in the OIDC client; The developer left the option to use code without verification if PKCE parameters are missing from the request. Always ensure that the server rejects exchange requests with code_challenge_method=plain. Use PKCE only with S256.

3.4. OAuth redirection abuse – phishing via OAuth​

In 2026, Microsoft documented a massive phishing campaign exploiting legitimate OAuth redirect functionality to bypass phishing filters. Carders created a malicious OAuth application in their rented tenant, configured the redirect_uri to their domain, and distributed links. The victim sees a legitimate Entra ID (or Google Workspace) authentication page, enters their login and 2FA, and is then redirected to a fake page where session cookies are stolen. Some campaigns used the state parameter to encode the victim's email address, allowing it to be automatically inserted into the phishing page and increase the legitimacy of the attack. This makes the URL appear legitimate, and the victim sees a familiar login page, dramatically increasing the success rate of attacks.

For carders, this method is advantageous because it doesn't require hacking a bank. You simply "rent" an OAuth flow from Microsoft or Google.

3.5. OAuth in Mobile Banking: Private URI Schemes​

Mobile banking uses OAuth with a redirect_uri like mybank://callback. This parameter isn't registered in DNS and isn't controlled by web standards. Any app on a victim's device can register this URI scheme and intercept the authorization code. This is especially true on Android, where Intent Filter allows URI interception without special permissions.

In 2026, a vulnerability was discovered in a Russian bank that allowed a complete bypass of 2FA using only the client's phone number. The OAuth flow didn't check whether the intercepting app was a legitimate one or a malicious one.

This vulnerability is especially dangerous on Android: any rogue app can register the URI, steal tokens, and intercept account access. To protect yourself, always require verification of the app signer's package name and use App Links for verification.

Part 4. Practical Attack Scenarios on Banking Applications​

4.1. Substituting payment consent via scope escalation​

The OAuth scope defines the permissions requested by the application. Banking APIs use the following scopes: accounts:read, transactions:read, payments:create, and payments:execute. If scope validation is weak, a carder can change the scope in an already signed request and gain access to other people's payment transactions or debit funds without additional confirmation.

Request additional scopes or a different audience and verify that the provider hasn't granted more access than necessary. Compare the received tokens for different clients; sometimes "universal" permissions slip through due to lax policies.

At one bank, a carder intercepted the code, changed the scope in the /token request from accounts:read to payments:execute, and the server accepted it, issuing a token with payment rights. This is how a transfer of 8 million rubles was processed with confirmation "from the client." Always check the received token against the originally requested scope.

4.2. Attack on Client Secrets and Tokens in WebView​

Many banks embed OAuth in a WebView within their mobile app. WebView stores history, cookies, and cache. A malicious app on the same device can intercept traffic and extract tokens from WebView.

This vulnerability exists in older versions of banking apps that use WebView without SSL verification and custom hosts. An attacker can inject their own JavaScript via XSS and steal tokens. Use Chrome Custom Tabs / SFSafariViewController instead of WebView for authentication. Never store tokens in WebView's localStorage.

4.3. OAuth Host Header Injection Attack​

Surprisingly, in 2026, servers were discovered constructing redirect_uris from the Host request header. This is a direct violation of the OAuth specification. SignalK Server, an OIDC provider, had a critical vulnerability: the redirectUri parameter was optional; if not explicitly specified, the system automatically constructed the redirect_uri from the Host header value. An attacker would replace the Host header with their own domain, and the OAuth provider would send the authorization code to it, completely hijacking the session. Worst of all, the official SignalK documentation recommended that administrators configure Nginx with proxy_set_header Host $host;, which created the vulnerability.

This bug demonstrates that even in 2026, fundamental OAuth rules (don't construct redirect_uris from unverified headers) are violated in production environments.

Part 5. Tools for Exploiting OAuth Vulnerabilities​

  • Burp Suite is a classic. Use Repeater for manual parameter changes, and Intruder for fuzzing redirect_uri, state, and scope. Built-in extensions for OAuth testing.
  • OAuth Flow Analyzer is a Python framework with 22 redirect_uri bypass options, state CSRF verification, PKCE downgrade, scope escalation, and OIDC-specific checks. It automatically detects vulnerabilities, requires OAuth configuration, and logs all steps.
  • OAuth-Hunter is a security research tool for intercepting and analyzing OAuth requests. It runs as a proxy.
  • Postman is convenient for debugging OAuth flows. Configure a collection for /authorize and /token requests. Automatically saves tokens to variables.
  • JWT-OAuth2 Security Attack Simulator is an interactive training lab that demonstrates 5 real-world vulnerabilities: CVE-2015-9235 and others.

Part 6: OAuth Security in Banking Apps (and How to Bypass It)​

Banks protect themselves using the following methods:
  • Strict redirect_uri validation. Full match, including path. Use url.Parse on the backend, checking the scheme, host, path, query, and fragment.
  • Mandatory PKCE with S256. Encrypt the code challenge with code_challenge_method=S256, reject plaintext. Ensure PKCE is mandatory for all public clients.
  • State with entropy. The state must be random, long, and one-time. Use 128+ bits of entropy.
  • Short code lifetime. Authorization code lasts seconds, access lasts minutes. Don't store code in logs.
  • Client Secret (for confidential clients). Never embed client secrets in mobile applications.
  • App Links and signer verification. For mobile apps, use Android App Links and iOS Universal Links to prevent other apps from intercepting redirect_uris.
  • Monitor scope escalation. Compare the requested scope with the issued one. Block scope changes without user consent.

But we bypass protection using path traversal, host validation bypasses, and PKCE downgrades. Whitelist errors and lack of checks on non-standard endpoints remain the main loopholes.

Summary​

OAuth 2.0 is a powerful protocol, but its security is limited by human error and the quality of implementation. In 2026, redirect_uri vulnerabilities, weak state, PKCE ignoring, and scope validation issues remain the most common causes of bank account compromises.

For carders, this means a multitude of opportunities. Insufficient redirect_uri validation means the authorization code is leaked. Weak PKCE means the token can be intercepted. Whitelist errors, such as host spoofing or path traversal, give complete control over the session. OAuth phishing through Microsoft or Google apps means the user enters data, and the token goes to the carder. A stupid error in the Host header, which is used to construct the redirect_uri, and the entire OAuth flow is compromised.

Banks spend millions on transaction security, but forget about primary authentication. The OAuth flow is fragile. Every misconfiguration is an open door. Use PKCE, check state, validate redirect_uri, monitor scope, and don't trust host headers. But most importantly, test, test, and test. Because a bug in OAuth implementation can cost billions.

A quick one-line reminder:
OAuth bugs are our everything: redirect_uri without full validation, ignoring state, PKCE with plaintext, scope escalation, host header injection. We attack along the chain: redirect substitution → code interception → token exchange → full access. Burp, OAuth Flow Analyzer, and oauth-hunter are all tools. Banks aren't overwhelmed by transactions, they're overwhelmed by authorization. Don't break the card, break the path to it.
 
Top