DataCon2021优秀解题思路分享:物联网固件自动化漏洞挖掘WP (浙江大学 go-go-go战队)

WriteUp 2周前 admin
86 0 0
DataCon2021优秀解题思路分享:物联网固件自动化漏洞挖掘WP (浙江大学 go-go-go战队)

一、题目介绍

万物互联时代的到来,物联网设备越来越多地参与到我们的生活中,各类物联网产品迭代更新速度极快,导致传统人工漏洞挖掘方式在效率上达到瓶颈,这就要求设计自动化的解决方案来辅助甚至完成漏洞挖掘工作。赛题将给出一批固件,请设计自动化的检测方案来定位可能会造成命令注入、格式化字符串和密码学误用危险函数的位置(具体危险函数如下),并排除确定不能被利用的危险函数,找到可能利用的危险函数。

[‘popen’, ‘system’, ‘doSystemCmd’, ‘doSystembk’, ‘doSystem’, ‘COMMAND’, ‘_popen’, ‘_system’, ‘_doSystemCmd’, ‘_doSystembk’, ‘_doSystem’, ‘_COMMAND’, ‘AES_set_encrypt_key’, ‘AES_set_decrypt_key’, ‘EVP_DecryptInit_ex’, ‘EVP_EncryptInit_ex’, ‘DES_set_key_checked’, ‘AES_cbc_encrypt’, ‘_AES_set_encrypt_key’, ‘_AES_set_decrypt_key’, ‘_EVP_DecryptInit_ex’, ‘_EVP_EncryptInit_ex’, ‘_DES_set_key_checked’, ‘_AES_cbc_encrypt’, ‘sprintf’, ‘snprintf’, ‘_sprintf’, ‘_snprintf’]

二、解题思路

2.1 技术选型

在综合考虑了基于IDA的IDAPython、基于Ghidra的脚本开发以及谷歌开源的的angr,我们选择了跨平台、能够进行静态分析和符号执行的angr。另外在运行Python代码时,我们采用PyPy即时编译器,而不是传统的CPython解释器。

2.2 获取危险函数的调用地址

题目给出的危险函数均是动态链接库中的函数,在程序进行动态链接的时候由于延迟绑定机制的存在,危险函数的调用地址的下一个交叉引用可能是在plt(Procedure Linkage Table, 过程链接表)段,也可能直接指向了危险函数。
DataCon2021优秀解题思路分享:物联网固件自动化漏洞挖掘WP (浙江大学 go-go-go战队)
图2.1. 危险函数调用
我们首先获取整个二进制文件的CFG(Control Flow Graph, 控制流图),如果交叉引用是在plt段中,我们通过指定危险函数的名字就可以直接获取到plt所在的block对象,然后找block节点的所有前继节点就可以获取到危险函数的调用地址。如果交叉引用直接指向了危险函数,同样获取其节点的所有前继节点,再排除在plt段中的节点就可以拿到危险函数的调用地址,最后进行去重就可以拿到所有危险函数的所有调用地址。

2.3 检测危险函数调用是否可利用

2.3.1 总体思路

首先我们定义造成危险函数误用的参数,并对这些参数进行def-use链的跟踪,发现确定不可能利用的命令注入,密码学误用和格式化字符串漏洞。然后根据函数调用路径和观察到的现象(命令执行的参数是格式化后的值)进一步实现命令注入的检测。对于存在混淆、无符号表等特殊文件,我们通过相关的开源代码和人工分析的方法也都一一解决了。
DataCon2021优秀解题思路分享:物联网固件自动化漏洞挖掘WP (浙江大学 go-go-go战队)

图2.2. 总体思路

2.3.2 危险函数参数

危险函数能够被利用,主要是由于关键的参数使用了不合理的值,因此我们首先确定每个危险函数造成误用的参数位置。例如system,popen函数造成命令注入是由第一个参数使用不当造成的,sprintf、snprintf造成格式化字符串漏洞是由第二个参数使用不当造成的,EVP_DecryptInit_ex、AES_cbc_encrypt密码学误用主要由第四,五个参数使用不当造成的。
但是物联网软件架构非常多样性,题目给我的软件就包括了mip32, armel, amd64, x86四种架构,而每种架构的函数传参方式也不一样。例如mips架构先把参数放在a0,a1,a2,a3寄存器,如果寄存器不够再通过栈传递,而x86架构则直接通过栈进行参数的传递。所以如何拿到参数对应的object并对其进行追踪是一个挑战,但如果使用angr就可以根据预定义的传参方式和偏移轻松拿到参数对应的object。

2.3.3 参数def-use链追踪

我们知道危险函数能够利用主要是由于参数使用不当造成的,因此我们通过angr的ReachingDefinitionsAnalysis模块对造成危险函数被利用的主要参数进行追踪,找到参数的def-use链路。如果追踪发现参数的内容是存储在二进制文件中的某个只读地址段,我们则认为该危险函数调用是确定不可利用的。这套方法对于判断格式化字符串漏洞是否可利用有非常不错的效果,我们通过这套方法跑出来的结果和IDA插件LazyIDA的输出结果进行判断,在随机选择的几个文件中均达到了一样的输出结果。
例如下图中ARM架构下的sprintf格式化字符串函数,通过def-use追踪,我们可以得到造成格式化字符串漏洞的第二个参数(R1寄存器)是指向一个只读地址,就可以确定该格式化字符串函数是确定不可利用的。
DataCon2021优秀解题思路分享:物联网固件自动化漏洞挖掘WP (浙江大学 go-go-go战队)
图2.3. 参数def-use链追踪

