Análise de Aplicações React Native

Reading time: 10 minutes

tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks

Para confirmar se a aplicação foi construída no framework React Native, siga estes passos:

  1. Renomeie o arquivo APK com uma extensão zip e extraia-o para uma nova pasta usando o comando cp com.example.apk example-apk.zip e unzip -qq example-apk.zip -d ReactNative.

  2. Navegue até a nova pasta ReactNative e localize a pasta assets. Dentro desta pasta, você deve encontrar o arquivo index.android.bundle, que contém o JavaScript React em um formato minificado.

  3. Use o comando find . -print | grep -i ".bundle$" para procurar o arquivo JavaScript.

Nota: Se você receber um Android App Bundle (.aab) em vez de um APK, gere um APK universal primeiro e depois extraia o 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

# 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/

Código Javascript

Se ao verificar o conteúdo do index.android.bundle você encontrar o código JavaScript da aplicação (mesmo que minificado), você pode analisá-lo para encontrar informações sensíveis e vulnerabilidades.

Como o bundle contém na verdade todo o código JS da aplicação, é possível dividi-lo em diferentes arquivos (potencialmente facilitando sua engenharia reversa) usando a ferramenta react-native-decompiler.

Webpack

Para analisar ainda mais o código JavaScript, você pode fazer o upload do arquivo para https://spaceraccoon.github.io/webpack-exploder/ ou seguir estes passos:

  1. Crie um arquivo chamado index.html no mesmo diretório com o seguinte código:
html
<script src="./index.android.bundle"></script>
  1. Abra o arquivo index.html no Google Chrome.

  2. Abra a Developer Toolbar pressionando Command+Option+J para OS X ou Control+Shift+J para Windows.

  3. Clique em "Sources" na Developer Toolbar. Você deve ver um arquivo JavaScript que está dividido em pastas e arquivos, formando o pacote principal.

Se você encontrar um arquivo chamado index.android.bundle.map, poderá analisar o código-fonte em um formato não minificado. Os arquivos de mapa contêm mapeamento de origem, que permite mapear identificadores minificados.

Para procurar credenciais sensíveis e endpoints, siga estas etapas:

  1. Identifique palavras-chave sensíveis para analisar o código JavaScript. Aplicações React Native costumam usar serviços de terceiros como Firebase, endpoints de serviço AWS S3, chaves privadas, etc.

  2. Neste caso específico, observou-se que a aplicação estava usando o serviço Dialogflow. Procure por um padrão relacionado à sua configuração.

  3. Foi uma sorte que credenciais sensíveis codificadas foram encontradas no código JavaScript durante o processo de reconhecimento.

Caça rápida a segredos/endpoints em pacotes

Esses greps simples frequentemente revelam indicadores interessantes mesmo em 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*:)"

Se você suspeitar de frameworks de atualização Over-The-Air, também procure por:

  • Chaves de implantação do Microsoft App Center / CodePush
  • Configuração de Atualizações do Expo EAS (expo-updates, expo\.io, certificados de assinatura)

Mudar o código JS e reconstruir

Neste caso, mudar o código é fácil. Você só precisa renomear o aplicativo para usar a extensão .zip e extraí-lo. Então você pode modificar o código JS dentro deste pacote e reconstruir o aplicativo. Isso deve ser suficiente para permitir que você injete código no aplicativo para fins de teste.

Código de bytes Hermes

Se o pacote contiver código de bytes Hermes, você não poderá acessar o código Javascript do aplicativo (nem mesmo a versão minificada).

Você pode verificar se o pacote contém código de bytes Hermes executando o seguinte comando:

bash
file index.android.bundle
index.android.bundle: Hermes JavaScript bytecode, version 96

No entanto, você pode usar as ferramentas hbctool, forks atualizados do hbctool que suportam versões mais recentes de bytecode, hasmer, hermes_rs (biblioteca/APIs Rust), ou hermes-dec para desmontar o bytecode e também para decompilar para algum código pseudo JS. Por exemplo:

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

