mcpField
A
apk-redteam-pipeline

apk-redteam-pipeline

github.com/elementalsouls安全5.3k281 次安装今天更新
代码仓库

关于 apk-redteam-pipeline

apk-redteam-pipeline 是面向授权 Android 应用安全评估的技能,涵盖 APK 清点、获取、静态与运行时分析,并强调验证发现结果。

主要功能

  1. 01清点 Android 应用并获取 APK
  2. 02DEX 反编译与密钥扫描
  3. 03检查证书和导出组件
  4. 04检查 Firebase 配置
  5. 05使用 Frida 分析并捕获流量

适用场景

  1. 01评估项目范围内的 Android 应用
  2. 02发现嵌入的端点与凭据
  3. 03检查导出组件的 Intent 风险
  4. 04跟踪运行时令牌和 API 请求

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/elementalsouls/claude-bughunter --skill apk-redteam-pipeline

安装后在 Claude Code 中输入/apk-redteam-pipeline确认已加载。

详细介绍

使用此技能的时机

在以下情况触发:

  • Recon 发现目标开发者名下有 1 个或多个移动应用(Play Store 开发者页面)
  • Web 应用直接托管 *.apk 文件(例如某次测试期间在子域名上发现 Recruitz.apk)
  • 信息窃取程序日志泄露了 APK 包 ID(例如窃取程序转储格式中出现 com.<brand>.app、com.<brand>.<sub-brand> 模式)
  • 客户端应用、经销商/合作伙伴门户或员工移动端配套应用在测试范围内
  • 漏洞赏金计划将 Android 列入测试范围

请勿用于:

  • 仅限 iOS 的目标(使用不同流程——IPA 逆向、MobSF、frida-ios-dump)
  • 已通过 JS bundle 分析覆盖的 React Native/Flutter Web 应用
  • 仅限服务端的评估

阶段 0 — 清点所有组织自有应用

抓取 Play Store 开发者页面
# Find developer page from the target's brand name
curl -sk -A "Mozilla/5.0" "https://play.google.com/store/apps/developer?id=<Brand+Name>" -o /tmp/dev.html

# Extract package IDs
grep -oE 'id=[a-zA-Z0-9._]+' /tmp/dev.html | sort -u

示例输出(已匿名处理——多品牌企业通常有 7 个包):

com.events.<brand>build
com.<corp>.<sub-brand-1>
com.<corp>.<sub-brand-2>
com.<corp>.<flagship>
com.<corp>.<product-line-1>
com.<corp>.<product-line-2>
com.<corp>.<sub-brand-3>
与信息窃取程序日志交叉核对

信息窃取程序日志格式包含类似 *@com.<corp>.<app> 的包名——如果你有泄露的转储文件,可从 creds_userpass.txt 中提取这些信息。

品牌排列组合猜测(多品牌企业模式)
com.<brand>.app
com.<brand>.mobile  
com.<brand>.android
com.<brand>connect.app
in.<brand>.dealer
in.co.<brand>.app

阶段 1 — 获取 APK

首选:直接从 APKPure 获取(无需身份验证)
# Follow 302 redirects to actual download
curl -sk -L --max-time 60 \
  "https://d.apkpure.net/b/APK/<package_id>?version=latest" \
  -o "<package_id>.apk"

# Or via the legacy d-XX.winudf.com mirror chain (we saw this work)
次选:在 APKMirror 搜索
curl -sk -A "Mozilla/5.0" "https://www.apkmirror.com/?post_type=app_release&searchtype=apk&s=<brand>" \
  | grep -oE 'href="[^"]+\.apk[^"]*"' | sort -u
备选:在 APKPure 网页搜索
curl -sk "https://apkpure.com/search?q=<brand>" | grep -oE 'data-dt-app="[^"]+"'
XAPK 与 APK
  • .xapk = 包含多个拆分 APK 的 zip 文件(base + config.armeabi-v7a + config.en + 等)
  • 先解压外层文件,再解压内层的 base.apk 或 <package>.apk
  • 部分 apkpure 下载会返回缺少 EOCD 签名的截断 XAPK——这是 CDN 限流的表现;更换 IP 后重试,或使用 7z x,它比 unzip 更宽容