2.3.4 命令注入检测

对于命令注入检测,除了对参数进行def-use链追踪判断参数的位置外,我们也基于在分析二进制文件时观察到的现象进行检测。在查看二进制程序的反汇编和反编译的程序后,我们发现很多命令执行函数例如system函数调用前会先对参数进行格式化字符串处理,我们猜测可能是由于物联网的输入不确定和多样性导致的。
基于def-use链跑出来的结果,我们找出格式化字符串函数和命令注入函数距离为0x20个字节(设置为0x20主要是尽力确保格式化后的字符串是作为命令执行的参数),同时格式化字符串函数标记为确定不可利用,而命令注入函数标记为不确定可利用的组合。通过在block内部进行符号执行,符号执行的起点是block的开始地址,终点是危险函数的调用地址,执行结束后获取到格式化字符串中format参数的内容,如果内容中不包括%s,则确定该system不可利用。
例如下图中MIPS架构下的system命令执行函数,我们知道system的第一个参数a0是经过sprintf格式化后的值,而sprintf中的format并没有%s,只有%d,所以经过格式化后的a0仍然是安全的,因此可以确定system函数是确定不可利用的。
DataCon2021优秀解题思路分享:物联网固件自动化漏洞挖掘WP (浙江大学 go-go-go战队)
图2.4. 命令注入检测

2.3.5 密码学误用检测

对于密码学误用的检测我们提出了两条方案,第一: IV(initialization vector, 初始向量)和KEY不能是常数,需要来自安全的随机数,也就是产生随机数的种子也需要是安全的;第二AES_cbc_encrypt的key要来自于对应的 AES_set_encrypt_key或者AES_set_decrypt_key 输出。由于时间原因,我们这边暂时没有进行具体的实现。

2.3.6 函数调用路径

我们收集了题目文件中的所有external函数并人工筛选出属于输入的函数作为source function集合,再结合网络资源对source function集合进行扩充。最后source function包括读取外部输入、读取内存信息、读取文件信息、获取网络获取信息、获取环境信息、其他读取六大类。然后利用深度优先搜索算法判断在调用危险函数指令所在的Funciton中和调用source function指令所在的Function之间是否存在一条调用路径,如果存在则认为不确定可利用,否则认为确定不可利用,这里的搜索深度我们设置为10。
DataCon2021优秀解题思路分享:物联网固件自动化漏洞挖掘WP (浙江大学 go-go-go战队)
图2.5. 函数调用路径

2.3.7 特殊文件处理

在利用angr进行自动化漏洞挖掘的时候,我们遇到了有些文件存在符号表,但是却和地址对应不上;有些文件的函数内部实现了混淆;以及mip32架构中存在的延迟槽问题(参数传递指令在函数调用指令之后),我们通过自动化和半自动化的方法进行处理。

三、未完成的工作

在利用angr的ReachingDefinitionsAnalysis模块对def-use链进行追踪的时候,遇到local function和external function都会直接跳过,因为它不知道函数内部具体做了什么。直接跳过函数,会导致我们存在一些漏报,检测不完整。因此我们利用ReachingDefinitionsAnalysis模块中的function handler来解决该问题,由于目前这块技术的闭源以及时间原因,我们目前只实现了部分external function的模拟,对于模拟local function虽然有一些思路,但是没来得及实现。
具体思路如下,以左边的例子为例,首先我们在main函数中通过ReachingDefinitionsAnalysis模块得到一个RDA,在main函数中遇到local function check的时候我们在check函数中再生成一个RDA,在check函数中遇到external function时,通过执行我们编写的模拟external函数对寄存器的影响更新RDA,最后将整个RDA返回并和main函数的RDA合并,就可以得到参数跨函数的def-use链。
DataCon2021优秀解题思路分享:物联网固件自动化漏洞挖掘WP (浙江大学 go-go-go战队)
图3.1. function handler

四、展望与总结

这次比赛我们主要采用传统的污点分析和符号执行技术,不过由于题目直接给出了危险函数,所以我们在进行污点分析直接把危险函数的参数作为sink,然后通过逆向的方式跟踪危险函数的参数。另外在找参数的具体值时,在block内部实现符号执行,不会存在符号执行存在的路径爆炸和约束求解等问题。最后提出并部分实现模拟本地函数和外部函数的功能,使得def-use链追踪更加完整。
本次比赛锻炼了我们通过污点分析和符号执行来实现物联网固件的自动化漏洞挖掘,在将理论变成实践的过程中整个团队成长了很多。

 

 

原文始发于王, 欣蕾 :DataCon2021优秀解题思路分享:物联网固件自动化漏洞挖掘WP (浙江大学 go-go-go战队)

相关文章

暂无评论

暂无评论...