Dica: O projeto open-source Hermes também fornece ferramentas de desenvolvedor como hbcdump em versões específicas do Hermes. Se você compilar a versão correspondente do Hermes usada para produzir o bundle, hbcdump pode despejar funções, tabelas de strings e bytecode para uma análise mais profunda.

Mudar código e recompilar (Hermes)

Idealmente, você deve ser capaz de modificar o código desmontado (mudando uma comparação, ou um valor ou qualquer coisa que você precise modificar) e então recompilar o bytecode e recompilar o aplicativo.

  • O hbctool original suporta desmontar o bundle e reconstruí-lo após as alterações, mas historicamente suportou apenas versões mais antigas de bytecode. Forks mantidos pela comunidade estendem o suporte a versões mais novas do Hermes (incluindo meados dos anos 80–96) e muitas vezes são a opção mais prática para corrigir aplicativos RN modernos.
  • A ferramenta hermes-dec não suporta a recompilação do bytecode (apenas decompilador/desmontador), mas é muito útil para navegar na lógica e despejar strings.
  • A ferramenta hasmer visa suportar tanto a desmontagem quanto a montagem para várias versões do Hermes; a montagem ainda está se desenvolvendo, mas vale a pena tentar em bytecode recente.

Um fluxo de trabalho mínimo com montadores semelhantes ao 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 o formato de bytecode do Hermes é versionado e o montador deve corresponder exatamente ao formato em disco. Se você receber erros de formato, mude para um fork/alternativa atualizado ou reconstrua as ferramentas Hermes correspondentes.

Análise Dinâmica

Você pode tentar analisar dinamicamente o aplicativo usando o Frida para habilitar o modo de desenvolvedor do aplicativo React e usar react-native-debugger para se conectar a ele. No entanto, para isso, você aparentemente precisa do código-fonte do aplicativo. Você pode encontrar mais informações sobre isso em https://newsroom.bedefended.com/hooking-react-native-applications-with-frida/.

Habilitando o Suporte ao Desenvolvedor em release com Frida (advertências)

Alguns aplicativos acidentalmente enviam classes que tornam o Suporte ao Desenvolvedor alternável. Se presente, você pode tentar forçar getUseDeveloperSupport() a retornar 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);
}
});

Atenção: Em builds de release corretamente construídos, DevSupportManagerImpl e classes relacionadas apenas para depuração são removidas e mudar esta flag pode fazer o app travar ou não ter efeito. Quando isso funciona, você pode tipicamente expor o menu de desenvolvedor e anexar depuradores/inspetores.

Interceptação de rede em apps RN

React Native Android geralmente depende do OkHttp por baixo dos panos (via o módulo nativo Networking). Para interceptar/observar tráfego em um dispositivo não enraizado durante testes dinâmicos:

  • Use proxy do sistema + confie no CA do usuário ou use outras técnicas genéricas de bypass de TLS do Android.
  • Dica específica do RN: se o app incluir Flipper na release por engano (ferramentas de depuração), o plugin de Rede do Flipper pode expor requisições/respostas.

Para técnicas genéricas de interceptação e bypass de pinning do Android, consulte:

Make APK Accept CA Certificate

Objection Tutorial

Problemas recentes em bibliotecas populares do RN (o que procurar)

Ao auditar módulos de terceiros visíveis no bundle JS ou libs nativas, verifique por vulnerabilidades conhecidas e verifique versões em package.json/yarn.lock.

  • react-native-mmkv (Android): versões anteriores a 2.11.0 registravam a chave de criptografia opcional nos logs do Android. Se ADB/logcat estiver disponível, segredos poderiam ser recuperados. Assegure-se de usar >= 2.11.0. Indicadores: uso de react-native-mmkv, declarações de log mencionando a inicialização do MMKV com criptografia. CVE-2024-21668.
  • react-native-document-picker: versões < 9.1.1 eram vulneráveis a travessia de caminho no Android (seleção de arquivo), corrigido na 9.1.1. Valide entradas e versão da biblioteca.

Verificações 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

Referências

tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks