【论文分享】ARBITRAR: User-Guided API Misuse Detection

S&P 2021 ,一篇检查API误用的工作

开源于:https://github.com/petablox/arbitrar

简介

软件的API因为他的多样性和复杂性很容易导致编程错误,而且也很难用分析工具检查出来。这类检查API误用的工具要么需要专家去设置精确的API规范,要么假设API的使用是遵守一些简单的规则,而这些规则可以自动地从代码中提取。这种方法的准确性很差。

文章提出的方法可以与用户交互来区分目标API是合法还是非法使用。具体来说是通过一种主动学习的算法来计算API使用非法的概率,从而来减少用户的负担。

实现了检查C/C++程序的API误用工具的原型ARBITRAR,并测试了21个真实程序,包括OpenSSL和内核。找到了40个新的bug,已经被修补了18个。也在APISAN benchmark里找到了所有的已知的bug,误报率为51.5%,比APISAN的87.9%要好。

引言

现代软件包含了很多API,提供了模块的接口包含丰富的语义信息,使得实际使用的过程比较复杂。根据最近的研究(19年一篇API误用综述)表明,17%的bug都是来自API误用。这些误用可能会造成很严重的安全影响。

现在有很多程序分析技术用来检查API误用。然而API误用仍然很广泛。现有的API误用检测工具可以分为两类,第一类是给定API的规范,检查有没有违反这个规范,比如IMChecker,Semmle,Sys。这些工作的有效性取决于API规范的质量。然而,编写准确的规范需要很多专家知识,对于很有经验的用户来说也不好写。而且这些规范一般都是用Domain Specific Language写的,不同的工具还不一样。

  • IMChecker用的是YAML
  • Sys用的是Lisp和LLVM IR
  • Semmle用的是CodeQL

第二类工具比如APISAN和JADET,假设API的使用是遵照一些简单的规则,而这些规则是可以自动化地从代码中挖掘出来的。具体来说,给定很多使用API的代码,大部分的使用模式都是合法使用的,和他们不同的就是非法的。这些工具的假设有两点,一个是有很大的代码语料库,另一个是大部分的使用是合法的。然而这两个假设并不总是有,尤其是那些很少使用但很重要的API。这些方法就很难获取到这些API的使用模式,而且先进的工具APISAN在有很多种合法使用模式的情况下会产生很多误报。

总的来说,检测出合法的API使用模式是很难的,尤其是在缺少足够多的样例的情况下。另一方面,开发者也不一定能够写出精确的API规范。然而,给定一条表示API使用的路径,开发者可以很容易地确定API是不是合法的。

比如下面的代码分别在第6行和第12行调用了目标API:png_destroy_write_struct。这两个调用的trace分别是1,2,3,4,6和1,2,3,4,12。当给出这两个trace的时候,对这个API:png_destroy_write_struct有了解的开发者就知道第12行的调用是非法的。

image-20211110195124548

那么我们可以利用这个feedback来实现一个高效的API 误用检查器吗?总共有以下这四个挑战:

  1. 高效的路径生成:给定代码中的一个目标API,我们需要一个机制去高效地生成所有到达API调用点的路径。而且,我们需要一个方式去减少一些trace,因为并不是所有的trace都和API调用有关系。
  2. 通用的路径表示:不像其他的方法,只能适用于简单的API使用模式,我们需要找到一种通用的方法来表示trace,能够处理所有类型、不同使用方式的API
  3. 实时的用户交互:不考虑trace的长度或者API语义的复杂性,我们需要迅速从用户反馈中学习,并反馈给用户
  4. 准确的alarm识别:需要准确的识别出有问题的API误用,来让开发者很快地验证。

文章使用了最大差异的核密度估计方法,一种主动学习方法。不像现有的方法需要API规范或者大的代码语料库。文章使用无约束的符号执行生成过程内的调用点的trace。通过在API调用点处,使用后向切片来最小化trace。这个优化的trace用于转换为特征向量。然后在向量化的trace上用MD-KDE算法计算是非法使用的概率。

Motivation

方法

image-20211110204302678

Trace Generation

trace generation的目的是生成所有调用API方法的路径。然而要枚举真实程序里的所有路径是不太现实的,因为会遇到路径爆炸问题、工程上的限制。这里文章对API调用的上下文做了unconstrained symbolic execution。

