Header Injection Leading to Full Account Takeover
During a recent mobile application VAPT, I encountered an interesting account takeover vulnerability that started from header bruteforcing.
The application initially appeared quite secure. Root detection was heavily implemented; common Frida bypass scripts failed and SSL pinning was enabled. Before I could even begin proper API testing, I had to spend significant time bypassing multiple client-side protections.
After decompiling the APK and analyzing the application logic, I identified several custom root detection and anti-Frida checks. I wrote custom hooks to bypass them and combined those with an SSL pinning bypass to intercept the application traffic successfully.
At that point, the real testing began.
The Header Injection Discovery
While testing authorization controls, I started bruteforcing header names to identify whether the backend trusted any client-supplied headers.
I selected an authorized endpoint (transaction history) and began bruteforcing header names. I was not bruteforcing the header value itself. Instead, I used another user's phone number as a static header value and only bruteforced the header name.
At one point, one particular header (x-msisdn) immediately stood out because the response behavior changed completely. Instead of returning my own transaction history, the API responded with records belonging to the user whose phone number I supplied in the header value.
That was the turning point. The application used phone numbers as a primary identifier for authorization. After identifying the trusted header, I replaced the value with different users' phone numbers and started testing additional endpoints.
Multiple endpoints trusted the supplied header value completely and returned the victim user's data.
I was able to access:
- Transaction history
- Account details
- Beneficiaries
- Other authorization-sensitive responses
More critically, I was also able to perform actions on behalf of the victim user, including sending money from the affected account.
The impact was severe. By controlling a single header, I was effectively able to act as arbitrary users within the application.
No OTP bypass, session hijacking, or credential compromise was required. The backend simply trusted the client-supplied header without validating whether it actually belonged to the authenticated user.
The vulnerability effectively allowed full account takeover of any user whose phone number was known.
The Interesting Part
What made this finding particularly interesting was the contrast between the frontend and backend security posture.
The mobile application invested significant effort into:
- Root detection
- Frida detection
- SSL pinning
- Anti-tampering protections
Yet a single trusted client-controlled header was enough to bypass authorization controls completely.
The client-side protections definitely increased testing complexity and slowed down analysis, but the critical issue ultimately existed in the server-side authorization logic.
Final Thoughts
This assessment was a strong reminder that client-side protections alone cannot secure an application.
Root detection, SSL pinning, and anti-tampering controls may slow down attackers and testers, but authorization must always be enforced securely on the server side.
Identity should never rely on client-controlled headers unless they are injected and validated by a trusted upstream component.