Penetration Test di un'Applicazione Mobile – Android

Tempo di lettura: 12 minuti

Ammetto di non aver mai approfondito in maniera adeguata la sicurezza delle applicazioni Mobile sul blog, sia per poco interesse da parte mio, sia per mancanza di tempo, ma ho deciso di scrivere una mini guida abbastanza approfondita in modo che chiunque possa iniziare a capirne il funzionamento, la metodologia e chissà, magari appassionarsi all’argomento.

Per chi non avesse nessun’infarinatura, consiglio Come Funziona un’applicazione Android e Introduzione alla sicurezza di un’applicazione Android, anche se ne potete trovare altri nella categoria Mobile.

Nel seguente articolo utilizzerò un telefono rootato, con al suo interno Xposed con i moduli:

  • Inspeckage
  • SSLUnpinning
  • Rootcloack

L’applicazione in oggetto sarà InsecureBankv2.

NB: se non avete un secondo telefono per fare i test, non fatelo sul vostro principale, in quando il root, se non utilizzato con criterio, riduce di molto la sicurezza del dispositivo e rischia di essere vulnerabile a particolari attacchi. Se volete potete crearne uno virtuale, seguendo questa guida o direttamente quella di Android.

Setup dell’ambiente

Per prima cosa, dobbiamo configurare il telefono in modo tale che possa dialogare con la nostra Kali. Io, utilizzando una macchina virtuale, l’ho connessa in modalità Bridged in modo tale che esponga l’indirizzo IP direttamente sulla rete Wifi.

Dopo aver aperto Burp, imposto il proxy sull’indirizzo IP della rete

Proxy Listener in Burp
Proxy Listener in Burp

Sul telefono, basterà andare in Impostazioni -> Wifi, tener premuto sul Wifi a cui siamo connessi (dipende dalla versione che avete) e cliccare su Modifica. All’interno del menu, impostate il proxy Manuale, inserendo l’indirizzo IP di Burp

Impostazioni Proxy su Android
Impostazioni Proxy su Android

Una volta impostato, basterà importare il certificato di Burp seguendo questa guida di PortSwigger.

Per installare l’applicazione utilizzerò per comodità adb, quindi dopo aver collegato il telefono con il suo cavo alla macchina virtuale, e digitato

adb install
adb install

Avremo la nostra applicazione installata. Avviate sulla Kali AndroServer (il server dell’applicazione) con il comando

python app.py

E voilà, avremo il nostro ambiente pronto per essere testato!

InsecureBankv2
InsecureBankv2

Analisi statica

L’analisi statica, come si evince dal nome, è la fase in cui si analizza il file apk, sia manualmente, sia con tool automatici, al fine di poter trovare vulnerabilità o misconfigurazioni.

Per prima caso andremo ad analizzare il file con MobSF, il quale permette di farsi un’idea iniziale e iniziare a comprendere l’applicazione.

MobSF eseguito
MobSF eseguito
Interfaccia di MobSF
Interfaccia di MobSF
Applicazione analizzata
Applicazione analizzata

Le informazioni che possiamo ottenere sono:

  • l’analisi del manifesto (AndroidManifest.xml) dove sono esplicitamente segnalate le attività che il file esegue
AndroidManifest.xml
AndroidManifest.xml

Che possiamo anche trovare in basso

Lista delle attività, servizi e altro
Lista delle attività, servizi e altro
  • L’analisi del codice, che in questo caso non è disponibile * L’analisi del file * Le stringhe trovate, come ad esempio
Stringhe identificate
Stringhe identificate

Con applicazioni vere solitamente trova molte informazioni e permette di farsi un’idea generale. In questo caso, oltre alle attività, non ha trovato nulla di rilevante.

Altri tool per effettuare analisi automatiche sono:

Decompilazione APK

Tramite apktool decompilo l’app in modo da averla in una comoda cartella. Il comando utilizzato è

apktool d InsecureBankv2.apk
Apk decompilato
Apk decompilato

AndroidManifest.xml contiene la maggior parte dei dettagli di configurazione, incluso il nome del pacchetto, i componenti dell’app, le impostazioni di sicurezza e i permessi. È quello che MobSF analizza e stampa le configurazioni insicure.

Per quanto riguarda le stringhe invece le prende dal file /res/strings.xml

Stringhe trovate
Stringhe trovate

Questo ci fa capire quando sia utile in certi casi fare sempre un passaggio con MobSF, in quanto ci permette di evitare un’analisi manuale (in certi casi).