(1)找到执行的上下文

我们使用执行上下文s来表示under-constrained symbolic execution的入口和范围。形式化表示的话就是s=(g,φ),g是入口函数,φ={g1,g2,…,gn}是允许探索的函数。给定:

  • 目标API方法的在函数f的一个调用点k,
  • 程序的调用图
  • 上下文深度d

通过算法1去计算执行环境的上下文。首先使用逆向的BFS从函数f开始遍历调用图,来找到距离为d的函数。然后对于每个函数g,使用bfs找到2*d距离的φ函数。然后从φg中移除目标k。因为关注的是API如何使用的,而不是API如何实现的。

image-20211111161223079

(2)Under-constrained Symbolic Execution

给定调用点k的执行上下文,我们从入口函数开始符号执行,使用符号化变量作为函数的参数。遇到函数调用时,如果是在φ里的函数,就跳进那个函数里。反之,就忽视call指令,并且生成一个符号值作为调用的返回值。(感觉可能会出现很多符号值)

内存模型:使用简单的哈希表来作为内存模型,地址作为key来进行映射。使用符号化变量来初始化内存的每个字节。内存模型和17年的两篇工作一样。

循环和递归的处理:将循环展开一次,并且不会跳进递归函数调用来避免状态爆炸。因为一次循环就能获取到API的使用情况。但是,我们也记录循环的入口和出口,因为他们可以用来降低误报。

生成的trace长这样:

image-20211111170741275

Trace Encoding

trace编码的目的是将程序的trace转化为固定维度的特征向量,然后用在后面的主动学习算法里。基于API 误用的bug,我们定义了一些特征。这些特征基本覆盖了大部分API使用的行为。这个工具使用datalog规则来提供了一个统一可扩展的接口来定义特征。

image-20211111185236476

特征主要分为四类:

  • return value:返回值特征表示返回值是如何使用的。如果目标函数有返回值,就生成这个特征。
  • argument:包括餐宿的类型,前置条件和后置条件。
  • causality relation:这个出现在API方法属于一组需要同时调用的情况下。比如lock/unlock,fopen/fclose。具体来说,作者弄了个字典,key是API,值是和这个API一起出现次数top k个的函数。
  • 控制流:这类特征和API没啥关系,主要是这个特征能够描述trace的结构,并且能够降低误报。

主动学习和用户交互

这部分提出了一个新的主动学习方法来处理API误用检测问题。首先,将问题定义为机器学习的异常检测问题,目标是能够通过人类专家的交互来识别出异常。然后我们提出了MD-KDE算法,最大差异的核密度估计算法,能够学习人类专家的反馈,然后在几次迭代中精确地识别可疑数据。

交互式异常检测问题:传统的异常检测方法在很大量级的代码上训练,但这个方法存在一个问题,就是正负样本差很多,因此这些方法通常需要额外的假设。比如one-class假设。然而这种假设在我们的例子中是不现实的,因为每个API使用模式都是不同的。为了解决这个问题,我们通过让人类专家和结果进行交互,来给机器学习算法提供更多的信息。

给定一个n个数据点的数据集,一个专家将数据映射为正常或者异常。学习器可以在每轮使用一个数据点来查询f,总共查询T轮。交互式异常检测问题的目的是最大化识别出的异常的总数。

具体来说,学习器从数据集挑一个没打标签的数据给专家,专家给出反馈。最后的准确率是T次查询中,是API误用的情况所占的百分比。

基于主动学习算法的核密度估计

在每个轮次,给定当前有标签的数据集,学习器为每个没打标签的数据点计算分数,分数越高最有可能是异常,然后让专家评估分数最高的数据。

image-20211111195032324

算法的核心就是要找到离bug最近的,离非bug最远的没打标签的trace。

image-20211121204434518

image-20211121203316797

MD-KDE 的有效性

一开始给出一个没打标签的trace,然后用户如果将这个标签设置为正样本,就会变成中间的样子。如果设置为负样本,就会变成右边图的样子。

image-20211121203436370

实现

3.5k的Rust代码和2K的Python代码。

trace生成和under-constrained symbolic execution都是基于rust代码实现。

主动学习框架是基于python实现。

结果

Effectiveness:和APISAN相比的有效性

