会找漏洞的时光机:Pinpointing Vulnerabilities

2017-12-05 06:40YueCHEN
中国教育网络 2017年9期
关键词:整数漏洞内存

文/Yue CHEN

会找漏洞的时光机:Pinpointing Vulnerabilities

文/Yue CHEN

当我们的系统遭受攻击时,即便我们已经检测到攻击,如何知道被利用的漏洞在哪里呢?

先让我们来看一个简单的例子(图1):假如用户输入的argv[ ]是个很长的字符串,由于strcpy不限制拷贝的字符数,buf会被溢出,那么在第6行函数return时候,很可能会控制流异常。假如使用攻击检测,很可能检测到第6行的return 0,但是真正的漏洞在第4行。症状(Symptom)和根本原因(Root Cause)在不同的地方。对于复杂的大程序,想要定位到Root Cause还是非常困难的。

图1

目前基于memory instrumentation的漏洞检测,由于要instrument所有的内存访问,其开销特别大,因此不适合用于程序运行时使用。所以这篇论文提出个系统叫Ravel (Root-cause Analysis of Vulnerabilities from Exploitation Log), 它包含一个online模块和一个offline模块. Online的模块把运行的不确定事件都记录(Record)下来,并且提供攻击检测功能;Offline的模块可以重放(Replay)程序的运行,并且可以instrument memory并且定位漏洞。

这样做有以下优势:

1. 可以把真实世界里的攻击,在实验室环境进行重放(Replay)并分析。

2. 运行时候性能开销很小,开销大的漏洞定位阶段被放在了Offline的实验室里。

3. 可扩展。可以自由添加新的攻击检测和漏洞定位方法。

对于攻击检测,Ravel用了现有的方法,比如程序崩溃,异常系统调用,CFI等。 对于Record amp; Replay, Ravel主要记录了不确定事件,比如系统调用(syscall)结果,内核到用户空间的数据拷贝,同步原语等。

对于Replay阶段的Memory Instrumentation,Ravel集成了二进制翻译引擎(Binary Translation Engine,简称BT)。其中很重要的功能 (也是一项挑战) , 是可以把BT发出的syscall和目标程序本身的syscall区分开来,以确保replay和record的一致性。

对于漏洞定位,Ravel设计了一系列功能。首先是数据流分析(Data-flow Analysis)。写入一块内存叫做define(简称def),把从这块内存里读出数据叫use。假如指令A写入这块内存,指令B接着读了出来,它们就构成了一组def-use关系。一堆这种关系可以构成一张图,叫DFG (Data-flow Graph)。

我们可以预先把这些关系找出来,做一张DFG。假如运行时候有之前没见过的def-use关系出现,可以视为发现 违规(violation),意味着很可能有漏洞。那么如何知道出问题的地方是在def,还是在use呢?

图2

图3

Ravel用了一些启发式搜索(heuristics)。这里用buffer overflow举个例子。

比如我们本来有三个use (也就是read from memory),如图2所示。然后有一个大的def (write to memory) 把这三个use都覆盖了,如图3所示。假如发现这些def-use关系是violation,那么很有可能,漏洞在def的指令及其周围。并且很有可能是buffer overflow, memory overwriting之类的。Violation关系如图4所示。别的漏洞,如information leakage,也可以用类似的方法来定位。

图4

对于整数错误(Integer Errors), Ravel关注的是一些用整数计数(比如放在RCX/ECX寄存器里)的指令,比如MOVS, STOS 等; 和有整数参数的函数,比如memcpy, recvfrom 等。从这些参数开始,Ravel进行backwards search来定位漏洞。

可以定位的整数错误漏洞包括:

Assignment Truncation (比 如0x12345678 → 0x5678)

检测方法:从longer type赋值到shorter type

Integer Overflow/underflow (比如0xFFFFFFFF + 1)

检测方法:检测RFLAGS/EFLAGS寄存器

Signedness Error (比如 unsigned_int_var = signed_int_var)

检测方法:收集Hint。比如一些指令或者函数会指定特定的signed或者unsigned参数。详情参见slides或者paper.

那么有些整数错误是程序员/编译器故意设置的,如何区分呢?

由于这些错误已经和reported的漏洞相关,所以非常大可能是漏洞,而不是正常的整数操作。

假如Race Condition存在,replay的execution trace会和record下来的不一样,所以可以用该方法来检测。

一旦检测到,Ravel继续用happens-before relation来进一步尝试定位漏洞。

图5

Ravel还能检测以下一系列漏洞,此处不再赘述:

Use-after-free and Double-free

Buffer Overflow

Integer Errors

Information Leakage

Format String Vulnerabilities

Ravel的Record amp; Replay功能基于FreeBSD 10.2实现,漏洞定位基于Valgrind实现。

图5用Nginx的CVE-2013-2028 漏洞举了一个Ravel如何从攻击定位到漏洞的例子, 具体描述参见论文(论文链接: http://ww2.cs.fsu.edu/~ychen/paper/ravel.pdf)。

更多的Evaluation实验, 比如Heartbleed,以及别的漏洞类型比如Null Pointer Dereference,Heap Overflow,Out-of-bounds Read,Untrusted Pointer Dereference,也可以在论文里找到。

图6

图6 是Online Performance Overhead的Evaluation, 实验是在流行的Web服务器和SPEC CPU 2006上做的,可以看出性能开销非常小。

(责编:杨洁)

(作者单位为佛罗里达州立大学)

猜你喜欢
整数漏洞内存
漏洞
笔记本内存已经在涨价了,但幅度不大,升级扩容无须等待
“春夏秋冬”的内存
一类整数递推数列的周期性
三明:“两票制”堵住加价漏洞
漏洞在哪儿
高铁急救应补齐三漏洞
内存搭配DDR4、DDR3L还是DDR3?
上网本为什么只有1GB?
答案