48、Anatomist:增强型固件漏洞发现方法

Anatomist:增强型固件漏洞发现方法

1. 背景与动机
1.1 IoT模糊测试

模糊测试已被证明是发现未知漏洞最有效的方法之一,在工业和学术界都得到了广泛应用。对于物联网固件,有一些知名的模糊测试方法:
- IOTFUZZER :是专门为检测物联网固件中的内存损坏漏洞而设计的自动黑盒模糊测试框架。它基于物联网设备官方移动应用中包含的协议信息,在无需先验协议知识的情况下进行协议引导的模糊测试,具有轻量级、可靠且能生成有效测试负载的特点。
- Avatar :通过协调模拟器和真实硬件的执行,实现对嵌入式设备的复杂动态分析。它构建了一个由处理器模拟器(QEMU)和真实硬件组成的混合执行环境,并应用白盒模糊测试工具。基于Avatar的Avatar2进一步升级为动态多目标编排框架,实现不同动态二进制分析框架、调试器、模拟器和真实物理设备之间的互操作性。
- Firmadyne :是第一个以可扩展方式专门针对联网商用现货(COTS)设备上基于Linux的固件的自动化动态分析系统,使用插桩内核实现基于软件的全系统仿真。
- FirmAE :基于简单启发式方法可避免广泛的仿真失败情况的观察,开发了几种仲裁技术,提高了仿真成功率。
- FirmAFL :基于AFL和Firmadyne构建,是第一个用于物联网固件的高吞吐量灰盒模糊测试器,通过结合进程仿真和全系统仿真,解决了系统模式仿真带来的性能瓶颈问题。

然而,上述模糊测试方法根据程序异常信号检测漏洞,无法发现不会导致程序崩溃的逻辑漏洞,也不能检测执行路径中未触发的漏洞,本质上是基于漏洞症状而非程序状态异常来识别漏洞。

1.2 基于程序状态的漏洞发现

近年来,提出了一些基于程序状态异常判定的漏洞发现方法:
- Bunkerbuster :专为在常规Linux系统上运行的终端程序设计。它使用硬件处理器跟踪收集终端主机数据,推断输入结构并分割跟踪信息,然后基于执行跟踪重建符号状态,能有效检测和定位4种类型的漏洞,但由于嵌入式平台资源受限,无法用于固件。
- Timeplayer :用于有效检测未初始化变量的使用,包含差分重放和符号污点分析两种关键技术。但它专门用于查找未初始化变量漏洞,不能检测固件的多类型漏洞。

1.3 激励示例

以下代码展示了一个栈溢出漏洞(CVE - 2017 - 3193)和一个由Anatomist发现的0日命令注入漏洞:

int hnap_main( int a1 , int a2 , int ∗a3 )
{
    char ∗env , process_env ;
    char buf [ 2 5 6 ] ;
    /*Read from environment variable */
    env = getenv ( "HTTP_SOAPACTION" ) ;
    /*Simple process */
    process_env = strrchr ( v5 , ’ / ’ )+1;
    /*Copy to stack without length check */
    strcpy ( buf , process_env ) ; // Overflow
    /*Check and process the buf. */
    check_and_process ( buf ) ;
    system ( buf ) ; //Command injection
    /*Omitting unimportant codes */
    ...
    return 0;
}

在实际中,模糊测试方法通过变异 HTTP_SOAPACTION 来查找漏洞。只有当 HTTP_SOAPACTION 超过 buf 并导致 cgibin 崩溃时,才能发现溢出漏洞;当 HTTP_SOAPACTION 不超过 buf 时,即使执行路径经过该漏洞,也无法发现。此外,由于这种逻辑类命令注入漏洞不会使 cgibin 崩溃,模糊测试方法无法检测到。因此,我们面临两个重要问题:如何发现执行路径中存在但未触发的漏洞?如何发现包括内存损坏和逻辑漏洞在内的多类型固件漏洞?

2. 方法

基于上述考虑,我们提出了Anatomist,这是第一个基于程序状态异常判定和全系统重放的增强型固件漏洞发现方法。Anatomist在两个关键领域进行了改进:一是能够发现执行路径中存在但未触发的漏洞;二是可以发现内存损坏漏洞和逻辑漏洞。其工作流程如下:

