From b5e3e23d69e1ab86500397d9f68fd2eda2cf1bbb Mon Sep 17 00:00:00 2001 From: Translator Date: Thu, 21 Aug 2025 04:22:51 +0000 Subject: [PATCH] Translated ['src/mobile-pentesting/android-app-pentesting/react-native-a --- .../react-native-application.md | 150 +++++++++++++++--- 1 file changed, 132 insertions(+), 18 deletions(-) diff --git a/src/mobile-pentesting/android-app-pentesting/react-native-application.md b/src/mobile-pentesting/android-app-pentesting/react-native-application.md index 9efa8d4c4..164fbea73 100644 --- a/src/mobile-pentesting/android-app-pentesting/react-native-application.md +++ b/src/mobile-pentesting/android-app-pentesting/react-native-application.md @@ -1,24 +1,38 @@ -{{#include ../../banners/hacktricks-training.md}} - # React Native 应用程序分析 +{{#include ../../banners/hacktricks-training.md}} + 要确认应用程序是否基于 React Native 框架构建,请按照以下步骤操作: 1. 将 APK 文件重命名为 zip 扩展名,并使用命令 `cp com.example.apk example-apk.zip` 和 `unzip -qq example-apk.zip -d ReactNative` 将其提取到新文件夹中。 -2. 导航到新创建的 ReactNative 文件夹,找到 assets 文件夹。在此文件夹中,您应该找到文件 `index.android.bundle`,该文件以压缩格式包含 React JavaScript。 +2. 导航到新创建的 ReactNative 文件夹,找到 assets 文件夹。在此文件夹中,您应该找到文件 `index.android.bundle`,该文件包含以压缩格式的 React JavaScript。 3. 使用命令 `find . -print | grep -i ".bundle$"` 搜索 JavaScript 文件。 +注意:如果您获得的是 Android App Bundle (.aab) 而不是 APK,请先生成一个通用 APK,然后提取该包: +```bash +# 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 代码(即使是压缩的),您可以 **分析它以查找敏感信息和漏洞**。 +如果检查 `index.android.bundle` 的内容,你会发现应用程序的 JavaScript 代码(即使是经过压缩的),你可以 **分析它以寻找敏感信息和漏洞**。 -由于该包实际上包含了应用程序的所有 JS 代码,因此可以 **将其分割成不同的文件**(可能使其逆向工程更容易),使用 **工具 [react-native-decompiler](https://github.com/numandev1/react-native-decompiler)**。 +由于该包实际上包含了应用程序的所有 JS 代码,因此可以 **将其分成不同的文件**(可能使其逆向工程更容易),使用 **工具 [react-native-decompiler](https://github.com/numandev1/react-native-decompiler)**。 ### Webpack -要进一步分析 JavaScript 代码,您可以将文件上传到 [https://spaceraccoon.github.io/webpack-exploder/](https://spaceraccoon.github.io/webpack-exploder/) 或按照以下步骤操作: +要进一步分析 JavaScript 代码,你可以将文件上传到 [https://spaceraccoon.github.io/webpack-exploder/](https://spaceraccoon.github.io/webpack-exploder/) 或按照以下步骤操作: 1. 在同一目录中创建一个名为 `index.html` 的文件,内容如下: ```html @@ -28,7 +42,7 @@ 3. 通过按 **Command+Option+J for OS X** 或 **Control+Shift+J for Windows** 打开开发者工具栏。 -4. 在开发者工具栏中点击 "Sources"。你应该会看到一个 JavaScript 文件,它被分成文件夹和文件,构成了主包。 +4. 在开发者工具栏中点击 "Sources"。你应该会看到一个分成文件夹和文件的 JavaScript 文件,构成了主包。 如果你找到一个名为 `index.android.bundle.map` 的文件,你将能够以未压缩的格式分析源代码。映射文件包含源映射,这允许你映射压缩的标识符。 @@ -40,42 +54,142 @@ 3. 幸运的是,在侦查过程中在 JavaScript 代码中发现了敏感的硬编码凭证。 +### 快速在包中寻找秘密/端点 + +这些简单的 grep 通常会在压缩的 JS 中浮现出有趣的指示器: +```bash +# 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 代码并重建应用程序**。这应该足以让你 **注入代码** 以进行测试。 +在这种情况下,更改代码很简单。您只需将应用程序重命名为使用扩展名 `.zip` 并提取它。然后您可以**修改此捆绑包中的 JS 代码并重建应用程序**。这应该足以让您**在应用程序中注入代码**以进行测试。 ## Hermes 字节码 -如果包包含 **Hermes 字节码**,你 **将无法访问应用程序的 JavaScript 代码**(甚至无法访问压缩版本)。 +如果捆绑包包含**Hermes 字节码**,您**将无法访问应用程序的 Javascript 代码**(甚至无法访问压缩版本)。 -你可以通过运行以下命令检查包是否包含 Hermes 字节码: +您可以通过运行以下命令检查捆绑包是否包含 Hermes 字节码: ```bash file index.android.bundle index.android.bundle: Hermes JavaScript bytecode, version 96 ``` -然而,您可以使用工具 **[hbctool](https://github.com/bongtrop/hbctool)**、**[hermes-dec](https://github.com/P1sec/hermes-dec)** 或 **[hermes_rs](https://github.com/Pilfer/hermes_rs)** 来 **反汇编字节码**,并且还可以 **将其反编译为一些伪 JS 代码**。要做到这一点,例如可以使用以下命令: +然而,您可以使用工具 **[hbctool](https://github.com/bongtrop/hbctool)**、支持更新字节码版本的 hbctool 更新分支、**[hasmer](https://github.com/lucasbaizer2/hasmer)**、**[hermes_rs](https://github.com/Pilfer/hermes_rs)**(Rust 库/API)或 **[hermes-dec](https://github.com/P1sec/hermes-dec)** 来 **反汇编字节码**,并且 **将其反编译为一些伪 JS 代码**。例如: ```bash +# 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 +hbc-decompiler ./index.android.bundle /tmp/my_output_file.js ``` -### 修改代码并重建 +提示:开源的 Hermes 项目在特定的 Hermes 版本中也提供开发者工具,如 `hbcdump`。如果您构建与生成捆绑包所使用的 Hermes 版本匹配的版本,`hbcdump` 可以转储函数、字符串表和字节码以进行更深入的分析。 -理想情况下,您应该能够修改反汇编的代码(更改比较、值或您需要修改的任何内容),然后**重建字节码**,再重建应用程序。 +### 修改代码并重建 (Hermes) -工具**[hbctool](https://github.com/bongtrop/hbctool)**支持反汇编包并在进行更改后重新构建,但它**仅支持旧版本**的Hermes字节码。 +理想情况下,您应该能够修改反汇编的代码(更改比较、值或您需要修改的任何内容),然后 **重建字节码** 并重建应用程序。 -工具**[hermes-dec](https://github.com/P1sec/hermes-dec)**不支持重建字节码。 +- 原始 **[hbctool](https://github.com/bongtrop/hbctool)** 支持反汇编捆绑包并在更改后重新构建,但历史上仅支持较旧的字节码版本。社区维护的分支扩展了对较新 Hermes 版本(包括中间 80s–96)的支持,通常是修补现代 RN 应用程序的最实用选项。 +- 工具 **[hermes-dec](https://github.com/P1sec/hermes-dec)** 不支持重建字节码(仅反编译器/反汇编器),但在导航逻辑和转储字符串方面非常有用。 +- 工具 **[hasmer](https://github.com/lucasbaizer2/hasmer)** 旨在支持多个 Hermes 版本的反汇编和汇编;汇编仍在成熟中,但在最近的字节码上值得尝试。 -工具**[hermes_rs](https://github.com/Pilfer/hermes_rs)**支持重建字节码,但它实际上是一个库,而不是CLI工具。 +使用类似 hbctool 的汇编器的最小工作流程: +```bash +# 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/](https://newsroom.bedefended.com/hooking-react-native-applications-with-frida/)找到更多信息。 +您可以尝试动态分析应用程序的方法是使用 Frida 启用 React 应用的开发者模式,并使用 **`react-native-debugger`** 附加到它。然而,显然您需要应用的源代码。您可以在 [https://newsroom.bedefended.com/hooking-react-native-applications-with-frida/](https://newsroom.bedefended.com/hooking-react-native-applications-with-frida/) 找到更多信息。 +### 在发布版本中使用 Frida 启用开发支持(注意事项) + +一些应用程序意外地发布了可以切换开发支持的类。如果存在,您可以尝试强制 `getUseDeveloperSupport()` 返回 true: +```javascript +// 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 拦截和固定绕过技术,请参考: + +{{#ref}} +make-apk-accept-ca-certificate.md +{{#endref}} + +{{#ref}} +frida-tutorial/objection-tutorial.md +{{#endref}} + +## 流行 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 中修复。验证输入和库版本。 + +快速检查: +```bash +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://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://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](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 {{#include ../../banners/hacktricks-training.md}}