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

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

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

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!

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.



Le informazioni che possiamo ottenere sono:
- l’analisi del manifesto (AndroidManifest.xml) dove sono esplicitamente segnalate le attività che il file esegue

Che possiamo anche trovare in basso

- L’analisi del codice, che in questo caso non è disponibile
- L’analisi del file
- Le stringhe trovate, come ad esempio

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:
- https://github.com/vincentcox/StaCoAn
- https://github.com/SUPERAndroidAnalyzer/super
- https://github.com/1N3/ReverseAPK
- https://github.com/linkedin/qark
Per capire cosa succede dietro le quinte nell’analisi automatica, passiamo a quella manuale.
Decompilazione APK
Tramite apktool decompilo l’app in modo da averla in una comoda cartella. Il comando utilizzato è
apktool d InsecureBankv2.apk

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

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

Ricompilo l’applicazione con il comando
apktool b InsecureBankv2
Dove InsecureBankv2 è la cartella contenente tutti i file precedentemente estratti

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

La installiamo di nuovo con adb

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

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.

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.

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

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


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.

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


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

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

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)


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$.


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}')"

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:
- Aprire l’applicazione da analizzare (e chiudere tutte le altre per semplicità)
- Comando adb jdwp e prendere nota dell’ID stampato (nel mio caso 16432)
- Digitare a db forward tcp:7777 jdwp:16432
- Ed infine jdb -attach localhost:7777 ed ecco che possiamo iniziare a debuggare

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

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


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




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

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
- https://appsecwiki.com/#/mobilesecurity
- https://manifestsecurity.com/android-application-security/
- https://github.com/OWASP/owasp-mstg/tree/master/Document
- https://www.evilsocket.net/2017/04/27/Android-Applications-Reversing-101/
- https://conference.hitb.org/hitbsecconf2018ams/materials/D1T1%20-%20Federico%20Dotta%20and%20Piergiovanni%20Cipolloni%20-%20Brida%20When%20Burp%20Suite%20Meets%20Frida.pdf
- https://mobile-security.gitbook.io/mobile-security-testing-guide/
- https://god.owasp.de/archive/2018/slides/2018-god-holguera.pdf