InsecureShop é um aplicativo Android projetado para ser intencionalmente vulnerável. O aplicativo serve como uma plataforma para testar suas habilidades de pentesting no Android.
O aplicativo do projeto pode ser encontrado no repositório do GitHub nesse endereço: https://github.com/hax0rgb/InsecureShop
Nessa postagem eu vou mostrar como resolvi os desafios presentes no app.
M7: Insufficient Binary Protection
Para iniciar o teste, foi realizado a engenharia reversa do aplicativo utilizando a ferramenta conhecida como “enjarify”.
Também foi utilizado a ferramenta “apktool” para extrair todos os arquivos presentes no apk.
Credential HardCoded
Analisando o código fonte do app, foi possível encontrar as credenciais utilizadas para acesso ao aplicativo.
Com as credenciais encontradas, foi possível acessar o app.
MASTG-TEST-0003 - Testing Logs for Sensitive Data
Analisando o código fonte da aplicação, foi possível identificar que o app realiza o log das informações passadas para login e senha no aplicativo.
Analisando os logs gerados pelo app, foi possível confirmar essa informação.
shopuser:!ns3csh0p
M9: Insecure Data Storage
Analisando o conteúdo da pasta “shared_prefs” do app, foi possível encontrar o arquivo “Prefs.xml” contendo o usuário e senha salvos em texto claro.
M8: Security Misconfiguration
Bypass Trust Manager
Com acesso ao aplicativo, foi realizado a tentativa de acesso aos produtos listados pelo app, porém as informações não foram carregadas.
Foi possível realizar o bypass da proteção utilizando o seguinte script frida público:
Java.perform(function() {
// TrustManager (Android < 7) //
////////////////////////////////
var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');
var SSLContext = Java.use('javax.net.ssl.SSLContext');
var TrustManager = Java.registerClass({
// Implement a custom TrustManager
name: 'dev.asd.test.TrustManager',
implements: [X509TrustManager],
methods: {
checkClientTrusted: function(chain, authType) {},
checkServerTrusted: function(chain, authType) {},
getAcceptedIssuers: function() {return []; }
}
});
// Prepare the TrustManager array to pass to SSLContext.init()
var TrustManagers = [TrustManager.$new()];
// Get a handle on the init() on the SSLContext class
var SSLContext_init = SSLContext.init.overload(
'[Ljavax.net.ssl.KeyManager;', '[Ljavax.net.ssl.TrustManager;', 'java.security.SecureRandom');
try {
// Override the init method, specifying the custom TrustManager
SSLContext_init.implementation = function(keyManager, trustManager, secureRandom) {
console.log('[+] Bypassing Trustmanager (Android < 7) pinner');
SSLContext_init.call(this, keyManager, TrustManagers, secureRandom);
};
} catch (err) {
console.log('[-] TrustManager (Android < 7) pinner not found');
//console.log(err);
}
// TrustManagerImpl (Android > 7) //
////////////////////////////////////
try {
// Bypass TrustManagerImpl (Android > 7) {1}
var array_list = Java.use("java.util.ArrayList");
var TrustManagerImpl_Activity_1 = Java.use('com.android.org.conscrypt.TrustManagerImpl');
TrustManagerImpl_Activity_1.checkTrustedRecursive.implementation = function(certs, ocspData, tlsSctData, host, clientAuth, untrustedChain, trustAnchorChain, used) {
console.log('[+] Bypassing TrustManagerImpl (Android > 7) checkTrustedRecursive check for: '+ host);
return array_list.$new();
};
} catch (err) {
console.log('[-] TrustManagerImpl (Android > 7) checkTrustedRecursive check not found');
//console.log(err);
errDict[err] = ['com.android.org.conscrypt.TrustManagerImpl', 'checkTrustedRecursive'];
}
try {
// Bypass TrustManagerImpl (Android > 7) {2} (probably no more necessary)
var TrustManagerImpl_Activity_2 = Java.use('com.android.org.conscrypt.TrustManagerImpl');
TrustManagerImpl_Activity_2.verifyChain.implementation = function(untrustedChain, trustAnchorChain, host, clientAuth, ocspData, tlsSctData) {
console.log('[+] Bypassing TrustManagerImpl (Android > 7) verifyChain check for: ' + host);
return untrustedChain;
};
} catch (err) {
console.log('[-] TrustManagerImpl (Android > 7) verifyChain check not found');
//console.log(err);
errDict[err] = ['com.android.org.conscrypt.TrustManagerImpl', 'verifyChain'];
}
});
Dessa forma, foi possível realizar o bypass nessa proteção.
Também foi possível interceptar as requisições realizadas pelo aplicativo.
E assim, acessar o conteúdo dos produtos presentes no app.
Analisando as requisições geradas pelo aplicativo, foi possível notar que a comunicação realizada pelo app e o servidor não possuem criptografia.
Insufficient URL Validation
Analisando o conteúdo do arquivo “AndroidManifest.xml” foi possível identificar a classe responsável pelo webview.
Realizando a análise do código fonte dessa classe, é possível identificar que o app realiza uma verificação, porém acaba carregando a url passada como argumento.
Dessa forma, é possível carregar conteúdo de outros sites dentro do app.
AWS Cognito Misconfigurations
Analisando o arquivo “strings.xml” presente nos arquivos do apk, é possível encontrar o ID do Identity Pool da AWS.
Com a informação encontrada, é possível realizar uma consulta e descobrir o Identity ID da acesso a AWS.
Com o identity id, é possível descobrir mais informações