Group of Software Security In Progress

GoSSIP @ LoCCS.Shanghai Jiao Tong University

KARONTE: Detecting Insecure Multi-binary Interactions in Embedded Firmware

作者:Nilo Redini1,Aravind Machiry1,Ruoyu Wang2

单位:UC Santa Barbara,Arizona State University

会议:IEEE Symposium on Security and Privacy 2020

原文:KARONTE: Detecting Insecure Multi-binary Interactions in Embedded Firmware

Abstract

​ 目前的 IOT 设备固件一般有两种实现,一种是基于 linux,由大量相互依赖的 binary 构成,另一种是编写各个模块并编译成一个巨大的单 binary 的嵌入式 OS(又称 blob firmware)。之前的有研究者分析了数万个固件,发现其中有 86% 都是第一种实现,即固件基于 linux,由大量独立的二进制文件相互通信协作实现功能。

​ 但现有的静态分析工具在面对这种由多个二进制文件协作提供服务的固件时,不能充分地建模分析,效率低且误报率高。因此作者开发了一个静态分析工具 KARONTE 来处理这类嵌入式设备固件。该工具能够通过建模和跟踪多个二进制文件的交互来分析嵌入式设备固件,其核心方法是在二进制文件之间传播污点信息,以检测不安全的交互并识别漏洞。

​ 作者利用 KARONTE 对 53 个常用的固件样本进行了测试,并发现了 46 个 0-day 和 5 个 n-day 漏洞。

Background

固件漏洞检测

单二进制文件漏洞检测工具在对由多二进制文件交互实现功能的固件检测时经常会产生大量误报。

image-20200709124149333

Listing 1 是接受用户请求进行解析的二进制文件,它通过环境变量 QUERY_STRING 保存解析结果,并 execve 执行 Listing 2 的二进制文件进行处理。Listing 1 对于以 “<soap:AddRule” 开头的用户请求并未做长度检查,导致在 Listing 2 中存在栈溢出。

单二进制文件漏洞检测对于Listing 2 ,因为其无法判断环境变量 QUERY_STRINGLOG_PATH 的长度以及是否能被攻击者控制,所以会报出 2 个栈溢出漏洞。而作者开发的工具 KARONTE 因为分析了各个二进制文件之间的协作情况,会排除掉无法由攻击者控制的 LOG_PATH 可能造成栈溢出的漏洞,所以降低了误报率。

在与其他单 binary 分析工具的评估中 KARONTE 将误报降低了2个数量级,之前的工具要花费分析人员4个月的时间去进行排查报告的漏洞, KARONTE 只需要分析人员10个小时。

进程间通信

​ 确定嵌入式设备如何引入用户输入并在各 binary 之间进行传播是目前比较困难的问题。作者发现进程通信必须通过一个数据标识,而通信中的每一个进程都必须知道这个数据标识。常见的进程间通信的数据标识主要包括以下几个:

  • 文件名 :一些进程通过共享一个文件来进行通信。
  • 共享内存 : linux 支持共享内存,提供了一组接口来允许两个进程通过同一个物理内存进行共享数据。
  • 环境变量:通过环境变量共享数据从而实现通信,比如范例中的 QUERY_STRING
  • 套接字(Sockets):通过 socket 实现进程间传输数据。
  • 命令行参数 :创建其他进程时通过命令行参数传输数据。

污点分析

​ 污点分析是一种跟踪并分析污点信息在程序中流动的技术。在漏洞分析中,使用污点分析技术将所感兴趣的数据(通常来自程序的外部输入)标记为污点数据,然后通过跟踪和污点数据相关的信息的流向,确定与污点相关的操作关键点,进而挖掘程序漏洞。

​ 污点分析通常包括以下部分:

  • 确定污染信息的产生点,并进行标记
  • 利用特定规则分析污点信息的传播过程
  • 在一些程序关键点(sink)处判断污点信息是否会带来影响

实例

1
2
3
4
5
6
7
String user = getUser();
String pass = getPass();
String sqlQuery = "select * from login where user='" + user + "' and pass='" + pass + "'";
Statement stam = con.createStatement();
ResultSetrs = stam.executeQuery(sqlQuery);
if (rs.next())
    success = true;

user , pass 作为污染信息源,因为 sqlQuery 变量依赖于污点信息,所以也被标记为受污染的信息。而在程序关键点(sink)stam.executeQuery(sqlQuery),其参数受污点信息影响,所以将发出警告。事实上这是一个 SQL 注入漏洞。

KARONTE

威胁模型

​ 即使在局域网中工作的 IOT 设备,也有可能被互联网中的攻击者攻击。

  • 假定互联网中的攻击者可以控制对任何(不论是在局域网还是互联网环境中) 嵌入式 IoT 设备的输入

整体流程

image-20200720190651680

Firmware Pre-processing

​ 将输入的固件镜像使用 binwalk 解压

Border Binaries Discovery

​ 将解压得到的 binary 进行分析,选择出 边界二进制文件集 ( border binaries ),并标记出边界二进制文件中与网络编程相关的关键字进行比较的语句位置。

  • 边界二进制文件是指直接从外界接受用户输入的二进制文件,其被抽象为 攻击者控制的数据 的引入点。

