Attack Chain¶
Overview¶
This section documents the complete end-to-end attack path — from an APK pulled off a device to full admin access on the backend — by chaining every finding across the previous sections into a single coherent narrative.
No single finding here produces meaningful impact in isolation. The hardcoded x-admin-token
is useless without knowing the endpoint exists. The IDOR is limited to read access without
privilege escalation. Privilege escalation requires a valid account, which requires getting
past the client-side protections first. The value is in how the findings connect.
Attack Flow¶
APK Extraction & Static Analysis
↓
Backend URL, SSL fingerprint, x-admin-token, protection call chain — all extracted
from the binary before any network request is made
↓
Root Detection Bypass (Frida)
↓
App runs on rooted emulator; JWT readable directly from SharedPreferences
↓
SSL Pinning Bypass (libflutter.so patch)
↓
Full HTTPS visibility; every API request interceptable and modifiable
↓
API Recon & Enumeration
↓
Full endpoint map via dynamic capture + static analysis + fuzzing;
x-admin-token abused to switch backend to development mode;
Swagger UI exposed
↓
IDOR — GET /todos/{id}
↓
Any authenticated user can read any todo by ID;
sequential IDs enable full dataset enumeration
↓
Privilege Escalation — PUT /users/{id}
↓
Regular user self-promotes to admin via single PUT request;
admin features confirmed accessible in mobile app
↓
Full Compromise
What "Full Compromise" Actually Means Here¶
It is worth being precise about what the chain achieves and what it does not.
The attacker ends the chain with an admin account, full read access to every user's todos, and the ability to switch the backend between production and development mode. In a real application with this architecture, admin access typically means visibility into all user data, the ability to delete or modify any account, and access to any privileged function the backend exposes. That is significant.
What this lab does not demonstrate: lateral movement beyond the application boundary, server exploitation, or data exfiltration at scale. The backend itself is not compromised — the database is not directly accessible, and the application server is not exploited at the OS level. The compromise is entirely within the application's own authorization model.
That framing matters because it reflects how these vulnerabilities would be reported in a real engagement. IDOR on a todo app reads differently to a client than IDOR on a healthcare platform or a financial service. The vulnerabilities here are real and the chain is coherent — but impact severity always depends on what the data is and what the admin role actually controls in the target application.
Two Paths to the Same Outcome¶
One thing worth noting about this attack surface: the bypass methodology — reverse engineering
the APK, patching libflutter.so, hooking Frida offsets — is impressive technically but not
actually required to reach the highest-impact findings.
A malicious legitimate user who just registers an account and intercepts their own traffic can:
- Hit
GET /todos/{id}with arbitrary IDs and read other users' data - Send
PUT /users/{own-id}with"role": "admin"and self-promote - Use the admin role to access privileged endpoints
Neither finding requires reverse engineering. Neither requires bypassing SSL pinning. They exist independently of any client-side protection.
This is the more important security conclusion from this lab. The client-side protections — root detection, SSL pinning — add friction for an external attacker starting from just the APK. But they do nothing to protect against a motivated user who already has a valid account. The authorization failures are backend problems. Fixing the client-side protections without fixing the backend changes the difficulty of the attack for one threat model while leaving the other completely unaffected.