Mobile API IDOR: Hunting Object Access Bugs Beyond the UI
Mobile apps hide parameters behind pretty screens. The API does not. Most mobile IDORs I file never appear as a button — they appear as /v2/users/{uuid}/orders called from a Flutter or React Native client with a numeric or UUID object ID the server never authorizes.
Think BOLA on a JSON API that happens to be consumed by iOS/Android. OWASP Mobile risks around insecure auth and CWE-639 (authorization bypass) frame the issue for triage.
Setup that actually works
- Install the app on a test device/emulator you control.
- Trust your proxy CA; intercept HTTPS (bypass SSL pinning only if in scope and allowed — many programs forbid pinning bypass; use a non-pinned build or traffic the program provides).
- Log in as User A and User B; save both token headers.
- Exercise profile, messages, payments, attachments, and “share link” flows so the history fills.
If pinning blocks you and bypass is out of scope, shift to exported deep links and any webviews — sometimes the same API is reachable from a mobile web host.
IDOR patterns mobile backends love
- Sequential invoice IDs in download endpoints
- UUID resources shared across tenants with only “know the ID” checks
- GraphQL
node(id:)or Relay global IDs copied from one session into another - Image/CDN URLs signed poorly — swap the object path, keep a static signature
- Push-notification unregister or device-token APIs that accept another user’s
userId
Change one identifier per request. Keep User A’s Authorization header while inserting User B’s object IDs.
Evidence triagers like
Side-by-side: User A token + User B orderId → response body containing User B PII. Redact payloads in public writeups. State platform (iOS/Android), app version, and API host.
Impact scales with data sensitivity: messages and medical records hit harder than “public” profile fields the app already shows.
Fixes to recommend
Server-side ownership checks on every object read/write; no trust of client-supplied user_id; short-lived signed URLs bound to the object and requester; consistent 404 on unauthorized access to avoid oracle leaks.
I almost never “test IDOR in the app UI” alone. The UI lies; the mobile API tells the truth.