mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/mobile-pentesting/android-app-pentesting/react-native-a
This commit is contained in:
parent
6f8af7c42b
commit
07c737a5af
@ -1,8 +1,8 @@
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
# Análisis de Aplicaciones React Native
|
||||
|
||||
Para confirmar si la aplicación fue construida sobre el framework React Native, sigue estos pasos:
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Para confirmar si la aplicación fue construida sobre el marco de React Native, sigue estos pasos:
|
||||
|
||||
1. Cambia el nombre del archivo APK con una extensión zip y extráelo a una nueva carpeta usando el comando `cp com.example.apk example-apk.zip` y `unzip -qq example-apk.zip -d ReactNative`.
|
||||
|
||||
@ -10,15 +10,29 @@ Para confirmar si la aplicación fue construida sobre el framework React Native,
|
||||
|
||||
3. Usa el comando `find . -print | grep -i ".bundle$"` para buscar el archivo JavaScript.
|
||||
|
||||
## Código Javascript
|
||||
Nota: Si se te proporciona un Android App Bundle (.aab) en lugar de un APK, genera primero un APK universal y luego extrae el bundle:
|
||||
```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
|
||||
|
||||
Si al revisar el contenido de `index.android.bundle` encuentras el código JavaScript de la aplicación (incluso si está minificado), puedes **analizarlo para encontrar información sensible y vulnerabilidades**.
|
||||
# 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 Code
|
||||
|
||||
Dado que el bundle contiene en realidad todo el código JS de la aplicación, es posible **dividirlo en diferentes archivos** (potencialmente facilitando su ingeniería inversa) usando la **herramienta [react-native-decompiler](https://github.com/numandev1/react-native-decompiler)**.
|
||||
Si al verificar el contenido de `index.android.bundle` encuentras el código JavaScript de la aplicación (incluso si está minificado), puedes **analizarlo para encontrar información sensible y vulnerabilidades**.
|
||||
|
||||
Dado que el bundle contiene en realidad todo el código JS de la aplicación, es posible **dividirlo en diferentes archivos** (potencialmente facilitando su ingeniería inversa) utilizando la **herramienta [react-native-decompiler](https://github.com/numandev1/react-native-decompiler)**.
|
||||
|
||||
### Webpack
|
||||
|
||||
Para analizar más a fondo el código JavaScript, puedes subir el archivo a [https://spaceraccoon.github.io/webpack-exploder/](https://spaceraccoon.github.io/webpack-exploder/) o seguir estos pasos:
|
||||
Para analizar aún más el código JavaScript, puedes subir el archivo a [https://spaceraccoon.github.io/webpack-exploder/](https://spaceraccoon.github.io/webpack-exploder/) o seguir estos pasos:
|
||||
|
||||
1. Crea un archivo llamado `index.html` en el mismo directorio con el siguiente código:
|
||||
```html
|
||||
@ -26,56 +40,156 @@ Para analizar más a fondo el código JavaScript, puedes subir el archivo a [htt
|
||||
```
|
||||
2. Abre el archivo `index.html` en Google Chrome.
|
||||
|
||||
3. Abre la Developer Toolbar presionando **Command+Option+J para OS X** o **Control+Shift+J para Windows**.
|
||||
3. Abre la Barra de Herramientas del Desarrollador presionando **Command+Option+J para OS X** o **Control+Shift+J para Windows**.
|
||||
|
||||
4. Haz clic en "Sources" en la Developer Toolbar. Deberías ver un archivo JavaScript que está dividido en carpetas y archivos, formando el paquete principal.
|
||||
4. Haz clic en "Sources" en la Barra de Herramientas del Desarrollador. Deberías ver un archivo JavaScript que está dividido en carpetas y archivos, formando el paquete principal.
|
||||
|
||||
Si encuentras un archivo llamado `index.android.bundle.map`, podrás analizar el código fuente en un formato no minificado. Los archivos de mapa contienen mapeo de origen, lo que te permite mapear identificadores minificados.
|
||||
|
||||
Para buscar credenciales sensibles y endpoints, sigue estos pasos:
|
||||
Para buscar credenciales sensibles y puntos finales, sigue estos pasos:
|
||||
|
||||
1. Identifica palabras clave sensibles para analizar el código JavaScript. Las aplicaciones de React Native a menudo utilizan servicios de terceros como Firebase, endpoints de servicio AWS S3, claves privadas, etc.
|
||||
1. Identifica palabras clave sensibles para analizar el código JavaScript. Las aplicaciones de React Native a menudo utilizan servicios de terceros como Firebase, puntos finales del servicio AWS S3, claves privadas, etc.
|
||||
|
||||
2. En este caso específico, se observó que la aplicación estaba utilizando el servicio Dialogflow. Busca un patrón relacionado con su configuración.
|
||||
|
||||
3. Fue afortunado que se encontraran credenciales sensibles codificadas en el código JavaScript durante el proceso de reconocimiento.
|
||||
3. Fue afortunado que se encontraran credenciales sensibles codificadas de forma rígida en el código JavaScript durante el proceso de reconocimiento.
|
||||
|
||||
### Búsqueda rápida de secretos/puntos finales en paquetes
|
||||
|
||||
Estos simples greps a menudo revelan indicadores interesantes incluso en JS minificado:
|
||||
```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*:)"
|
||||
```
|
||||
Si sospechas de marcos de actualización Over-The-Air, también busca:
|
||||
- Microsoft App Center / claves de implementación de CodePush
|
||||
- Configuración de Expo EAS Updates (`expo-updates`, `expo\.io`, certificados de firma)
|
||||
|
||||
### Cambiar el código JS y reconstruir
|
||||
|
||||
En este caso, cambiar el código es fácil. Solo necesitas renombrar la aplicación para usar la extensión `.zip` y extraerla. Luego puedes **modificar el código JS dentro de este paquete y reconstruir la aplicación**. Esto debería ser suficiente para permitirte **inyectar código** en la aplicación con fines de prueba.
|
||||
|
||||
## Código de bytes de Hermes
|
||||
## Bytecode de Hermes
|
||||
|
||||
Si el paquete contiene **código de bytes de Hermes**, **no podrás acceder al código Javascript** de la aplicación (ni siquiera a la versión minificada).
|
||||
Si el paquete contiene **bytecode de Hermes**, **no podrás acceder al código Javascript** de la aplicación (ni siquiera a la versión minificada).
|
||||
|
||||
Puedes verificar si el paquete contiene código de bytes de Hermes ejecutando el siguiente comando:
|
||||
Puedes verificar si el paquete contiene bytecode de Hermes ejecutando el siguiente comando:
|
||||
```bash
|
||||
file index.android.bundle
|
||||
index.android.bundle: Hermes JavaScript bytecode, version 96
|
||||
```
|
||||
Sin embargo, puedes usar las herramientas **[hbctool](https://github.com/bongtrop/hbctool)**, **[hermes-dec](https://github.com/P1sec/hermes-dec)** o **[hermes_rs](https://github.com/Pilfer/hermes_rs)** para **desensamblar el bytecode** y también para **decompilarlo a algún código JS pseudo**. Para hacer esto, por ejemplo, estos comandos:
|
||||
Sin embargo, puedes usar las herramientas **[hbctool](https://github.com/bongtrop/hbctool)**, forks actualizados de hbctool que soportan versiones más nuevas de bytecode, **[hasmer](https://github.com/lucasbaizer2/hasmer)**, **[hermes_rs](https://github.com/Pilfer/hermes_rs)** (biblioteca/API de Rust), o **[hermes-dec](https://github.com/P1sec/hermes-dec)** para **desensamblar el bytecode** y también para **decompilarlo a algún código pseudo JS**. Por ejemplo:
|
||||
```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
|
||||
```
|
||||
### Cambiar código y reconstruir
|
||||
Tip: El proyecto de código abierto Hermes también incluye herramientas para desarrolladores como `hbcdump` en versiones específicas de Hermes. Si construyes la versión de Hermes que coincide con la utilizada para producir el paquete, `hbcdump` puede volcar funciones, tablas de cadenas y bytecode para un análisis más profundo.
|
||||
|
||||
Idealmente, deberías poder modificar el código desensamblado (cambiando una comparación, un valor o lo que necesites modificar) y luego **reconstruir el bytecode** y luego reconstruir la aplicación.
|
||||
### Cambiar código y reconstruir (Hermes)
|
||||
|
||||
La herramienta **[hbctool](https://github.com/bongtrop/hbctool)** soporta desensamblar el paquete y volver a construirlo después de que se hayan realizado los cambios, sin embargo, **solo soporta versiones antiguas** del bytecode de Hermes.
|
||||
Idealmente deberías poder modificar el código desensamblado (cambiando una comparación, o un valor o lo que necesites modificar) y luego **reconstruir el bytecode** y reconstruir la aplicación.
|
||||
|
||||
La herramienta **[hermes-dec](https://github.com/P1sec/hermes-dec)** no soporta la reconstrucción del bytecode.
|
||||
- El **[hbctool](https://github.com/bongtrop/hbctool)** original soporta desensamblar el paquete y volver a construirlo después de los cambios, pero históricamente solo soportó versiones de bytecode más antiguas. Los forks mantenidos por la comunidad extienden el soporte a versiones más nuevas de Hermes (incluyendo mediados de los 80–96) y a menudo son la opción más práctica para parchear aplicaciones modernas de RN.
|
||||
- La herramienta **[hermes-dec](https://github.com/P1sec/hermes-dec)** no soporta la reconstrucción del bytecode (solo descompilador/desensamblador), pero es muy útil para navegar la lógica y volcar cadenas.
|
||||
- La herramienta **[hasmer](https://github.com/lucasbaizer2/hasmer)** tiene como objetivo soportar tanto desensamblaje como ensamblaje para múltiples versiones de Hermes; el ensamblaje aún está madurando pero vale la pena probar en bytecode reciente.
|
||||
|
||||
La herramienta **[hermes_rs](https://github.com/Pilfer/hermes_rs)** soporta la reconstrucción del bytecode, pero en realidad es una biblioteca y no una herramienta de línea de comandos.
|
||||
Un flujo de trabajo mínimo con ensambladores similares a 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)
|
||||
```
|
||||
Note que el formato de bytecode de Hermes está versionado y el ensamblador debe coincidir exactamente con el formato en disco. Si recibe errores de formato, cambie a un fork/alternativa actualizado o reconstruya las herramientas de Hermes correspondientes.
|
||||
|
||||
## Análisis Dinámico
|
||||
|
||||
Podrías intentar analizar dinámicamente la aplicación usando Frida para habilitar el modo desarrollador de la aplicación React y usar **`react-native-debugger`** para conectarte a ella. Sin embargo, para esto aparentemente necesitas el código fuente de la aplicación. Puedes encontrar más información sobre esto en [https://newsroom.bedefended.com/hooking-react-native-applications-with-frida/](https://newsroom.bedefended.com/hooking-react-native-applications-with-frida/).
|
||||
Podrías intentar analizar dinámicamente la aplicación usando Frida para habilitar el modo de desarrollador de la aplicación React y usar **`react-native-debugger`** para conectarte a ella. Sin embargo, para esto aparentemente necesitas el código fuente de la aplicación. Puedes encontrar más información sobre esto en [https://newsroom.bedefended.com/hooking-react-native-applications-with-frida/](https://newsroom.bedefended.com/hooking-react-native-applications-with-frida/).
|
||||
|
||||
### Habilitando el Soporte para Desarrolladores en la versión de lanzamiento con Frida (advertencias)
|
||||
|
||||
Algunas aplicaciones accidentalmente envían clases que hacen que el Soporte para Desarrolladores sea activable. Si están presentes, puedes intentar forzar que `getUseDeveloperSupport()` devuelva verdadero:
|
||||
```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);
|
||||
}
|
||||
});
|
||||
```
|
||||
Advertencia: En las versiones de lanzamiento correctamente construidas, `DevSupportManagerImpl` y las clases relacionadas solo para depuración son eliminadas y cambiar esta bandera puede hacer que la aplicación se bloquee o no tenga efecto. Cuando esto funciona, típicamente puedes exponer el menú de desarrollo y adjuntar depuradores/inspectores.
|
||||
|
||||
### Intercepción de red en aplicaciones RN
|
||||
|
||||
React Native Android típicamente se basa en OkHttp en segundo plano (a través del módulo nativo `Networking`). Para interceptar/observar tráfico en un dispositivo no rooteado durante pruebas dinámicas:
|
||||
- Usa un proxy del sistema + confía en el CA del usuario o utiliza otras técnicas genéricas de bypass de TLS en Android.
|
||||
- Consejo específico de RN: si la aplicación incluye Flipper en la versión de lanzamiento por error (herramientas de depuración), el plugin de red de Flipper puede exponer solicitudes/respuestas.
|
||||
|
||||
Para técnicas genéricas de intercepción y bypass de pinning en Android, consulta:
|
||||
|
||||
{{#ref}}
|
||||
make-apk-accept-ca-certificate.md
|
||||
{{#endref}}
|
||||
|
||||
{{#ref}}
|
||||
frida-tutorial/objection-tutorial.md
|
||||
{{#endref}}
|
||||
|
||||
## Problemas recientes en bibliotecas RN populares (qué buscar)
|
||||
|
||||
Al auditar módulos de terceros visibles en el paquete JS o bibliotecas nativas, verifica vulnerabilidades conocidas y verifica versiones en `package.json`/`yarn.lock`.
|
||||
|
||||
- react-native-mmkv (Android): las versiones anteriores a 2.11.0 registraron la clave de cifrado opcional en los registros de Android. Si ADB/logcat está disponible, se podrían recuperar secretos. Asegúrate de tener >= 2.11.0. Indicadores: uso de `react-native-mmkv`, declaraciones de registro que mencionan la inicialización de MMKV con cifrado. CVE-2024-21668.
|
||||
- react-native-document-picker: las versiones < 9.1.1 eran vulnerables a la traversía de ruta en Android (selección de archivos), corregido en 9.1.1. Valida entradas y versión de la biblioteca.
|
||||
|
||||
Comprobaciones rápidas:
|
||||
```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
|
||||
```
|
||||
## Referencias
|
||||
|
||||
- [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 registra la clave de cifrado de logs en Android, corregido en v2.11.0 (NVD): https://nvd.nist.gov/vuln/detail/CVE-2024-21668
|
||||
- hbctool (y forks) para ensamblar/desensamblar Hermes: https://github.com/bongtrop/hbctool
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user