graph LR
    A[开始:包含固件的虚拟机] --> B[记录执行过程,生成快照和执行记录]
    B --> C[全系统确定性重放执行过程]
    C --> D[识别危险操作候选]
    D --> E[单路径符号跟踪]
    E --> F{程序状态是否异常}
    F -- 是 --> G[危险操作导致漏洞]
    F -- 否 --> H[无漏洞]
    G --> I[生成漏洞报告]
2.1 危险操作候选

程序执行的一些危险操作,如内存写入和命令执行,如果执行不当,往往会导致程序状态异常。基于观察,如果程序执行的危险操作可能受网络消息输入影响,则该操作有可能导致程序状态异常,我们将这些操作识别为候选操作,以便进行程序状态异常判定。

由于嵌入式平台资源有限,我们使用全系统记录和重放技术提取固件的运行时语义。在全系统重放过程中,Anatomist自动对网络消息输入进行污点标记。如果之前定义的两种危险操作(内存写入和命令执行)受输入影响,则记录相关信息。具体如下:
| 操作类型 | 受影响判断条件 | 记录信息 |
| ---- | ---- | ---- |
| 内存写入 | 存储写入操作长度的内存被污点标记 | 操作的PC、影响操作的输入污点标签、写入目标内存空间的大小 |
| 命令执行 | 命令执行函数的任何参数被污点标记 | 操作的PC、影响命令执行的输入污点标签 |

2.2 程序状态异常判定

获得危险操作候选后,进行单路径符号跟踪,根据记录的执行路径判断危险操作候选的程序状态是否异常。单路径符号跟踪可以避免符号执行的状态爆炸问题,并且Anatomist仅对影响危险操作候选的输入进行符号化,减少了符号执行的开销,提高了执行效率。

当单路径符号跟踪命中候选内存写入操作的PC时,Anatomist提取对应污点标签的符号约束,判断该约束是否能大于写入内存空间的大小。如果可以,则该危险操作将导致内存状态异常,进而引发内存溢出漏洞。当符号执行执行候选命令执行操作时,Anatomist提取对应污点标签的符号约束,如果该约束不严格且可以穿插恶意命令,则该危险操作会导致语义状态异常,引发命令注入漏洞。

2.3 工作流程

以下示例代码解释了Anatomist的工作流程:

int main (){
    char ∗recv_buf = malloc ( 1 0 ) ;
    SOCKET servSock ;
    sockaddr_in sockAddr ;
    SOCKADDR clntAddr ;
    /*Omitting unimportant codes */
    ...
    /*Establishing socket communication */
    bind ( servSock , (SOCKADDR∗)&sockAddr , sizeof (SOCKADDR) ) ;
    listen ( servSock , 2 0 ) ;
    int nSize = sizeof (SOCKADDR) ;
    SOCKET clntSock = \
    accept ( servSock , (SOCKADDR∗)&clntAddr , &nSize ) ;
    /*Receiving network message inputs */
    int strLen = recv ( clntSock , recv_buf , 10 , 0 ) ;
    /*Doing dangerous operations */
    int length = ( int ) recv_buf [ 0 ] ;
    char dst [ 2 5 6 ] = "" ;
    memcpy( dst , recv_buf+1, length ) ; // Dangerous operation
    system ( recv_buf +5); // Dangerous operation
    /*Omitting unimportant codes */
    ...
    return 0;
}

Anatomist的具体工作步骤如下:
1. 记录目标程序的全系统执行过程,然后在全系统模式下确定性重放。
2. 重放过程中,识别危险操作候选并保存目标程序的执行路径。当重放执行消息接收时,自动对接收的消息进行污点标记。
3. 当重放执行内存写入危险操作时,记录相关信息;当重放执行命令执行操作时,也记录相关信息。
4. 获得危险操作候选后,根据记录的路径进行单路径符号跟踪。符号执行时,部分符号化接收到的消息。
5. 在单路径符号跟踪过程中,判断候选操作的程序状态是否异常。如果符号执行命中相应PC,提取约束进行检查。
6. 程序状态异常判定后,生成漏洞报告。

2.4 实现