Impact:能够找到未知的API误用bug吗?

Scalability:能够扩展到真实的大型程序里吗?并且呢个够快速学习反馈给用户?

Extensibility:应用到其他场景的扩展性?

数据集:2个API误用的benchmark 和 21个真实程序包括内核

有效性

传统的漏洞检测的评估都是用漏报,误报来衡量的。但这个工具不好用这个来衡量,因为这个工具一开始对漏洞一无所知,需要用户给他打标签。所有这个技术的有效性,就需要工具能够快速从用户反馈中学习,并且提供给用户较少的没有漏洞的trace。

所以ARBITRAR的误报指的是提供给用户不是bug的trace。同时也定义了反馈容忍度,就是没有bug的trace的上界。从而让我们能够策略误报。

比如 容忍度为2表示,用户只能容忍两条没有bug的trace。因此,在两次交互中没有找到的bug,就属于漏报。如果容忍度为无穷大,用户就可以检查所有的trace,也就是漏报为0,如果容忍度为0,则就不会找到bug,因为这个工具需要初始数据来进行学习。如果用户分析了n条trace,其中容忍度为k,那么意味着至少有n-k个trace是真实的bug。

和APISAN工具进行了对比,虽然二者的误报并不是一种方法计算的。作者工具的误报加上了主动学习引入的成本,仍然要比APISAN的误报要低。并且在同一个benchmark上的漏报率也要低于APISAN.

image-20211121200001210

同时还设置了一下容忍度对于检测API误用的影响。实验结果表明,大部分API 误用bug都可以在3次迭代内找到。

image-20211121192223407

Impact

找到了40个真实的漏洞,也提交了补丁被开发者验证通过。first bug warning这一列表示找到第一个bug中间遇见了多少个误报。

image-20211121200338292

Scalability

不管有多少条trace,MD-KDE算法都可以很快地和用户进行交互。下面的图说明了他们创新的MD-KDE算法要比传统的KDE算法要快很多。

image-20211121200400431

Extensibility

为了说明这个MD-KDE算法的创新性,他们还做了一个实验来回答一个这样的问题:已知一个bug,能否用工具更快地找到剩下的所有的bug。xf表示找到第一个真的bug需要的迭代次数。xl表示找完剩下所有的bug的迭代次数。

选择这几个API的标准是有两个:一是API有多个bug,二是找bug还有提升的空间。

image-20211121200427771

局限

需要提供API方法:需要事先提供API方法。作者也提供了一种方法来枚举所有的API调用点,以及这些API的出现次数,因此可以根据API次数来选择要测试的API。

生成的trace不完整:只考虑了直接调用。没有考虑函数指针的情况,作者认为补充下指向分析可以解决。

离散的用户反馈:主动学习算法只需要用户反馈的一个位,yes or no。然而实际上用户可能要提供各种各样的反馈,比如80%的概率是yes,现有的设计不支持这种反馈。不过像ALPF这种技术可以用来处理这种反馈。

对用户反馈敏感:主动学习算法的前提是信任用户的反馈,然而一个用户可能会出错。当给出一个错误的反馈时,模型能够在几个正确的回答后,自动修正。然而,这种方法可能没有办法扩展到所有的API,因为模型是建立在API的复杂性之上。需要更多的研究来精确的处理模型对于用户反馈的敏感性问题。

未来工作

模型可解释性和迁移学习:作者相信他们的算法学习的模型是具有可解释性的,并且是可迁移的。比如对malloc建立的模型,同样也可以迁移到realloc和calloc。下一步计划将迁移学习应用到其他相关的API方法上。同时也计划为每个trace生成一个描述来解释哪个特征决定了选择哪个trace。

确定高危险漏洞的优先级:确定高危险API 误用bug的优先级是很重要的。比如,可能会导致内存泄露或者代码嗅探的API误用bug要比会导致内存损坏的bug优先级要低。为了解决这个,我们计划让用户提供bug类型的回馈。然后利用bug类型的反馈去训练漏洞类型的检测模型,从而能够确定漏洞的优先级。

总结

实验做的很完整。

引入用户交互,对文章的实验设计都有很大的影响。文章中处理的很好。一直在强调工具的误报和传统的漏洞检测不一样。

开源于:https://github.com/petablox/arbitrar

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

破落之实

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值