Ma cosa significa quelli is_admin? Proviamo a capirlo andando a modificarlo e ricompilare l’app.

Compilazione APK

Modifico la stringa inserendo yes

Stringa modificata
Stringa modificata

Ricompilo l’applicazione con il comando

apktool b InsecureBankv2

Dove InsecureBankv2 è la cartella contenente tutti i file precedentemente estratti

App ricompilata
App ricompilata

Con i comandi

keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000







jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore InsecureBankv2.apk alias_name

Andiamo a firmarla nuovamente, altrimenti non potrà essere installata

Apk ricompilato
Apk ricompilato

La installiamo di nuovo con adb

Apk installato nuovamente
Apk installato nuovamente

Ed ecco che abbiamo l’applicazione con un nuovo bottone, probabilmente disponibile solo per gli admin

Nuovo apk
Nuovo apk

Cliccando dice che è ancora Work In Progress, ma è stato un ottimo esercizio per analizzare, decompilare e ricompilare un file apk.

Analisi statica del codice

Per poter leggere il codice java di un’applicazione è necessario utilizzare il tool jadx-gui, il quale decompilerà l’app in maniera automatica e ci permetterà di leggere e capire tutte le funzioni dell’app. In certi casi il codice è ofuscato e jadx fallisce, ma in questo caso è chiaramente leggibile.

Codice Java dell'apk
Codice Java dell'apk

Una volta aperto possiamo sia analizzare file per file il codice alla ricerca di funzioni particolari, sia cercare stringhe come “password”, “token” e similari, in modo da vedere se è rimasta qualche credenziale hardcodata all’interno del file.

Ricerca di informazioni sensibili
Ricerca di informazioni sensibili

In questo caso abbiamo trovato la chiave AES utilizzata per cifrare.

Andando invece a frugare tra le varie funzioni, troviamo una particolare condizione durante il Login

Funzione di Login
Funzione di Login

Il quale dice che se viene inserito il nome utente devadmin, la password viene ignorata.

Inserimento devadmin come username
Inserimento devadmin come username
Bypass del Login
Bypass del Login

Bingo! Siamo dentro l’app senza conoscerne le credenziali.

È possibile bypassare il login anche tramite il modulo app.activity.start di Drozer, come ho spiegato in questa guida.

Un altro tool per l’analisi statica molto comodo è Andromeda.

Bypass dei controlli root

Come potete vedere dallo screenshot l’app segnala che il dispositivo non è rootato, anche se in realtà lo è. Potrei spiegare come bypassare il root ma in realtà il 90% delle volte basta avere un modulo come RootCloak o MagiskHide. Nel caso in cui non funzioni, potrebbe essere necessario usare Frida, che inserirò in una prossima guida probabilmente. Se volete approfondire, questo è un ottimo articolo.

Analisi Dinamica

Nella fase di analisi dinamica andremo ad analizzare il comportamento dell’app, cosa salva all’interno del device, quali chiamate fa al server di riferimento, e via discorrendo.

Analisi all’interno del dispositivo

Una volta installata ed aver fatto qualche operazione, i file che utilizza l’app potrebbero trovarsi sia nella memoria esterna (che è una bad practice, perchè potrebbero essere letti e modificati da qualsiasi altra app) sia nella memoria interna, nel path /data/data/nomepacchetto.

Memoria locale del device
Memoria locale del device

Nella cartella databases solitamente si trova il database utilizzato dall’app per salvare le informazioni, mentre in shared_prefs alcune coppie chiavi:valori, utilizzate per il login o token di sessione.

Controlliamo il database per vedere se ci sono informazioni sensibili al suo interno. Per vederlo direttamente sul nostro pc facciamo una copia in una cartella accessibile dall’esterno

cp mydb /storage/emulated/0/Download/

e lo copiamo sulla nostra kali

adb pull /storage/emulated/0/Download/mydb ./mydb

Ora con un software come SQLIte viewer possiamo tranquillamente analizzarlo

File mydb
File mydb
Credenziali in chiaro all'interno del database
Credenziali in chiaro all'interno del database

Ed ecco altre credenziali hardcodate, con le quali possiamo autenticarci all’applicativo.

Per quanto riguarda la cartella shared_prefs, vediamo che ci potrebbe essere qualche informazione sensibile

Sharedprefs
Sharedprefs

Nel nostro caso abbiamo sia il server e la porta utilizzata per connettersi al server, sia delle credenziali che sembrano encodate o cifrate.