# Standard unzip (works for clean APK)
unzip -o <package>.apk -d extracted_<package>/

# For truncated/repaired XAPK
7z x -y <package>.apk -o"extracted_<package>"

# For nested XAPK
for inner in extracted_<package>/*.apk; do
  mkdir -p "extracted_<package>/$(basename "$inner" .apk)"
  unzip -o "$inner" -d "extracted_<package>/$(basename "$inner" .apk)"
done

阶段 2 — DEX 反编译(jadx)

# Install
brew install jadx          # macOS
# or
wget https://github.com/skylot/jadx/releases/latest/download/jadx-1.5.x.zip

# Decompile
jadx -d decompiled_<package>/ <package>.apk

# For XAPK that contains multiple APKs
for inner in extracted_<package>/*.apk; do
  jadx -d decompiled_<package>_$(basename "$inner" .apk)/ "$inner"
done

如需快速扫描“仅字符串”而不进行完整反编译:

find extracted_<package> -name "classes*.dex" -exec strings -8 {} \; > strings_<package>.txt

阶段 3 — 搜索密钥(60 种模式目录)

# URL grep — owned-domain references
grep -oE 'https?://[a-zA-Z0-9.-]+\.(target1|target2|target3)\.(com|io|net|in)[a-zA-Z0-9./_?=&%-]*' strings_<package>.txt | sort -u

# Internal IP / port URLs
grep -oE 'https?://(10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.|127\.)[0-9.]+(:[0-9]+)?[a-zA-Z0-9./_?=&-]*' strings_<package>.txt

# Cloud credentials
grep -oE 'AKIA[A-Z0-9]{16}'                            # AWS Access Key
grep -oE 'aws_secret_access_key[\s:=]+[A-Za-z0-9/+=]{40}' # AWS Secret
grep -oE 'AIza[A-Za-z0-9_-]{35}'                       # Google API key
grep -oE 'ya29\.[A-Za-z0-9_-]+'                        # Google OAuth refresh token
grep -oE 'gh[ps]_[A-Za-z0-9]{36}'                      # GitHub PAT
grep -oE 'glpat-[A-Za-z0-9_-]{20}'                     # GitLab PAT
grep -oE 'xox[pbar]-[A-Za-z0-9-]+'                     # Slack token
grep -oE 'sk-[A-Za-z0-9]{48}'                          # OpenAI API key
grep -oE 'sk-ant-[A-Za-z0-9_-]{90,}'                   # Anthropic API key
grep -oE 'AC[a-f0-9]{32}'                              # Twilio Account SID
grep -oE 'sk_live_[A-Za-z0-9]{24}'                     # Stripe live key
grep -oE 'pk_live_[A-Za-z0-9]{24}'                     # Stripe publishable
grep -oE 'mailgun-[A-Za-z0-9-]{40}'                    # Mailgun
grep -oE 'SG\.[A-Za-z0-9_-]{22}\.[A-Za-z0-9_-]{43}'    # SendGrid

# JWT (any algorithm)
grep -oE 'eyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]*' strings_<package>.txt

# Firebase
grep -oE '"(api_key|project_id|database_url|storage_bucket|client_id|mobilesdk_app_id|google_app_id|gcm_defaultSenderId)"\s*:\s*"[^"]+"' \
  extracted_<package>/res/values/strings.xml \
  extracted_<package>/google-services.json \
  decompiled_<package>/resources/AndroidManifest.xml 2>/dev/null

# OAuth client secrets
grep -oE 'client_secret["\s:=]+[A-Za-z0-9_-]{24,}' strings_<package>.txt

# Hardcoded passwords (heuristic — many false positives, manual review)
grep -oE '"password"\s*:\s*"[^"]+"|password\s*=\s*"[^"]+"' decompiled_<package>/sources/**/*.java 2>/dev/null
真实案例发现(已匿名处理——来自一次经授权的测试)
# Customer-facing APK shipped a hardcoded URL of this shape:
https://api.<client>.example/<path-token>/<resource-token>?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.<payload>.<sig>

