Imported from abisheikM1/Tribunal (
skills/api-pivot/SKILL.md). Install upstream withnpx skills add abisheikM1/Tribunal --skill api-pivot. Copyright stays with the author.
api-pivot — server-side found through the app (catalog §12)
Knowledge module the pipeline consults. Owns catalog §12 Server-side entirely, plus the
"Auth logic gated client-side only" row of §4 and "Push/FCM abuse" row of §8. This is a
rubric + static seed module, not the replay engine — the dynamic Burp-replay workflow (send
modified requests, save evidence, emit api_findings.json) lives in the sibling pipeline skill
api-vuln-test. Consult this module for what to test and how; consult that one for how the
pipeline records it. On most programs the app itself is thin — the server behind it is where
severity and payout live. A client-side "this button is hidden" finding is often informational; the
same gap enforced only in the app and not on the API is a High.
1. SCOPE GATE (authorized testing only) — do this first
Server-side testing is still testing someone else's infrastructure — treat it at least as seriously as testing the app itself.
python scripts/scope_gate.py --hash <sha256> # exit 3 = REFUSED
- API hosts are sometimes scoped separately from the mobile app on a bug-bounty program —
confirm every host you're about to hit (
api.example.com,internal-staging.example.com, a GraphQL endpoint) is explicitly in scope before sending a single modified request. - Replay only against accounts you control (your own "Account A" / "Account B" test users) and in-scope hosts. Never touch another real user's data — an IDOR is proven the moment you can read/modify Account B's object as Account A; stop there, don't go further.
- No destructive payloads, no mass-exploitation scripts, no automated brute force beyond a small, clearly-bounded rate-limit probe. This module ships methodology and a static seed script — never a weaponized replay/attack tool.
2. What this class is, when to use it, what it consumes
The mobile app is a client to a web API (REST/GraphQL). Every business rule the client "enforces" — auth, ownership, plan/tier gating, quantity limits — is only real if the server also enforces it. This class is about testing that server, using the app to find and authenticate to the surface:
- IDOR/BOLA — object refs (
/users/{id},?account=, UUIDs) not re-checked against the caller's identity. - Broken authentication/session — weak tokens, no expiry, session fixation, JWT trust issues.
- Broken access control / BFLA — admin or privileged routes reachable by a normal-tier caller.
- Business logic flaws — abuse of the app's specific multi-step flow (skip a step, replay a one-time action, race a limited resource).
- Missing rate limiting — brute-forceable OTP/login/coupon/referral endpoints.
- Mass assignment — extra JSON fields accepted and applied (
isAdmin,role,price). - Backend injection — SQLi/NoSQLi/command injection reachable via app-originated params.
- XXE — the API parses attacker-supplied XML with external entities enabled.
- SSRF (server-side) — a URL/host param the app supplies is fetched server-side.
- GraphQL abuse — introspection left on in prod, batching abuse, missing field-level authz.
- JWT flaws —
alg:none, unsigned acceptance, weak/guessable/reused HMAC secret,kidinjection. - Insecure file upload — type/path/size validation bypassable via the app's upload flow.
- Auth logic gated client-side only (§4) — a check exists only in Kotlin/Java, never on the API.
- Push/FCM abuse (§8) — spoofable push sender, or sensitive data riding in the push payload/deeplink.
Use when: you have decompiled sources (jadx/apktool output) and want the candidate API surface before Burp is even running; or you have live Burp traffic and want the per-bug-class test to run against each endpoint; or you're deciding whether a client-side gate (premium flag, admin menu, biometric-only screen) is actually enforced server-side.
Consumes: targets/<hash>/threat_model.json (network_endpoints, auth logic gated client-side
findings from decompile-threat-review), targets/<hash>/inventory.json sink hits in category
8-network, this skill's own static extractor output, and — once dynamic-verify has traffic
flowing — the live Burp proxy history. Feeds directly into api-vuln-test's
extract_endpoints.py and api_findings.json.
3. Detection — STATIC seeds, DYNAMIC (Burp) does the actual testing
3a. Static seed (deterministic) — bundled extractor
python skills/api-pivot/scripts/scan_api_surface.py --hash <sha256> --json targets/<hash>/api_surface.json
# or ad-hoc: --dir path/to/decompiled
Greps decompiled sources for: absolute http(s):// URLs (deduped, grouped by host), Retrofit
method annotations (@GET/@POST/@PUT/@DELETE/@PATCH) and their path templates, Retrofit param
annotations (@Path/@Query/@Header/@Body/... — the object refs and auth carriers you'll target),
BASE_URL/API_URL/HOST-style string constants, Authorization/Bearer header code, and any
inline JWTs. Every hit carries file:line. This is the pre-Burp work list: candidate hosts,
endpoint templates, and where auth is attached — read each hit in context, then confirm live once
traffic flows.
3b. Dynamic (the real test) — after dynamic-verify gets traffic into Burp
Pinning bypass (generic or a custom Frida hook from threat_model.json.pinning) is a
dynamic-verify job, not this skill's. Once HTTPS is visible in Burp, work each endpoint from
scan_api_surface.py + Burp history against the OWASP API Top 10. Exact method per class:
| Class | Exact test |
|---|---|
| IDOR / BOLA | Log in as Account A and Account B (both yours). As A, replay A's request but swap the object id/UUID in the URL, body, or query for B's. Confirm = you get B's data/write B's object while authenticated as A. |
| Broken auth/session | Drop the token entirely; replay with an expired token; swap A's token onto B's request. Decode the JWT (jwt.io/CyberChef) — check exp, audience, and whether the signature is actually verified server-side (see JWT row). |
| BFLA / broken access control | As a low-privilege account, call the exact route an admin/privileged screen uses (found via Retrofit annotations or Burp history for that role). Flip HTTP method (GET→PUT/DELETE) on a route you can only GET. Confirm = the privileged action executes. |
| Business logic | Replay a multi-step flow out of order or skip a step (e.g. skip payment-confirm, go straight to fulfill). Race a one-time action (double-submit a coupon/referral concurrently in Burp Turbo Intruder / Repeater tabs). Tamper price/quantity/currency in the body. |
| Missing rate limiting | Burp Intruder (or Turbo Intruder) sweep on login/OTP/password-reset/coupon-redeem with a wordlist or numeric range; confirm no lockout/backoff/CAPTCHA kicks in. |
| Mass assignment | On a write endpoint (POST/PATCH create-or-update), add fields the client never sends: "isAdmin":true, "role":"admin", "verified":true, "price":0. Confirm = the field is accepted/applied (re-GET the object). |
| Backend injection | Put ', " OR 1=1--, ; sleep 5, ${jndi:...}-class markers in params that reach the backend (search, filter, sort); watch for SQL errors, timing deltas, or command output. |
| XXE | If any endpoint accepts XML/SOAP, submit a body with a <!DOCTYPE> external entity referencing a local file or your Burp Collaborator URL; confirm = file contents returned or an out-of-band callback. |
| SSRF (server-side) | Any param that is itself a URL/host/webhook the server fetches (image-by-URL, webhook registration, PDF-from-URL) — point it at http://169.254.169.254/... or your Collaborator; confirm = server-side fetch happens. |
| GraphQL abuse | POST {"query":"{__schema{types{name,fields{name}}}}"} to the GraphQL endpoint — introspection left on in prod is already a finding; then probe batching (array of queries in one POST) and field-level authz (query a field the UI never exposes). |
| JWT flaws | Decode the token. Try alg:"none" with the signature stripped; try re-signing with an empty/guessed HMAC secret (jwt_tool/hashcat mode 16500 against common/leaked secrets); try kid header pointing at a file/../ path if kid-based key lookup is used. Confirm = server accepts the forged token. |
| Insecure file upload | Upload with a double extension (shell.php.jpg), null-byte/path-traversal filename, mismatched Content-Type, or a polyglot; check where/how the server stores and serves it back (public path? executable?). |
| Auth gated client-side only (§4) | From local-auth-audit/decompile-threat-review, find a "premium"/"admin"/"unlocked" check that's Kotlin/Java-only. Call the underlying API route directly (bypass the UI) as a non-premium/non-admin account. Confirm = the server performs the action anyway. |
| Push/FCM abuse (§8) | Inspect the push payload (via a Frida hook on the messaging callback or a MITM'd FCM channel) for sensitive data, and check whether the app trusts payload fields (e.g. a deep-link URL or "mark as read" action) without server-side re-validation. |
Reference PortSwigger Web Security Academy and OWASP API Security Top 10 methodology for
depth on each class (references/reports.md). This module does not ship a mass-exploitation
scanner — every test above is one deliberate, human-reasoned request replayed in Burp Repeater
against an account and host you're authorized to touch.
4. TTP catalog (pointers — full detail + citations in references/reports.md)
Each technique in references/reports.md carries precondition · signal · test procedure ·
confirmation · impact · cited reference. The high-value ones:
- BOLA/IDOR — object ref swap across two owned accounts. Usually the fastest confirmed finding.
- BFLA — privileged route reachable by low-priv role; method-flip on a read-only route.
- JWT
alg:none/ weak secret — signature verification not actually enforced server-side. - Mass assignment — extra JSON field accepted on a write.
- Auth logic gated client-side only — the app's gate has no server-side twin.
- Server-side SSRF via app-controlled URL — a URL the app lets the user supply is fetched by the server, reachable to internal/metadata endpoints.
- GraphQL introspection / batching / field authz gaps.
- Missing rate limiting on OTP/login/coupon.
5. Chaining playbook (≥2 concrete chains)
- Client-gated "premium" bypass → free premium.
local-auth-audit/decompile-threat-review flags a premium/paywall check that only exists in app code (§4 row) [cross-ref local-auth-audit].scan_api_surface.py+ Burp show the underlyingPOST /subscriptions/activate-style call the UI makes only after the client check passes. Call that route directly as a non-paying account [this skill: auth gated client-side only] → server grants premium with no payment. High. - Hardcoded HMAC/signing key (apk-recon) → forged signed request → privileged action.
apk-reconfinds a hardcoded signing/HMAC key baked into the APK (catalog §6). This skill's extractor shows which endpoint expects anX-Signature/HMAC header (via theauth_header_signals/retrofit_paramshits) [cross-ref apk-recon]. Forge a validly-signed request for a privileged action (e.g. a promo-code redemption or admin webhook) the server otherwise trusts only from the app [this skill: broken auth/session, business logic]. High. - SSRF via app-controlled URL → cloud metadata. WebView/upload flow lets the app forward a
user- or app-controlled URL to the backend (avatar-by-URL, link-preview, PDF export)
[cross-ref webview-audit for the client-side entry point]. Server fetches it server-side
with no allow-list [this skill: SSRF (server-side)] → point at
169.254.169.254→ cloud credentials/instance metadata disclosed. Critical. - Deep-link OAuth leak → API token replay → account takeover. A weak
redirect_uri/statein an OAuth deep link [cross-ref deeplink-audit] lets you capture another user's auth code/token. Replay that token against the API [this skill: broken auth/session, then IDOR to confirm the takeover] → read/modify the victim's account. High.
6. Impact / severity & report template
Severity tracks what the backend actually does, not just "no pinning" or "debuggable" style client-side noise: IDOR/BOLA on PII or account-modifying endpoints, BFLA reaching admin actions, backend injection, SSRF to internal/metadata, and JWT forgery are High–Critical; mass assignment and missing rate limiting are Med–High depending on the field/endpoint; business logic flaws scale with the abused value (free premium, price manipulation).
### <Server-side class> — <impact> on <host><path>
- Summary: <what an authenticated-as-A / unauthenticated caller can do to B's data or a privileged route>
- Affected: <method> <host><path> (<normalized_path>), backend behind <pkg>
- Preconditions: <auth mechanism>; <account tier>; <host in scope? yes>
- Steps: 1) scan_api_surface.py / api-vuln-test endpoint 2) Burp Repeater request (exact diff from baseline) 3) response proving cross-account/privileged access
- PoC: <request + response> (evidence/<id>/burp/request.txt, response.txt)
- Impact: <data exposed / action performed / privilege gained>
- Chaining: <next link + sibling skill, e.g. apk-recon hardcoded key, local-auth-audit client gate>
- Remediation: server-side object-ownership check; re-verify JWT signature + `alg`; allow-list
mass-assignable fields; rate-limit + backoff/CAPTCHA; SSRF allow-list; parameterized queries
- References: OWASP API Top 10 <APIx:2023>; PortSwigger technique page (see references/reports.md)
7. MASVS / MASTG / OWASP mapping
- MASVS-NETWORK (the channel the app uses to reach the API), MASVS-AUTH (session/token handling, the client-gated-auth row), plus standard web/API testing methodology once traffic is observable (this is not an Android-specific test surface once you're past the app).
- MASTG: "Testing Network Communication" / MASVS-NETWORK tests; MASVS-AUTH local/remote auth tests. OWASP Mobile Top 10 M4 (Insufficient Input/Output Validation — injection/XXE/SSRF via app-originated data) and M6 (Insecure Authorization — IDOR/BOLA/BFLA reached through the app).
- OWASP API Security Top 10 (2023) mapping: API1 BOLA, API2 Broken authentication, API3 Broken object property level authz (mass assignment), API4 Unrestricted resource consumption (rate limiting), API5 BFLA, API6 Unrestricted sensitive business flows, API7 SSRF, API8 Security misconfiguration, API9 Improper inventory management (old/staging endpoints found in the APK), API10 Unsafe consumption of 3rd-party APIs.
See references/reports.md for the full per-TTP procedures and citations, and
skills/api-vuln-test/references/api-top10.md for the pipeline's per-endpoint checklist this
module's rubric feeds.