Password cifrata
Password cifrata

Per quanto riguarda lo username, è encodato in base64 e lo abbiamo ricavato. Ma la password sembra cifrata, magari in AES con la chiave trovata prima?

Per scoprirlo, basta tornare sul codice Java, utilizzarne le funzioni che ci servono (in questo caso per pura comodità, in quanto il codice è perfettamente leggibile e possiamo copiarlo, con qualche modifica, per averne una copia funzionante)

Codice Java utilizzato per decifrare
Codice Java utilizzato per decifrare
Password decifrata
Password decifrata

Beh, vuota perché siamo autenticati con devadmin che non ha password.

Per capire se funziona, mi loggo nell’app con le credenziali presenti nel database, danesh/Dinesh@123$.

Sharedprefs si è modificato automaticamente
Sharedprefs si è modificato automaticamente
Password decifrata
Password decifrata

Ed ecco che abbiamo decifrato delle credenziali grazie all’analisi statica effettuata precedentemente.

Logging

È importante che non vengano loggate informazioni sensibili durante l’utilizzo dell’app. Per verificare ciò, basta aprire logcat greppando solo il nome del pacchetto in analisi, con il comando

adb logcat | grep "$(adb shell ps | grep | awk '{print $2}')"
Logcat in azione
Logcat in azione

Come possiamo vedere, in questo caso vengono loggate tutte le informazioni, come password in chiaro o i trasferimenti effettuati.

Debugging con JDWP

Se nel Manifest è attivo il debugging possiamo utilizzarlo per analizzare le funzioni passo passo e potenzialmente bypassare certi controlli. Per debuggare è necessario:

  1. Aprire l’applicazione da analizzare (e chiudere tutte le altre per semplicità)
  2. Comando adb jdwp e prendere nota dell’ID stampato (nel mio caso 16432)
  3. Digitare a db forward tcp:7777 jdwp:16432 4
  4. Ed infine jdb -attach localhost:7777 ed ecco che possiamo iniziare a debuggare
Debugger collegato
Debugger collegato

Per un approfondimento su questo rimando ad un ottimo articolo di FSecure (descrivere questo processo richiederebbe un altro articolo).

External Storage

Come anticipato, salvare file sulla memoria esterna non è consigliato, in quanto questi file potranno essere poi utilizzati da chiunque, poiché non sono protetti come nel caso dei dati salvati nella memoria interna.

Durante il logging e il contemporaneo utilizzo dell’app vediamo come essa cerchi di aprire un file che si trova nella memoria esterna

File esterno richiamato
File esterno richiamato

Ma nella GUI appare che il file non esiste. Proviamo a crearne uno, inserendo un javascript

File html creato e copiato sul device
File html creato e copiato sul device
Attacco XSS
Attacco XSS

Ed ecco che il nostro Javascript è stato eseguito. Ciò significa che l’app è vulnerabile ad un attacco Cross Site Scripting da parte da altre app, in quando tutti possono accedere a quel percorso e modificarne i file.

Per un’analisi dinamica omnicomprensiva io ho sempre utilizzato Inspeckage, il quale permette di “attaccarsi” all’app ed analizzare tutte le chiamare, le funzioni e

App Inspeckage
App Inspeckage
Inspeackage
Inspeackage
Chiave AES
Chiave AES
FIle letti e scritti durante l'esecuzione
FIle letti e scritti durante l'esecuzione

Come potete vedere, tante delle informazioni che abbiamo ricavato in maniera manuale, Inspeckage le trova durante l’utilizzo dell’app, in modo che siano già tutte in un’unica interfaccia.

Conclusioni

Ho volutamente evitato la parte di analisi delle API, in quanto sconfinano nella parte delle vulnerabilità Web, ma non dimentichiamoci che oltre a tutto ciò che abbiamo visto nell’articolo, rimane il testing di tutte le chiamate verso il server

Chiamate API
Chiamate API
che potrebbero essere vulnerabili ai classici attacchi di SQLInjection, XSS, IDOR e via discorrendo.

Come abbiamo visto l’analisi di un’applicazione Android comprende diverse parti, diverse metodologie ed è decisamente più complessa di una normale applicazione web. L’apk utilizzato come esempio ha altre vulnerabilità che ho deciso di non introdurre, ma se volete potete trovare altri esempi a questo indirizzo.

Dopo aver scritto questo articolo ho scoperto l’esistenza di un’altra applicazione vulnerabile, che vi consiglio se volete fare altra pratica.

Risorse utili