# Decoded JWT payload: {"sid":<int>,"iat":<unix-ts>,"exp":<unix-ts>}
# Expired ~8 years earlier — but path tokens + 30 /v1/* endpoints still useful intel

阶段 4 — 提取固定证书

# Find .cer / .der / .pem files in assets/
find extracted_<package>/assets -iname "*.cer" -o -iname "*.der" -o -iname "*.pem" -o -iname "*.crt" 2>/dev/null

# Or in network_security_config.xml
find extracted_<package> -name "network_security_config.xml" -exec cat {} \;

# For each cert, extract subject + SAN (might reveal new internal API hosts)
for cert in $(find extracted_<package>/assets -iname "*.cer"); do
  echo "=== $cert ==="
  openssl x509 -in "$cert" -noout -subject -issuer -dates 2>/dev/null
  openssl x509 -in "$cert" -noout -text 2>/dev/null | grep -E 'Subject:|DNS:|Issuer:|Validity'
done
真实案例

某次经授权测试中的一款面向客户的 APK 包含 assets/api_<service>_<domain>_com.cer,揭示了 api.<service>.<domain>.example 资产的存在,而被动侦察此前并未发现该资产。


阶段 5 — 枚举导出组件

AndroidManifest.xml 会列出组件。导出的组件(尤其是带有 android:exported="true" 或通过 intent-filter 隐式导出的组件)可由其他应用触发,可能构成 Intent 注入攻击面。

# Decode binary AndroidManifest if needed
apktool d <package>.apk -o decoded_<package>/    # apktool decodes binary manifest

# Or read directly from jadx output
cat decompiled_<package>/resources/AndroidManifest.xml | grep -E '<(activity|service|receiver|provider)' | head -50

# Filter exported
grep -E 'android:exported="true"' decompiled_<package>/resources/AndroidManifest.xml