识别方法

​ 作者假设的威胁模型中的攻击者是基于网络进行攻击的,因此边界二进制文件就是那些接受和处理网络数据的二进制文件。作者选取了以下五个特征来识别出 IoT 设备固件中从网络套接字中读取数据并进行解析的二进制文件。

  • 基本块的数量
  • 分支的数目,比如 if-else 等结构
  • 比较指令的数目,比如 cmp 指令

以上是之前的工作者在研究中用来识别嵌入式设备固件中解析输入的函数的三个特征。但是为了识别出面向网络的二进制文件,作者还选取了2个特征

  • 网络标志,对 soapHTTP 等网络编码字符串的引用或硬编码数目
  • 连接标志,是否从套接字中读取数据并与内存中的数据比较

然后根据模型

image-20200709145128063

计算出某个二进制文件可能是网络边界二进制文件的得分。作者再用 DBSCAN density-based clustering algorithm 算法选出了边界二进制文件的集合,并标记出边界二进制文件中与网络编程相关的关键字进行比较的语句位置。

Binary Dependency Graph

​ 根据之前得到的边界二进制文件集合,对处理被攻击者控制的数据的二进制文件之间的通信进行分析,得到一个有向图 BDG。在该有向图 BDG 中包含了在固件中各二进制文件之间传递的数据流信息。

构建方法

image-20200709184715042

核心流程

1. 确定进行通信的 Binary

  • 标记出边界二进制文件集合中的所有的进程间的通信数据标识
  • 确定数据标识的位置,种类以及流向的文件(通过污点分析确认)
  • 将使用了上一步中的数据标识的二进制文件纳入集合,重复上述过程

2.构建有向图 BDG

  • 有向图的点是筛选出的进行通信的二进制文件

  • 有向图的边为 $$ e=([b1;loc1;cp1];[b2;loc2;cp2];k) $$ ​ 表示二进制文件 b1 的在 loc1 的位置(比如 setenv 函数)通过 cp1 的方法(比如共享环境变量 k)与二进制文件 b2 进行通信。b2 在 loc2 处通过 cp2 的方法进行了接收数据。

至此得到了一个用户输入的数据在二进制文件之间传播的有向图

MULTI-BINARY DATA-FLOW ANALYSIS

​ 根据上一步得到的 BDG 进行数据流分析,其目的是得到来自网络输入的数据在传播过程中的约束集。

​ 因此需要有向图 BDG 中的数据流细节。但通常情况下,列举 BDG 中所有二进制间的路径会导致路径爆炸的问题。因此作者的关键点是,更可能导致 bug 发生的路径是那些对用户提供的数据约束较少的路径,每次只将那些对用户输入数据约束最少的路径传播到其他二进制文件。

Insecure Interactions Detection

​ 不断探索上一步得到的路径,收集约束集并分析漏洞。

函数分类

在进行漏洞检测之前,扫描所有函数,并标记出两类函数

  • 内存比较类函数,比如 memcmp
  • 内存复制类函数,比如 memcpy

标记的方法:

​ 以内存比较类函数为例,其应该包含一个循环对函数某个参数所指向的内存位置进行比较。因此筛选出至少包含一个循环的函数,并从循环内的内存比较指令如cmp等,到该函数入口点进行切片,分析该切片内函数的参数是否会影响该比较指令的操作数,如果是,则认为这是一个内存比较函数。

主要作用

Insecure Interactions Detection 模块的主要作用是检测两类漏洞:

  • 内存冲突类(memory-corruption)漏洞,比如堆栈溢出
    • 对于缓冲区溢出漏洞,利用污点分析检测由攻击者控制的数据是否地到达了内存复制类函数,然后分析其目标缓存区的边界大小和污染信息的被约束后的大小,进而判断是否存在溢出等问题。
  • 拒绝服务类漏洞,比如能被攻击者控制的循环(attacker-controlled loops)
    • 对于被攻击者控制的循环,该模块会检测每个循环执行的次数是否不加约束地由用户控制。

作者提到尽管他们只实现了这两类漏洞的检测,但是分析人员是可以对该模块进行拓展的。

评估

有效性

​ 作者从四家提供设备固件的主要 IoT 设备供应商(NETGEAR, TP-Link, D-Link, and Tenda)的官网上下载了 53 个固件样本,人工核查后共确认了 46 个 0-day 漏洞

image-20200720205805869

稳定性

​ 为了测试 KARONTE 的稳定性,作者使用了先前研究者的一个较大的测试集,其中包含来自 21 个不同供应商的 899 个固件样本

image-20200709215432766

可验证性

​ 作者邀请了另一所大学的独立研究员利用他们的工具并进行了测试,得到了与表一相同的结论。

​ 作者还提供了一个包含该工具的 docker,以便于其他研究者进行相关验证。

总结

​ 作者提出的 KARONTE 工具极大减少了传统二进制分析技术在分析真实固件时产生的误报。