In questo articolo ci occuperemo della ricerca di sequenze di istruzioni presenti nella piattaforma Android (su sistemi ARM) al fine di sfruttare delle vulnerabilità nelle applicazioni, con attacchi di tipo ROP, aggirando i principali sistemi di sicurezza.
Gli attacchi di tipo Return Oriented Programming (ROP, vedi Riquadro 1) si basano su delle sequenze di istruzioni chiamate gadget. Un gadget deve fornire un’operazione usabile, quindi di fondamentale importanza è la loro disponibilità.
I gadget sono istruzioni o sequenze di istruzioni che soddisfano le seguenti condizioni:
Dopo aver trovato le varie sequenze di istruzioni utili (gadget) disponibili non resta che metterli insieme in una “ROP chain” in modo da ottenere l’esecuzione di codice arbitrario (figura 1). In Android (vedi Riquadro 2) tali gadget si possono trovare nelle librerie di sistema, nei file .oat di sistema, nelle librerie dell’applicazione e nei file .oat dell’applicazione.
C’è da aggiungere che un attaccante, all’atto di eseguire un attacco di tipo ROP, potrebbe trovarsi di fronte a diversi limiti dovuti ad esempio all’applicazione o alla particolare vulnerabilità. In una situazione del genere non tutti i gadget disponibili saranno utili all’attacco.
La tecnica di attacco di tipo ROP utilizza codice esistente già nell’applicazione indirizzando il flusso di controllo attraverso l’indirizzo di ritorno. Il concetto è semplice: si tratta di trovare ed eseguire diverse sequenze di istruzioni. Semplificando, i gadget fanno alcune operazioni e alla fine chiamano un indirizzo di ritorno, quindi l’operazione si ripete con il successivo gadget. Il risultato finale consiste nel concatenare tali gadget per ottenere in questo modo il comportamento voluto ed eseguire l’attacco.
Questa tecnica permette di sfruttare delle vulnerabilità aggirando il meccanismo che prevede la separazione di codice e dati. È da sottolineare che gran parte delle contromisure attualmente esistenti (ASLR, DEP, ecc.) sono aggirabili da tecniche avanzate di questo tipo. Gli exploit di tipo ROP possono essere visti come una versione avanzata di quelli Ret2libc.
Un attacco generalmente avviene attraverso i seguenti passi (figura 2):
ART (Android RunTime) è il runtime system software di Android introdotto come alternativa a Dalvik nella versione 4.4 (Kitkat, 31 Ottobre 2013) e introdotto ufficialmente nella versione 5.0 (Lollipop, 12 Novembre 2014). L’introduzione di ART, essenzialmente, riguarda due campi: l’esecuzione delle applicazioni e la garbage collection. Il vantaggio principale di ART su Dalvik è nelle performance delle app in quanto è stata introdotta la compilazione Ahead-Of-Time (AOT) in sostituzione di quella Just-In-Time (JIT), quindi ART precompila il bytecode di una applicazione in codice nativo.
Quello che ci interessa è che con ART abbiamo la presenza di file compilati AOT (file di sistema e file con estensione .odex relativi all’applicazione). In pratica con l’introduzione del compilatore AOT i file delle applicazioni .dex vengono compilati in file .odex, che contengono istruzioni native, al momento dell’installazione e dell’aggiornamento. Inoltre, tutte le app verranno compilate ogni volta che il sistema sul dispositivo viene aggiornato o anche la prima volta che viene avviato. In aggiunta anche l’intero framework viene compilato in un singolo file (boot.oat). Tale file viene chiamato dall’app ogni volta che questa fa riferimento ad un metodo dell’API del framework.
In definitiva, le versioni di Android con ART offrono una maggiore disponibilità di gadget che un attacante può usare per costruire la propria ROP chain.
Ropper (https://github.com/sashs/Ropper) è un tool per la ricerca di gadget in file binari. Sono attualmente supportate diverse architetture (x86, x86_64,MIPS, MIPS64, ARM, ARM THUMB, ARM64, PowerPC, PowerPC64) e diversi tipi di eseguibili (ELF, PE, Mach-O, Raw).
Ropper offre numerose opzioni (figura 3) per la ricerca di gadget che permettono di semplificare non poco il processo di ricerca e selezione. È possibile anche usare Ropper all’interno di uno script Python, ad esempio:
#!/usr/bin/env python
from ropper import RopperService
options = {'color': True,
'all': True,
'inst_count': 6,
'type': 'all',
'detailed': False}
rs = RopperService(options)
rs.addFile('Test.odex', arch='ARMTHUMB')
rs.loadGadgetsFor()
for _, gadget in rs.search(search='pop % r15'):
print(gadget)
In Android su tecnologia ARM i gadget usualmente includono istruzioni che permettono di indicare un registro per un trasferimento del controllo di flusso, ad esempio una POP che ha r14 (LR, link register) o r15 (PC, program counter) tra i suoi operandi, oppure un’istruzione di branching tipo BL, BX e BLX poiché scrivono un indirizzo nel registro r14 e quindi effettuano una chiamata a tale indirizzo.
Un esempio di sessione in Ropper, dove ad esempio filtriamo i risultati contenenti una pop che coinvolge il registro r15, è la seguente:
(Ropper)> help (Ropper)> help file (Ropper)> file Test.odex [INFO] Load gadgets from cache [LOAD] loading... 100% [INFO] File loaded. (Test.odex/ELF/ARM)> help arch (Test.odex/ELF/ARMTHUMB)> arch ARMTHUMB [INFO] Load gadgets from cache [LOAD] loading... 100% [LOAD] removing double gadgets... 100% (Test.odex/ELF/ARMTHUMB)> show information ELF Header ========== Name Value ---- ----- Class BITS_32 Machine ARM Version 1 EntryPoint 0x00000000 ProgramHeader Offset 52 SectionHeader Offset 1118336 Flags 0x05000000 ELF Header Size 52 ProgramHeader Size 32 ProgramHeader Number 5 SectionHeader Size 40 SectionHeader Number 9 (Test.odex/ELF/ARMTHUMB)> search pop % r15 [INFO] Searching for gadgets: pop % r15 [INFO] File: Test.odex 0x000b0c50 (0x000b0c51): pop {r0, r1, r2, r3, r7, pc}; 0x001038d8 (0x001038d9): pop {r0, r1, r2, r4, r5, r7, pc}; 0x00103802 (0x00103803): pop {r0, r1, r3, r4, r5, r6, r7, pc}; 0x000d574c (0x000d574d): pop {r0, r1, r3, r5, r6, r7, pc}; 0x00106874 (0x00106875): pop {r0, r1, r4, r7, pc}; 0x000d06d8 (0x000d06d9): pop {r0, r2, r3, r5, pc}; 0x000bf690 (0x000bf691): pop {r0, r2, r3, r5, r6, pc}; 0x00104c48 (0x00104c49): pop {r0, r2, r3, r5, r7, pc}; 0x000bf728 (0x000bf729): pop {r0, r2, r4, r5, r6, r7, pc}; 0x000d0740 (0x000d0741): pop {r0, r3, r4, r5, r7, pc}; 0x000bf648 (0x000bf649): pop {r0, r3, r5, pc}; 0x000e590c (0x000e590d): pop {r0, r4, r5, pc}; 0x000f3290 (0x000f3291): pop {r1, r2, r3, r4, r6, r7, pc}; 0x0009d948 (0x0009d949): pop {r1, r2, r3, r5, pc}; 0x000f9518 (0x000f9519): pop {r1, r2, r3, r5, r6, r7, pc}; 0x000f32f0 (0x000f32f1): pop {r1, r2, r3, r5, r7, pc}; 0x000c2b38 (0x000c2b39): pop {r1, r2, r4, pc}; 0x000c553c (0x000c553d): pop {r1, r3, r4, r6, r7, pc}; 0x00104cee (0x00104cef): pop {r1, r4, r5, r6, pc}; 0x000d5534 (0x000d5535): pop {r1, r4, r6, r7, pc}; 0x000c2bf8 (0x000c2bf9): pop {r1, r6, r7, pc}; 0x000c54e4 (0x000c54e5): pop {r1, r7, pc}; 0x000e7420 (0x000e7421): pop {r2, r3, r6, pc}; 0x0010680c (0x0010680d): pop {r2, r4, r5, pc}; 0x000e74b8 (0x000e74b9): pop {r2, r4, r6, r7, pc}; 0x001039ca (0x001039cb): pop {r2, r5, r6, pc}; 0x000d4ba0 (0x000d4ba1): pop {r2, r7, pc}; 0x000e5564 (0x000e5565): pop {r4, r6, r7, pc};
A questo punto dopo aver disassemblato tutte le sorgenti (librerie di sistema, boot.oat e file odex dell’applicazione), non ci resta che cercare le sequenze che terminano con una istruzione di ritorno necessarie all’attacco.
In questo articolo abbiamo visto come cercare i gadget per costruire una ROP chain in Android su ARM con Ropper; ed in particolare dove cercarli e cosa cercare per poter eseguire un attacco.
A cura di: Gianluigi Spagnuolo
Nel panorama odierno della sicurezza informatica, la protezione degli endpoint rappresenta un obiettivo imprescindibile per…
I numeri dell’evento Oltre 1000 ospiti, 42 relatori, 20 interventi tematici e 5 Tavole Rotonde:…
Group-IB è un fornitore, con sede a Singapore, di sistemi ad elevata attendibilità per il…
Le interazioni di natura digitale, su rete pubblica o all’interno di reti private, hanno assunto…
La Commissione Europea ha di recente ricordato come “Artificial intelligence (AI) is not science fiction;…
Di seguito il programma della Cyber Crime Conference 2024, che avrà luogo a Roma nei…