- by x32x01 ||
I usually do not like posting duplicate reports, but this one honestly frustrated me more than most 😅
So grab your coffee ☕ and let’s break down how a chain of security issues inside an Android mobile application turned into a complete Full Account Takeover.
The vulnerability was caused by multiple problems in the app’s implementation of OAuth Authorization Code Flow. Because of these issues, an attacker could steal the victim’s Access Token and Refresh Token, leading to full control over the account.
It was a combination of several weak security decisions that worked together.
The authorization request did not include:
This meant the authorization code was not tied to the legitimate application.
But what exactly is PKCE? 🤔
PKCE (Proof Key for Code Exchange) is an extra security layer designed for mobile applications and public OAuth clients.
The process works like this:
This ensures that the same application that started the login process is the one requesting the tokens.
Why does this matter? 👇
Even if an attacker steals the authorization code, they still cannot exchange it without the correct code_verifier.
But in this case, PKCE was completely missing.
That meant anyone who intercepted the authorization code could immediately exchange it for:
And that opened the door to account compromise.
The OAuth client_secret was stored directly inside the APK file.
After reversing the application, finding it was surprisingly easy.
This is a major security mistake because mobile apps are public clients.
Any secret stored inside a mobile application can eventually be extracted using techniques such as:
After unpacking the application, it was possible to recover:
And that made the attack much easier.
The application used a redirect format similar to:
At first glance, this may look normal.
But there is a serious security problem here.
Any Android application can register the same custom URI scheme.
That means a malicious application can intercept the OAuth callback.
The original application also exposed an Activity that accepted external interactions through Android Intents, making interception even easier.
That application registers the same OAuth Redirect Scheme used by the legitimate app.
After login, Android displays the familiar:
selection prompt.
At this point, the attacker-controlled app receives:
The attacker performs the OAuth token exchange.
The server returns:
They now have:
Missing PKCE, exposing a Client Secret inside the APK, and using an insecure Redirect URI design were enough to achieve Full Account Takeover.
Hopefully the next report will not be a duplicate 😅
So grab your coffee ☕ and let’s break down how a chain of security issues inside an Android mobile application turned into a complete Full Account Takeover.
The vulnerability was caused by multiple problems in the app’s implementation of OAuth Authorization Code Flow. Because of these issues, an attacker could steal the victim’s Access Token and Refresh Token, leading to full control over the account.
Root Causes Behind the OAuth Security Issue
This was not a single bug.It was a combination of several weak security decisions that worked together.
Missing PKCE in OAuth Authorization Code Flow
The first major issue was that the application used OAuth Authorization Code Flow without implementing PKCE.The authorization request did not include:
Code:
code_challenge
code_verifier But what exactly is PKCE? 🤔
PKCE (Proof Key for Code Exchange) is an extra security layer designed for mobile applications and public OAuth clients.
The process works like this:
- The application generates a random value called:
code_verifier
- It creates another value from it:
code_challenge
- The app sends the
code_challengeduring authentication. - After the user logs in, the authorization server returns an authorization code.
- The app must then provide the original code_verifier to verify its identity.
Code:
code_verifier = random_secret_value
code_challenge = SHA256(code_verifier) Why does this matter? 👇
Even if an attacker steals the authorization code, they still cannot exchange it without the correct code_verifier.
But in this case, PKCE was completely missing.
That meant anyone who intercepted the authorization code could immediately exchange it for:
Code:
access_token
refresh_token Hardcoded Client Secret Inside the APK 😬
The second problem was equally serious.The OAuth client_secret was stored directly inside the APK file.
After reversing the application, finding it was surprisingly easy.
This is a major security mistake because mobile apps are public clients.
Any secret stored inside a mobile application can eventually be extracted using techniques such as:
- Reverse engineering
- APK decompilation
- Static analysis
Code:
apktool d app.apk
jadx app.apk Code:
client_id
client_secret Insecure Custom URI Scheme Usage ⚠️
The third issue involved the OAuth Redirect URI configuration.The application used a redirect format similar to:
Code:
[REDACTED]://oauth-callback But there is a serious security problem here.
Any Android application can register the same custom URI scheme.
That means a malicious application can intercept the OAuth callback.
The original application also exposed an Activity that accepted external interactions through Android Intents, making interception even easier.
Full Exploitation Scenario Step by Step 🎯
Here is how the attack worked in practice.Step 1: Victim Installs a Malicious Application
The victim installs a malicious Android application.That application registers the same OAuth Redirect Scheme used by the legitimate app.
Step 2: Victim Starts the Login Process
The victim opens the original application and starts authentication.After login, Android displays the familiar:
Open withselection prompt.
Step 3: Victim Selects the Malicious App
The victim accidentally chooses the malicious application.At this point, the attacker-controlled app receives:
Authorization CodeStep 4: Token Exchange Begins
Using the values extracted earlier from the APK: Code:
client_id
client_secret
authorization_code The server returns:
Code:
access_token
refresh_token Final Result 🚨
Once the attacker obtains the tokens, the impact becomes severe.They now have:
✔️ Access to the victim’s account
✔️ Session persistence through the Refresh Token
✔️ Complete control over account activity
The final outcome ? Full Account Takeover✔️ Session persistence through the Refresh Token
✔️ Complete control over account activity
How to Prevent OAuth Vulnerabilities in Android Apps
If you build Android apps or work in application security, these security practices are critical:✅ Always enable PKCE with Authorization Code Flow.
✅ Never store client_secret inside mobile applications.
✅ Use HTTPS App Links instead of insecure Custom URI Schemes whenever possible.
✅ Restrict exported Activities and secure Android Intents properly.
✅ Regularly audit OAuth authentication flows during security testing.
✅ Never store client_secret inside mobile applications.
✅ Use HTTPS App Links instead of insecure Custom URI Schemes whenever possible.
✅ Restrict exported Activities and secure Android Intents properly.
✅ Regularly audit OAuth authentication flows during security testing.
Final Thoughts
This case shows how several small OAuth security mistakes can combine into a critical compromise.Missing PKCE, exposing a Client Secret inside the APK, and using an insecure Redirect URI design were enough to achieve Full Account Takeover.
Hopefully the next report will not be a duplicate 😅