我们使用全系统确定性记录和重放技术提取所需的运行时语义,基于具有丰富接口的PyPanda实现Anatomist,并使用固件仿真工具FirmAE制作固件的虚拟机镜像。具体操作步骤如下:
1. 使用PyPanda启动准备好的虚拟机镜像,通过发送数据包脚本与虚拟机交互,记录虚拟机的全系统执行过程,保存初始快照和执行记录。
2. 在全系统重放过程中,提取所需的运行时语义,识别危险操作候选。使用 cb_before_block_exec 回调获取目标程序的执行路径。
3. 挂钩用于接收消息的函数,如 read recv ,获取网络输入的地址和长度,并使用 taint_label_ram 函数对这些输入进行污点标记。
4. 对于命令执行危险操作候选,挂钩相关函数,如 system execve 。触发挂钩时,使用 taint_check_ram 函数判断函数参数是否被污点标记,如果是,则使用 taint_get_ram 函数获取污点标签。
5. 对于内存写入危险操作候选,挂钩与内存复制相关的函数,如 strcpy memcpy 。确定内存是属于栈还是堆,对于栈,使用内存地址与栈底的距离作为内存长度;对于堆,挂钩与堆分配和释放相关的函数,如 malloc free ,动态维护堆列表并记录每个堆的大小。
6. 基于angr实现部分程序状态异常判定。获得危险操作候选和目标程序执行路径后,通过自定义探索技术,使符号执行沿着记录的路径进行,判断危险操作候选的程序状态是否异常。符号执行命中危险操作候选的PC时,提取对应污点标签的符号约束,使用Z3求解器判断是否存在使程序状态异常的解。如果有解,则危险操作会导致程序状态异常并引发漏洞。

Anatomist:增强型固件漏洞发现方法

3. 评估

实验在Ubuntu 16.04系统上进行,该系统配备16GB内存和英特尔酷睿i9 4核CPU(i9 - 9880H,2.30 GHz x 4)。在评估中,我们解决了以下问题:
- 与现有技术相比,Anatomist是否有效,能否检测未触发的漏洞?
我们将Anatomist的结果与最先进的固件漏洞发现方法FirmAFL在FirmAFL数据集上进行了比较。实验表明,Anatomist平均将漏洞发现效率提高了741.64%,并能识别未触发的漏洞。
- Anatomist能否检测包括内存损坏和逻辑漏洞在内的未知固件漏洞?
我们选择了3个固件进行分析。通过分析网络上捕获的常规消息,Anatomist发现了3个新的0日漏洞。

为了更直观地展示Anatomist的优势,以下是Anatomist与FirmAFL在漏洞发现效率和发现漏洞类型方面的对比表格:
| 方法 | 漏洞发现效率提升 | 可发现漏洞类型 |
| ---- | ---- | ---- |
| Anatomist | 741.64% | 内存损坏漏洞、逻辑漏洞(如命令注入)、未触发的漏洞 |
| FirmAFL | - | 部分可触发的漏洞(基于程序异常信号) |

4. 总结与展望

Anatomist作为一种基于程序状态异常判定和全系统重放的增强型固件漏洞发现方法,在多个方面展现出显著优势。它不仅能够发现执行路径中存在但未触发的漏洞,还能同时检测内存损坏漏洞和逻辑漏洞,有效弥补了现有模糊测试方法的不足。

从评估结果来看,Anatomist在漏洞发现效率上有大幅提升,并且能够挖掘出未知的0日漏洞,这对于保障物联网设备的安全性具有重要意义。

然而,Anatomist也并非完美无缺。在实际应用中,由于嵌入式平台资源的限制,全系统记录和重放以及符号执行等操作可能会带来一定的性能开销。未来,可以进一步研究优化这些操作的方法,以提高Anatomist在资源受限环境下的性能。

同时,随着物联网技术的不断发展,新的漏洞类型和攻击方式也在不断涌现。Anatomist可以进一步扩展其检测范围,以应对更多类型的漏洞。例如,可以考虑增加对更多逻辑漏洞类型的检测,如身份验证绕过和信息泄露漏洞等。

此外,为了更好地应用于实际场景,可以开发更加友好的用户界面和工具,方便安全人员使用Anatomist进行固件漏洞检测。

graph LR
    A[Anatomist现状] --> B[存在性能开销问题]
    A --> C[可检测漏洞类型有限]
    B --> D[研究优化操作方法]
    C --> E[扩展检测范围]
    D --> F[提高资源受限环境下性能]
    E --> G[应对更多类型漏洞]
    F --> H[更好应用于实际场景]
    G --> H
    H --> I[开发友好用户界面和工具]

总之,Anatomist为固件漏洞发现提供了一种新的思路和方法,具有广阔的应用前景和发展空间。通过不断的改进和优化,它将在保障物联网设备安全方面发挥更加重要的作用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值