React Native 应用程序分析
Reading time: 13 minutes
tip
学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
学习和实践 Azure 黑客技术:
HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。
要确认应用程序是否基于 React Native 框架构建,请按照以下步骤操作:
-
将 APK 文件重命名为 zip 扩展名,并使用命令
cp com.example.apk example-apk.zip
和unzip -qq example-apk.zip -d ReactNative
将其提取到新文件夹中。 -
导航到新创建的 ReactNative 文件夹,找到 assets 文件夹。在此文件夹中,您应该找到文件
index.android.bundle
,该文件包含以压缩格式的 React JavaScript。 -
使用命令
find . -print | grep -i ".bundle$"
搜索 JavaScript 文件。
注意:如果您获得的是 Android App Bundle (.aab) 而不是 APK,请先生成一个通用 APK,然后提取该包:
# Get bundletool.jar and generate a universal APK set
java -jar bundletool.jar build-apks \
--bundle=app-release.aab \
--output=app.apks \
--mode=universal \
--overwrite
# Extract the APK and then unzip it to find assets/index.android.bundle
unzip -p app.apks universal.apk > universal.apk
unzip -qq universal.apk -d ReactNative
ls ReactNative/assets/
Javascript 代码
如果检查 index.android.bundle
的内容,你会发现应用程序的 JavaScript 代码(即使是经过压缩的),你可以 分析它以查找敏感信息和漏洞。
由于该包实际上包含了应用程序的所有 JS 代码,因此可以 将其分成不同的文件(可能使其逆向工程更容易),使用 工具 react-native-decompiler。
Webpack
要进一步分析 JavaScript 代码,你可以将文件上传到 https://spaceraccoon.github.io/webpack-exploder/ 或按照以下步骤操作:
- 在同一目录中创建一个名为
index.html
的文件,内容如下:
<script src="./index.android.bundle"></script>
-
在 Google Chrome 中打开
index.html
文件。 -
通过按 Command+Option+J for OS X 或 Control+Shift+J for Windows 打开开发者工具栏。
-
在开发者工具栏中点击 "Sources"。你应该会看到一个 JavaScript 文件,它被分成文件夹和文件,构成了主包。
如果你找到一个名为 index.android.bundle.map
的文件,你将能够以未压缩的格式分析源代码。映射文件包含源映射,这允许你映射压缩的标识符。
要搜索敏感凭证和端点,请按照以下步骤操作:
-
确定敏感关键词以分析 JavaScript 代码。React Native 应用程序通常使用第三方服务,如 Firebase、AWS S3 服务端点、私钥等。
-
在这个特定案例中,观察到该应用程序使用了 Dialogflow 服务。搜索与其配置相关的模式。
-
幸运的是,在侦查过程中在 JavaScript 代码中发现了敏感的硬编码凭证。
在包中快速寻找秘密/端点
这些简单的 grep 通常会在压缩的 JS 中浮现出有趣的指示器:
# Common backends and crash reporters
strings -n 6 index.android.bundle | grep -Ei "(api\.|graphql|/v1/|/v2/|socket|wss://|sentry\.io|bugsnag|appcenter|codepush|firebaseio\.com|amplify|aws)"
# Firebase / Google keys (heuristics)
strings -n 6 index.android.bundle | grep -Ei "(AIza[0-9A-Za-z_-]{35}|AIzaSy[0-9A-Za-z_-]{33})"
# AWS access key id heuristic
strings -n 6 index.android.bundle | grep -E "AKIA[0-9A-Z]{16}"
# Expo/CodePush deployment keys
strings -n 6 index.android.bundle | grep -Ei "(CodePush|codepush:\\/\\/|DeploymentKey)"
# Sentry DSN
strings -n 6 index.android.bundle | grep -Ei "(Sentry\.init|dsn\s*:)"
如果您怀疑无线更新框架,还要寻找:
- Microsoft App Center / CodePush 部署密钥
- Expo EAS 更新配置(
expo-updates
,expo\.io
,签名证书)
更改 JS 代码并重建
在这种情况下,更改代码很简单。您只需将应用程序重命名为使用扩展名 .zip
并提取它。然后,您可以修改此捆绑包中的 JS 代码并重建应用程序。这应该足以让您注入代码以进行测试。
Hermes 字节码
如果捆绑包包含Hermes 字节码,您将无法访问应用程序的 Javascript 代码(甚至无法访问压缩版本)。
您可以通过运行以下命令检查捆绑包是否包含 Hermes 字节码:
file index.android.bundle
index.android.bundle: Hermes JavaScript bytecode, version 96
然而,您可以使用工具 hbctool、支持更新字节码版本的 hbctool 更新分支、hasmer、hermes_rs(Rust 库/API)或 hermes-dec 来 反汇编字节码,并将其 反编译为一些伪 JS 代码。例如:
# Disassemble and re-assemble with hbctool (works only for supported HBC versions)
hbctool disasm ./index.android.bundle ./hasm_out
# ...edit ./hasm_out/**/*.hasm (e.g., change comparisons, constants, feature flags)...
hbctool asm ./hasm_out ./index.android.bundle
# Using hasmer (focus on disassembly; assembler/decompiler are WIP)
hasmer disasm ./index.android.bundle -o hasm_out
# Using hermes-dec to produce pseudo-JS
hbc-disassembler ./index.android.bundle /tmp/my_output_file.hasm
hbc-decompiler ./index.android.bundle /tmp/my_output_file.js
提示:开源的 Hermes 项目在特定的 Hermes 版本中也提供开发者工具,如 hbcdump
。如果您构建与生成捆绑包所使用的 Hermes 版本匹配的版本,hbcdump
可以转储函数、字符串表和字节码以进行更深入的分析。
修改代码并重建 (Hermes)
理想情况下,您应该能够修改反汇编的代码(更改比较、值或您需要修改的任何内容),然后 重建字节码 并重建应用程序。
- 原始 hbctool 支持反汇编捆绑包并在更改后重新构建,但历史上仅支持较旧的字节码版本。社区维护的分支扩展了对较新 Hermes 版本(包括中间 80s–96)的支持,通常是修补现代 RN 应用程序的最实用选项。
- 工具 hermes-dec 不支持重建字节码(仅反编译器/反汇编器),但在导航逻辑和转储字符串方面非常有用。
- 工具 hasmer 旨在支持多个 Hermes 版本的反汇编和汇编;汇编仍在成熟中,但在最近的字节码上值得尝试。
使用类似 hbctool 的汇编器的最小工作流程:
# 1) Disassemble to HASM directories
hbctool disasm assets/index.android.bundle ./hasm
# 2) Edit a guard or feature flag (example: force boolean true)
# In the relevant .hasm, replace a LoadConstUInt8 0 with 1
# or change a conditional jump target to bypass a check.
# 3) Reassemble into a new bundle
hbctool asm ./hasm assets/index.android.bundle
# 4) Repack the APK and resign
zip -r ../patched.apk *
# Align/sign as usual (see Android signing section in HackTricks)
注意,Hermes 字节码格式是有版本的,汇编器必须与磁盘上的确切格式匹配。如果您遇到格式错误,请切换到更新的分支/替代方案或重建匹配的 Hermes 工具。
动态分析
您可以尝试动态分析应用程序,使用 Frida 启用 React 应用的开发者模式,并使用 react-native-debugger
附加到它。然而,显然您需要应用的源代码。您可以在 https://newsroom.bedefended.com/hooking-react-native-applications-with-frida/ 找到更多信息。
使用 Frida 在发布版本中启用开发支持(注意事项)
一些应用程序意外地发布了可以切换开发支持的类。如果存在,您可以尝试强制 getUseDeveloperSupport()
返回 true:
// frida -U -f com.target.app -l enable-dev.js
Java.perform(function(){
try {
var Host = Java.use('com.facebook.react.ReactNativeHost');
Host.getUseDeveloperSupport.implementation = function(){
return true; // force dev support
};
console.log('[+] Patched ReactNativeHost.getUseDeveloperSupport');
} catch (e) {
console.log('[-] Could not patch: ' + e);
}
});
警告:在正确构建的发布版本中,DevSupportManagerImpl
和相关的仅调试类会被剥离,翻转此标志可能会导致应用崩溃或没有效果。当这有效时,您通常可以暴露开发菜单并附加调试器/检查器。
RN 应用中的网络拦截
React Native Android 通常依赖于 OkHttp(通过 Networking
原生模块)。要在非越狱设备上动态测试期间拦截/观察流量:
- 使用系统代理 + 信任用户 CA 或使用其他通用的 Android TLS 绕过技术。
- RN 特定提示:如果应用在发布中错误地捆绑了 Flipper(调试工具),Flipper 网络插件可以暴露请求/响应。
有关通用 Android 拦截和固定绕过技术,请参考:
Make APK Accept CA Certificate
流行 RN 库中的近期问题(需要注意的事项)
在审计 JS 包或原生库中可见的第三方模块时,检查已知漏洞并验证 package.json
/yarn.lock
中的版本。
- react-native-mmkv(Android):2.11.0 之前的版本将可选加密密钥记录到 Android 日志中。如果 ADB/logcat 可用,秘密可能会被恢复。确保版本 >= 2.11.0。指标:使用
react-native-mmkv
,日志语句提到带加密的 MMKV 初始化。CVE-2024-21668。 - react-native-document-picker:版本 < 9.1.1 在 Android 上存在路径遍历漏洞(文件选择),在 9.1.1 中修复。验证输入和库版本。
快速检查:
grep -R "react-native-mmkv" -n {index.android.bundle,*.map} 2>/dev/null || true
grep -R "react-native-document-picker" -n {index.android.bundle,*.map} 2>/dev/null || true
# If you also have the node_modules (rare on release): grep -R in package.json / yarn.lock
参考文献
- https://medium.com/bugbountywriteup/lets-know-how-i-have-explored-the-buried-secrets-in-react-native-application-6236728198f7
- https://www.assetnote.io/resources/research/expanding-the-attack-surface-react-native-android-applications
- https://payatu.com/wp-content/uploads/2023/02/Mastering-React-Native-Application-Pentesting-A-Practical-Guide-2.pdf
- CVE-2024-21668: react-native-mmkv 在 Android 上记录加密密钥,已在 v2.11.0 中修复 (NVD): https://nvd.nist.gov/vuln/detail/CVE-2024-21668
- hbctool (及其分支) 用于 Hermes 组装/拆解: https://github.com/bongtrop/hbctool
tip
学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
学习和实践 Azure 黑客技术:
HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。