
Scoperta di vulnerabilità nel firmware tramite analisi concolica e clustering di funzioni.
Firmware slap combina l'analisi concolica con il clustering di funzioni per la scoperta di vulnerabilità e la similarità di funzioni nel firmware. Firmware slap è costruito come una serie di librerie e esporta la maggior parte delle informazioni come pickle o JSON per l'integrazione con altri strumenti.

Le slide del talk sono disponibili qui
Firmware slap dovrebbe essere eseguito in un ambiente virtuale. È stato testato su Python3.6
sudo apt install python3-virtualenv
virtualenv -p python3 fwslap
source fwslap/bin/activate
-- oppure --
cd ~
mkdir .virtualenvs
pip install virtualenv
which virtualenv #note path warnings
pip install virtualenvwrapper
echo "export PATH=$PATH:~/.local/bin" >> ~/.bashrc
echo "export WORKON_HOME=~/.virtualenvs" >> ~/.bashrc
echo "source ~/.local/bin/virtualenvwrapper.sh" >> ~/.bashrc
#di solito è meglio aprire un nuovo terminale qui
mkvirtualenv fwslap -p /usr/bin/python3
workon fwslap
python setup.py install
Avrai bisogno di rabbitmq, docker e (radare2 o Ghidra)
# Ubuntu
sudo apt install rabbitmq-server docker.io
# OSX
brew install rabbitmq
# Radare2
git clone https://github.com/radare/radare2.git
sudo ./radare2/sys/install.sh
# Ghidra
wget https://ghidra-sre.org/ghidra_9.0.4_PUBLIC_20190516.zip
unzip ghidra_9.0.4_PUBLIC_20190516.zip -d ghidra
echo "export PATH=\$PATH:$PWD/ghidra/ghidra_9.0.4/support" >> ~/.bashrc
Ghidra richiede JDK 11.
sudo apt install default-jdk
java --version
Se vuoi usare le funzionalità di Elastic search esegui lo script Elasticsearch_and_kibana.sh
Assicurati che rabbitmq-server sia in esecuzione.
# In un terminale separato, esegui questo dalla directory principale "Firmware_Slap"
celery -A firmware_slap.celery_tasks worker --loglevel=info
# Buffer overflow di base
Discover_And_Dump.py examples/iwconfig -D iwconfig_results
Load_And_View_Results.py iwconfig_results.all.pickle
# Clicca su "management" nel pannello di sinistra
# Clicca su "Saved Objects"
# Clicca su "Import"
# Seleziona 'elastic_export.json' nella directory elastic all'interno di firmware slap
# Naviga su "dashboards" nel pannello di sinistra e seleziona 'Overview Dashboard'
Load_And_View_Results.py iwconfig_results.all.pickle -s
# Iniezione di comandi
tar -xvf examples/Almond_libs.tar.gz
Vuln_Discover_Celery.py examples/upload.cgi -L Almond_Root/lib/
# Scarica il firmware usato per gli esempi
wget https://firmware.securifi.com/AL3_64MB/AL3-R024-64MB
binwalk -Mre AL3-R024-64MB
Avvia un worker celery dalla directory principale del progetto:
# In un terminale separato
celery -A firmware_slap.celery_tasks worker --loglevel=info
In una finestra terminale diversa, esegui un job di scoperta di vulnerabilità.
$ Vuln_Discover_Celery.py Almond_Root/etc_ro/lighttpd/www/cgi-bin/upload_bootloader.cgi -L Almond_Root/lib/
[+] Getting argument functions
[+] Analyzing 1 functions
0%| | 0/1 [00:01<?, ?it/s]
{ 'Injected_Location': { 'base': '0x7ffefde8',
........................ SNIP ......................
'type': 'Command Injection'}
Python 3.5.2 (default, Nov 12 2018, 13:43:14)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.3.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]:
Il comando sopra restituirà un oggetto nella variabile result. Questo è un dizionario con tutti i tipi di informazioni fantastiche sulla vulnerabilità. Ci sono tre chiavi principali nell'oggetto: Gli argomenti della funzione, La memoria e la posizione iniettata.
In [3]: result.keys()
Out[3]: dict_keys(['args', 'file_name', 'type', 'mem', 'Injected_Location'])
La chiave args dettaglierà le informazioni sull'argomento recuperato e quali devono essere i valori degli argomenti per riprodurre la vulnerabilità. Nell'esempio seguente, è stato recuperato un argomento e per attivare l'iniezione di comandi quell'argomento deve essere un char* che contenga "`reboot`" per attivare un riavvio.
In [1]: result['args']
Out[1]:
[{'base': 'a1',
'type': 'int',
'value': "0x0 -> b'`reboot`\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x00'"}]
La componente memoria dell'oggetto tiene traccia dei valori di memoria richiesti per attivare la vulnerabilità. Offre anche indirizzi di stack e indirizzi .text con i comandi offensivi per impostare i vincoli di memoria richiesti. Il primo evento di memoria richiesto è a mtd_write_firmware+0x0 e il secondo a mtd_write_firmware+0x38. Viene fornito l'assembly per aiutare a migliorare il lavoro di visualizzazione futuro.
In [2]: result['mem']
Out[2]:
[{'BBL_ADDR': '0x401138',
'BBL_DESC': {'DESCRIPTION': 'mtd_write_firmware+0x0 in upload_bootloader.cgi (0x401138)',
'DISASSEMBLY': ['0x401138:\tlui\t$gp, 0x42',
'0x40113c:\taddiu\t$sp, $sp, -0x228',
'0x401140:\taddiu\t$gp, $gp, -0x5e90',
'0x401144:\tlw\t$t9, -0x7f84($gp)',
'0x401148:\tsw\t$a2, 0x10($sp)',
'0x40114c:\tlui\t$a2, 0x40',
'0x401150:\tmove\t$a3, $a1',
'0x401154:\tsw\t$ra, 0x224($sp)',
'0x401158:\tsw\t$gp, 0x18($sp)',
'0x40115c:\tsw\t$a0, 0x14($sp)',
'0x401160:\taddiu\t$a1, $zero, 0x200',
'0x401164:\taddiu\t$a0, $sp, 0x20',
'0x401168:\tjalr\t$t9',
'0x40116c:\taddiu\t$a2, $a2, 0x196c']},
'DATA': "b'`reboot`\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00'",
'DATA_ADDRS': ['0x0']},
{'BBL_ADDR': '0x401170',
'BBL_DESC': {'DESCRIPTION': 'mtd_write_firmware+0x38 in upload_bootloader.cgi (0x401170)',
'DISASSEMBLY': ['0x401170:\tlw\t$gp, 0x18($sp)',
'0x401174:\tnop\t',
'0x401178:\tlw\t$t9, -0x7f68($gp)',
'0x40117c:\tnop\t',
'0x401180:\tjalr\t$t9',
'0x401184:\taddiu\t$a0, $sp, 0x20']},
'DATA': "b'/bin/mtd_write -o 0 -l 0 write `reboot`'",
'DATA_ADDRS': ['0x7ffefe07']}]
Poiché le iniezioni di comandi sono le più facili da dimostrare, ho creato una chiave del dizionario di convenienza per mostrare facilmente la posizione dell'iniezione di comandi.
In [4]: result['Injected_Location']
Out[4]: {'base': '0x7ffefde8', 'type': 'char *', 'value': '/bin/mtd_write -o 0 -l 0 write `reboot`'}
Lo script di clustering delle vulnerabilità tenterà di scoprire vulnerabilità utilizzando il metodo nello script di scoperta vulnerabilità di esempio e quindi costruirà cluster k-means di un insieme di funzioni date su un firmware estratto per trovare funzioni simili a quelle vulnerabili.
$ Vuln_Cluster_Celery.py -h
usage: Vuln_Cluster_Celery.py [-h] [-L LD_PATH] [-F FUNCTION] [-V VULN_PICKLE]
Directory
positional arguments:
Directory
optional arguments:
-h, --help show this help message and exit
-L LD_PATH, --LD_PATH LD_PATH
Path to libraries to load
-F FUNCTION, --Function FUNCTION
-V VULN_PICKLE, --Vuln_Pickle VULN_PICKLE
Il comando seguente prende -F come funzione nota vulnerabile. -V come pickle salvato da un'esecuzione precedente per non dover scoprire nuove vulnerabilità e -L per il percorso della libreria. Un esempio di utilizzo:
$ python Vuln_Cluster_Celery.py -F mtd_write_firmware -L Almond_Root/lib/ Almond_Root/etc_ro/lighttpd/www/cgi-bin/
[+] Reading Files
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 2.80it/s]
Getting functions from executables
Starting main
... Snip ...