针对每个导出的组件,检查:

  • 它是否接受会流入 WebView 的 extras(intent → WebView → XSS / file://)
  • 它是否接受 URI extras(可能通过深层链接造成 SSRF)
  • 它是否将 extras 传递给其他 Activities(Intent 重定向)

阶段 6 — 检查 Firebase/云服务配置

# google-services.json — full Firebase config
find extracted_<package> -name "google-services.json" -exec cat {} \; | python3 -m json.tool

# Look for:
#   project_id   → can guess Firestore / RTDB URL: https://<project_id>.firebaseio.com/.json
#   storage_bucket → can guess GCS bucket: gs://<bucket>
#   web_api_key  → can use to enumerate Firebase tenant config

# Test if Firestore is publicly readable
curl -s "https://firestore.googleapis.com/v1/projects/<project_id>/databases/(default)/documents/users"

# Test if Realtime DB is publicly readable
curl -s "https://<project_id>.firebaseio.com/.json"

# Test if Storage Bucket is publicly listable
curl -s "https://firebasestorage.googleapis.com/v0/b/<bucket>/o"

阶段 7 — 运行时插桩(Frida)

当静态分析不够时使用——你可能需要在运行时转储令牌、绕过证书固定,或跟踪 API 调用。

设置
pip install --break-system-packages frida-tools objection
adb devices  # ensure device/emulator connected
# Push frida-server to device (root required, or use rooted emulator like Genymotion / x86_64 AVD)
绕过证书固定(通用方法)
// frida-script-pinning-bypass.js
Java.perform(function() {
    // OkHttp
    try {
        var CertificatePinner = Java.use('okhttp3.CertificatePinner');
        CertificatePinner.check.overload('java.lang.String', 'java.util.List').implementation = function() {
            console.log('[+] OkHttp pinning bypassed for: ' + arguments[0]);
            return;
        };
    } catch (e) {}
    // HttpsURLConnection
    try {
        var TrustManagerImpl = Java.use('com.android.org.conscrypt.TrustManagerImpl');
        TrustManagerImpl.verifyChain.implementation = function(chain) {
            console.log('[+] TrustManagerImpl verifyChain bypassed');
            return chain;
        };
    } catch (e) {}
});
frida -U -l frida-script-pinning-bypass.js -f <package_id> --no-pause
Hook HTTP 请求
Java.perform(function() {
    var OkHttpClient = Java.use('okhttp3.OkHttpClient');
    var Request = Java.use('okhttp3.Request');
    var Call = Java.use('okhttp3.Call');
    
    OkHttpClient.newCall.implementation = function(req) {
        var url = req.url().toString();
        var headers = req.headers().toString();
        console.log('[REQ] ' + url);
        console.log('[HDRS] ' + headers);
        return this.newCall(req);
    };
});
使用 objection 快速提取令牌
objection --gadget com.target.app explore
# Inside:
android hooking watch class_method <class>.<method> --dump-args --dump-return

阶段 8 — 捕获网络流量(通过 mitmproxy)

绕过证书固定后,可用于深入发现 API。

# Run mitmproxy on host
mitmproxy --listen-port 8080

# Configure Android device proxy to host:8080
# Install mitmproxy CA cert on device:
#   - Pull from http://mitm.it on the device, or
#   - Push to /system/etc/security/cacerts/ on rooted device

# Use the Frida pinning bypass script while traffic flows through mitmproxy
# All API calls visible in mitmproxy UI

决策树 — 如何处理发现的内容

发现下一步
有效 JWT(未过期)针对 API 主机进行测试 — 它是否授予访问权限?尝试操纵 sid
已过期的 JWT检查路径令牌 / API 端点结构 — 这些信息在 VPN 后仍有用
AWS 访问密钥使用 awscli 进行测试:aws sts get-caller-identity — 许多泄露的密钥仍有权限
Firebase project_id + web_api_key测试 Firestore/RTDB/Storage 的公开读取权限
Google API 密钥(AIza*)使用 https://www.googleapis.com/customsearch/v1 等进行测试 — 查看该密钥启用了哪些 API
硬编码的 HTTP URL(http://)如果缺少证书固定,可能遭遇降级攻击 MITM
内部主机的固定证书发现新资产 — 该主机确实存在
导出的 Activity 包含 WebView测试 Intent 注入 → URL 加载滥用
堆栈跟踪痕迹(Stack Overflow URL)找出开发者提出的问题 → 推断架构
硬编码凭据立即进行喷洒攻击(遵守相关技能中的任何限制)

反模式

  • 不要只搜索“password” — 大多数密钥都有特定的高信号模式(AKIA、AIza、eyJ 等)。搜索通用词会产生过多噪声。
  • 不要跳过 XAPK 拆分 APK — config.armeabi 拆分包和 config. 拆分包有时包含不同的代码路径。
  • 不要把过期的 JWT 当作“无用情报” — 路径结构、端点列表和签名算法仍然有用。上文 8 年前过期的 JWT 示例就说明了这一点。
  • 不要只逆向最新版本 — 较旧的 APK 版本(可通过 APKMirror 版本历史获取)有时仍保留已从新版本移除、但在服务端仍有效的密钥。
  • 即使应用看起来“简单”,也不要忽略 Firebase — Firebase 规则配置错误(Firestore 可公开读取)极为常见。
  • 不要在生产设备上运行 Frida — 仅使用已 Root 的模拟器或测试设备。

工具安装(一次性)

brew install jadx p7zip
pip install --break-system-packages frida-tools objection
# Genymotion or AVD for rooted Android emulator

为了方便下载 APK,可以添加一个 download-apk shell 函数:

download-apk() {
  local pkg="$1"
  curl -sk -L --max-time 60 "https://d.apkpure.net/b/APK/$pkg?version=latest" -o "$pkg.apk"
  echo "Downloaded $(wc -c < "$pkg.apk") bytes"
  file "$pkg.apk"
}

与相邻技能的衔接

  • offensive-osint — Play Store / APKMirror 枚举是更广泛 OSINT 的一部分
  • hunt-cloud-misconfig — 发现 Firebase 可公开读取后,后续处理正是此技能的专长
  • hunt-api-misconfig — 获取算法和示例令牌后操纵 JWT
  • evidence-hygiene — 将提取的密钥纳入报告前需要脱敏
  • redteam-mindset — 在交战第 1 天逆向 APK,而不是事后才做

真实案例发现模板(已匿名化 — 授权交战)

发现:面向客户的 APK 中存在硬编码 JWT + 30 多个内部 API 端点

  • 对象:旧版移动应用构建中的硬编码痕迹暴露了内部 API 面
  • 观察:对 com.<client>.<app> 进行反编译后,发现嵌入的 JWT(约 8 年前已过期)以及指向 api2.<client>.example 的 30 多个 /v1/* 端点路径(仅限内部访问,外部无法访问)
  • 描述:APK 随附了开发者构建痕迹。路径令牌属于通过隐蔽性实现安全;API 端点清单具有侦察级价值。
  • 影响:获得 VPN 后的立足点(通过凭据泄露)后,攻击者无需逆向二进制文件即可获取完整的 API 面图谱。通过 SSRF/LFI 恢复 HS256 密钥后,即可任意伪造令牌。
  • 建议:轮换 HS256 密钥,迁移至 RS256,从构建中移除硬编码 URL,并审计组织内所有 APK。
  • 证据:提取的字符串、解码后的 JWT、端点清单

相关技能与链路

  • cloud-iam-deep — APK 秘密提取经常会获得有效的 AWS/GCP/Azure 凭据。链路原语:jadx 字符串 grep 得到 AWS Access Key ID + Secret → cloud-iam-deep aws sts get-caller-identity → 枚举角色/策略 → IAM 权限提升路径(24 种有文档记录的 AWS 提权模式之一)→ 接管云控制面。同一流程也适用于从 APK 资源中提取的 GCP 服务账号 JSON 和 Azure 共享访问签名令牌。
  • hunt-api-misconfig — APK 端点清单会直接提供 API 攻击面;批量赋值、JWT 和 CORS 漏洞很常见。链路原语:APK 揭示 /v1/users/me 和 /v1/admin/users → 使用 hunt-api-misconfig 对 /v1/users/me 进行批量赋值探测({is_admin:true})→ 提升为管理员角色 → 访问 /v1/admin/users。
  • hunt-rce — 从 APK 提取的硬编码 JWT 签名密钥(HS256)可用于伪造任意令牌。链路原语:APK 字符串中提取出 HS256 密钥 → 伪造管理员令牌 → 访问管理员 API → 如果 API 存在 eval/template/sink → 使用 hunt-rce 入侵服务器。此外,如果应用是本地安装的,带有 intent 注入 sink 的导出组件可以触达 Runtime.exec。
  • offensive-osint — APK 是更广泛的组织侦察图谱中的一个节点;可结合泄露语料库和证书透明度数据。链路原语:APK 揭示内部 API 主机名 api2.example.com → 使用 offensive-osint 查询证书透明度 → 发现关联的子域名 → 扩大攻击面。
  • redteam-report-template — APK 发现需要清晰说明“二进制文件泄露了什么”,因为客户工程师常常会把移动端静态分析发现斥为“混淆问题”。链路原语:已验证的发现(提取出的令牌/URL/密钥)→ triage-validation 的 7-Question Gate(特别是:“此凭据目前仍能通过身份验证吗?”)→ 使用 redteam-report-template 打包,并明确注明二进制版本和提取复现步骤。

评论

支持 Markdown