
Descubriendo vulnerabilidades en firmware mediante análisis concolico y agrupación de funciones.
Firmware Slap combina análisis concolico con agrupación de funciones para el descubrimiento de vulnerabilidades y similitud de funciones en firmware. Firmware Slap está construido como una serie de bibliotecas y exporta la mayoría de la información como pickles o JSON para la integración con otras herramientas.

Las diapositivas de la charla se pueden encontrar aquí
Firmware Slap debe ejecutarse en un entorno virtual. Se ha probado en Python3.6
sudo apt install python3-virtualenv
virtualenv -p python3 fwslap
source fwslap/bin/activate
-- o --
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
#usually best here to open new terminal
mkvirtualenv fwslap -p /usr/bin/python3
workon fwslap
python setup.py install
Necesitarás rabbitmq, docker y (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 requiere JDK 11.
sudo apt install default-jdk
java --version
Si quieres usar las características de Elastic search, ejecuta el script Elasticsearch_and_kibana.sh
Asegúrate de que rabbitmq-server esté en ejecución.
# En una terminal separada, ejecuta esto en el directorio superior "Firmware_Slap"
celery -A firmware_slap.celery_tasks worker --loglevel=info
# Desbordamiento de búfer básico
Discover_And_Dump.py examples/iwconfig -D iwconfig_results
Load_And_View_Results.py iwconfig_results.all.pickle
# Haz clic en Administración en el panel izquierdo
# Haz clic en Objetos guardados
# Haz clic en Importar
# Selecciona 'elastic_export.json' en el directorio elastic de firmware slap
# Navega a Paneles de control en el panel izquierdo y selecciona 'Panel general'
Load_And_View_Results.py iwconfig_results.all.pickle -s
# Inyección de comandos
tar -xvf examples/Almond_libs.tar.gz
Vuln_Discover_Celery.py examples/upload.cgi -L Almond_Root/lib/
# Obtén el firmware usado para los ejemplos
wget https://firmware.securifi.com/AL3_64MB/AL3-R024-64MB
binwalk -Mre AL3-R024-64MB
Inicia un trabajo de celery desde el directorio raíz del proyecto:
# En una terminal separada
celery -A firmware_slap.celery_tasks worker --loglevel=info
En otra ventana de terminal, ejecuta un trabajo de descubrimiento de vulnerabilidades.
$ 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]:
El comando anterior devolverá un objeto en la variable result. Este es un diccionario con todo tipo de información útil sobre la vulnerabilidad. Hay tres claves principales en el objeto: Los argumentos de la función, la memoria y la ubicación inyectada.
In [3]: result.keys()
Out[3]: dict_keys(['args', 'file_name', 'type', 'mem', 'Injected_Location'])
La clave args detalla información sobre el argumento recuperado y cuáles deben ser los valores del argumento para recrear la vulnerabilidad. En el siguiente ejemplo, se recupera un argumento, y para desencadenar la inyección de comandos, ese argumento debe ser un char* que contenga "`reboot`" para desencadenar un reinicio.
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'"}]
El componente de memoria del objeto mantiene un registro de los valores de memoria requeridos establecidos para desencadenar la vulnerabilidad. También ofrece direcciones de pila y direcciones de .text con los comandos ofensivos para establecer las restricciones de memoria requeridas. El primer evento de memoria requerido está en mtd_write_firmware+0x0 y el segundo en mtd_write_firmware+0x38. Se proporciona el ensamblador para ayudar a embellecer futuros trabajos de visualización.
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']}]
Dado que las inyecciones de comandos son las más fáciles de demostrar, he creado una clave de diccionario de conveniencia para mostrar la ubicación de la inyección de comandos fácilmente.
In [4]: result['Injected_Location']
Out[4]: {'base': '0x7ffefde8', 'type': 'char *', 'value': '/bin/mtd_write -o 0 -l 0 write `reboot`'}
El script de agrupación de vulnerabilidades intentará descubrir vulnerabilidades usando el método del Script de descubrimiento de vulnerabilidades de muestra y luego construirá clústeres k-means de un conjunto de funciones dadas en un firmware extraído para encontrar funciones similares a las vulnerables.
$ 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
El comando siguiente toma -F como una función vulnerable conocida. -V como un pickle volcado de una ejecución anterior para no tener que descubrir nuevas vulnerabilidades, y -L para la ruta de las bibliotecas. Un ejemplo de uso:
$ 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 ...