Features • Installation • Usage • Extraction • Output • Scope
SubKu reads an Android APK and reports the cloud backend behind it. A React Native app carries its Firebase project ID, storage bucket, API key, and database URL inside resources.arsc and its JavaScript bundle. SubKu extracts those values offline, maps the cloud backend hosts the APK names (10 host suffixes covering Cloud Run, App Engine, Realtime Database, Cloud Functions, Firebase Hosting, Firebase Storage, Supabase, and AWS), then optionally probes each backend with unauthenticated marker reads against three services: Firebase Storage, Realtime Database, and Firestore (7 common collections). An OPEN probe earns a critical label. APK in, backend exposure out.
- APK in, backend exposure out: one Python file, one dependency (
androguard) - Offline extraction stage: package metadata, signing certificate, bundle type, Firebase config
- Cloud backend mapping: 10 host suffix roles across Google Cloud, Firebase, Supabase, and AWS
- Optional probe stage: unauthenticated marker reads against Storage, Realtime Database, and Firestore
- Restraint built in: any URL carrying the
alt=mediacontent-retrieval marker is refused before the request is made - Human report or JSON output; exit code 2 when severity is
critical - Accepts a local APK path or a URL to download
git clone https://github.com/nuclide-research/SubKu
cd SubKu
pip install androguardPython 3.8+. androguard is the only dependency.
python3 subku.py app-release.apk # extract only, offline, passive
python3 subku.py app-release.apk --probe # also test the backend
python3 subku.py app-release.apk --probe --deep # paginate Storage fully (up to 60 pages)
python3 subku.py https://host/app.apk --probe # download APK, then scan
python3 subku.py app-release.apk --json --out report.json
python3 subku.py --version| Flag | Effect |
|---|---|
--probe |
run unauthenticated marker reads against the discovered backend |
--deep |
with --probe, paginate a Storage bucket fully (up to 60 pages of 1,000 objects) |
--json |
emit JSON instead of the human report |
--out FILE |
write the report to FILE |
Offline (no network):
- APK package name, version name and code, min and target SDK levels, declared permissions
- Signing certificate (subject, issuer, validity range, self-signed flag): the strongest operator attribution signal in an APK
- Bundle type:
react-native/hermes,react-native/javascript, ornative/dex; Hermes bytecode version when present - Firebase config from
resources.arsc: project ID, app ID, API key, storage bucket, sender ID, database URL - Cloud backend hosts from the bundle string table: 10 suffix roles (Cloud Run, App Engine / GCS, Realtime Database x2, Cloud Functions, Firebase Hosting x2, Firebase Storage, Supabase, AWS)
With --probe (unauthenticated marker reads):
- Storage: list objects with no credentials. Returns object count, sample names, truncation flag
- Realtime Database: shallow-list the root (key names only, never values)
- Firestore: read 7 common collections (
users,accounts,applications,profiles,documents,config,settings)
exposure : OPEN | secured | not probed
severity : critical | info
open : storage | rtdb | firestore (when OPEN)
Exit code is 2 when severity is critical, 0 otherwise. An OPEN storage or database is verified unauthenticated access and earns a critical label directly. When nothing is probed, or every store is secured, severity is info.
Example:
==================================================================
SubKu 0.1.0 app-release.apk
==================================================================
APK
package : com.example.rentals
version : 1.0 (code 2)
sdk : min 23 / target 34
signed by : Common Name: Jane Dev, Organization: Example Technologies, ...
(self-signed, 2024-10-23 -> 2049-10-17)
code : react-native/hermes (hermes v96)
FIREBASE
project_id : example-rentals
storage_bucket: example-rentals.appspot.com
api_key : AIza...redacted...
note : a Firebase api_key in an APK is public by
design; the risk is an unrestricted key
CLOUD BACKENDS
api-xxxxxxxxxxxx.europe-west1.run.app Cloud Run
PROBES (unauthenticated marker reads)
storage example-rentals.appspot.com OPEN >=1000 objects
- ID_DOC_xxxxxxxxxxxx.jpg
rtdb absent
firestore secured
------------------------------------------------------------------
exposure : OPEN
severity : critical
open : storage
------------------------------------------------------------------
SubKu is not a network scanner. It reads one APK and probes the backends that APK names. It does not sweep IP ranges, does not enumerate subdomains, and does not test any surface the APK does not explicitly declare.
Probes are marker reads only. They list, they read object metadata, they ask a database for a shallow key set. Any request URL carrying alt=media (the Firebase Storage object-content retrieval marker) is refused before the request is made. SubKu cannot be used to exfiltrate object content. Use it on apps you are authorized to assess.
A Firebase API key in an APK is public by design. Google documents it as a project identifier. SubKu reports it so you can check its restrictions; the key alone is not a finding.
- aimap: fingerprint scanner for AI/ML infrastructure
- scanner: fast active-banner stage between passive discovery and deep enumeration
- osint-platoon: multi-agent OSINT framework on ATP 3-21.8 doctrine
- VisorGraph: cert-pivot to operator attribution
MIT. Part of the NuClide toolchain. Contact: nuclide-research.com