污点分析初探

超级超级超级详细的参考博客

这篇博客可以说是非常详尽了,里面讲述了如下内容,以下部分是记得一些笔记和理解

污点分析基本原理
污点传播分析的关键技术
污点分析方法实现:静态、动态、显式、隐式污点分析

污点分析基本原理

污点分析定义

污点分析可以抽象成一个三元组<sources,sinks,sanitizers>的形式,其中,source 即污点源,代表直接引入不受信任的数据或者机密数据到系统中;sink 即污点汇聚点,代表直接产生安全敏感操作(违反数据完整性)或者泄露隐私数据到外界(违反数据保密性);sanitizer 即无害处理,代表通过数据加密或者移除危害操作等手段使数据传播不再对软件系统的信息安全产生危害. 污点分析就是分析程序中由污点源引入的数据是否能够不经无害处理,而直接传播到污点汇聚点.如果不能,说明系统是信息流安全的;否则,说明系统产生了隐私数据泄露或危险数据操作等安全问题.

在漏洞分析中,使用污点分析技术将所感兴趣的数据(通常来自程序的外部输入,假定所有输入都是危险的)标记为污点数据,然后通过跟踪和污点数据相关的信息的流向,可以知道它们是否会影响某些关键的程序操作,进而挖掘程序漏洞. 即将程序是否存在某种漏洞的问题转化为污点信息是否会被 Sink 点上的操作所使用的问题.

污点分析的处理过程可以分成 3 个阶段:

(1) 识别污点源和汇聚点;(根据所分析的系统的不同使用定制的识别策略)
(2) 污点传播分析;(利用特定的规则跟踪分析污点信息在程序中的传播过程)
(3) 漏洞检测、无害处理

识别污点源和汇聚点

现有的识别污点源和汇聚点的方法可以大致分成 3 类:

(1)使用启发式的策略进行标记,例如把来自程序外部输入的数据统称为“污点”数据,保守地认为这些数据有可能包含恶意的攻击数据(如 PHP Aspis);
(2)根据具体应用程序调用的 API 或者重要的数据类型,手工标记源和汇聚点(如 DroidSafe[12]);
(3)使用统计或机器学习技术自动地识别和标记污点源及汇聚点.[11]

污点传播分析

污点传播分析就是分析污点标记数据在程序中的传播途径.按照分析过程中关注的程序依赖关系的不同, 可以将污点传播分析分为显式流分析和隐式流分析.

(1)显示流分析

污点传播分析中的显式流分析就是分析污点标记如何随程序中变量之间的数据依赖关系传播.

(2)隐式流分析

污点传播分析中的隐式流分析是分析污点标记如何随程序中变量之间的控制依赖关系传播,也就是分析污点标记如何从条件指令传播到其所控制的语句.

无害处理

污点数据在传播的过程中可能会经过无害处理模块,无害处理模块是指污点数据经过该模块的处理后,数据本身不再携带敏感信息或者针对该数据的操作不会再对系统产生危害.换言之,带污点标记的数据在经过无害处理模块后,污点标记可以被移除.正确地使用无害处理可以降低系统中污点标记的数量,提高污点分析的效率,并且避免由于污点扩散导致的分析结果不精确的问题.

在应用过程中,为了防止敏感数据被泄露(保护保密性),通常会对敏感数据进行加密处理.此时,加密库函数应该被识别成无害处理模块.这一方面是由于库函数中使用了大量的加密算法,导致攻击者很难有效地计算出密码的可能范围;另一方面是加密后的数据不再具有威胁性,继续传播污点标记没有意义.

此外,为了防止外界数据因为携带危险操作而对系统关键区域产生危害(保护完整性),通常会对输入的数据进行验证.此时,输入验证(input validation)模块应当被识别成无害处理模块.例如,为了防止代码注入漏洞,PHP 提供的 htmlentities 函数可以将特殊含义的 HTML 字符串转化成HTML实体(例如,将’<‘转化成’<’).输入字符串经过上述转化后不会再携带可能产生危害的代码,可以安全地 发送给用户使用.除了语言自带的输入验证函数外,一些系统还提供了额外的输入验证工具,比如ScriptGard[50],CSAS[51],XSS Auditor[]52,Bek[53].这些工具也应被识别成无害处理模块.

综上,目前对污点源、污点汇聚点以及无害处理模块的识别通常根据系统或漏洞类型使用定制的方法.由于这些方法都比较直接,本文将不再进行更深入的探讨.下一节将重点介绍污点传播中的关键技术.

总结一下,使用污点分析检测程序漏洞的工作原理如下图所示:

污点传播分析的关键技术

污点传播分析是当前污点分析领域的研究重点.与程序分析技术相结合,可以获得更加高效、精确的污点分析结果.根据分析过程中是否需要运行程序,可以将污点传播分析分为静态污点分析和动态污点分析.本节主要介绍如何使用动/静态程序分析技术来解决污点传播中的显式流分析和隐式流分析问题.

污点传播中的显式流分析

静态分析技术

静态污点传播分析(简称静态污点分析)是指在不运行且不修改代码的前提下,通过分析程序变量间的数据依赖关系来检测数据能否从污点源传播到污点汇聚点.

静态污点分析的对象一般是程序的源码或中间表示.可以将对污点传播中显式流的静态分析问题转化为对程序中静态数据依赖的分析:

(1)首先,根据程序中的函数调用关系构建调用图(call graph,简称CG);
(2)然后,在函数内或者函数间根据不同的程序特性进行具体的数据流传播分析.常见的显式流污点传播方式包括直接赋值传播、通过函数(过程)调用传播以及通过别名(指针)传播.

动态分析技术

动态污点传播分析(简称动态污点分析)是指在程序运行过程中,通过实时监控程序的污点数据在系统程序中的传播来检测数据能否从污点源传播到污点汇聚点.动态污点传播分析首先需要为污点数据扩展一个污点标记(tainted tag)的标签并将其存储在存储单元(内存、寄存器、缓存等)中,然后根据指令类型和指令操作数设计相应的传播逻辑传播污点标记.

动态污点传播分析按照实现层次被分为基于硬件、基于软件以及混合型的污点传播分析这3类.

1.硬件

基于硬件的污点传播分析需要定制的硬件支持,一般需要在原有体系结构上为寄存器或者内存扩展一个标记位,用来存储污点标记,代表的系统有 Minos[62],Raksha[63]等.

2.基于软件

基于软件的污点传播分析通过修改程序的二进制代码来进行污点标记位的存储与传播,代表的系统有 TaintEraser[64],TaintDroid[19]等.

基于软件的污点传播的优点在于不必更改处理器等底层的硬件,并且可以支持更高的语义逻辑的安全策略(利用其更贴近源程序层次的特点),但缺点是使用插桩(instrumentation 在保证被测程序原有逻辑完整性的基础上在程序中插入一些探针)或代码重写(code rewriting)修改程序往往会给分析系统带来巨大的开销.相反地,基于硬件的污点传播分析虽然可以利用定制硬件降低开销,但通常不能支持更高的语义逻辑的安全策略,并且需要对处理器结构进行重新设计.

3.混合型

混合型的污点分析是对上述两类方法的折中,即,通过尽可能少的硬件结构改动以保证更高的语义逻辑的安全策略,代表的系统有 Flexitaint[65],PIFT[19]等.

目前,针对动态污点传播分析的研究工作关注的首要问题是如何设计有效的污点传播逻辑,以确保精确的污点传播分析.

污点传播中的隐式流分析

(1)静态分析技术

静态隐式流分析面临的核心问题是精度与效率不可兼得的问题.精确的隐式流污点传播分析需要分析每一个分支控制条件是否需要传播污点标记.路径敏感的数据流分析往往会产生路径爆炸问题,导致开销难以接受.为了降低开销,一种简单的静态传播(标记)分支语句的污点标记方法是将控制依赖于它的语句全部进行污点标记,但该方法会导致一些并不携带隐私数据的变量被标记,导致过污染情况的发生.过污染会引起污点的大量扩散,最终导致用户得到的报告中信息过多,难以使用.

(2)动态分析技术

动态隐式流分析关注的首要问题是如何确定污点控制条件下需要标记的语句的范围.由于动态执行轨迹并不能反映出被执行的指令之间的控制依赖关系,**目前的研究多采用离线的静态分析辅助判断动态污点传播中的隐式流标记范围.**Clause等人[70]提出,利用离线静态分析得到的控制流图节点间的后支配(post-dominate)关系来解决动态污点传播中的隐式流标记问题.

污点分析方法实现

静态污点分析技术

静态污点分析系统首先对程序代码进行解析,获得程序代码的中间表示,然后在中间表示的基础上对程序代码进行控制流分析等辅助分析,以获得需要的控制流图、调用图等.在辅助分析的过程中,系统可以利用污点分析规则在中间表示上识别程序中的 Source 点和 Sink 点.最后检测系统根据污点分析规则,利用静态污点分析检查程序是否存在污点类型的漏洞.

(1)基于数据流的污点分析

在基于数据流的污点分析中,常常需要一些辅助分析技术,例如别名分析、取值分析等,来提高分析精度.辅助分析和污点分析交替进行,通常沿着程序路径的方向分析污点信息的流向,检查 Source 点处程序接收的污点信息是否会影响到 Sink 点处的敏感操作.

过程内的分析中,按照一定的顺序分析过程内的每一条语句或者指令,进而分析污点信息的流向.

  • 记录污点信息.在静态分析层面,程序变量的污染情况为主要关注对象.为记录污染信息,通常为变量添加一个污染标签.最简单的就是一个布尔型变量,表示变量是否被污染.更复杂的标签还可以记录变量的污染信息来自哪些 Source 点,甚至精确到 Source 点接收数据的哪一部分.当然也可以不使用污染标签,这时我们通过对变量进行跟踪的方式达到分析污点信息流向的目的.例如使用栈或者队列来记录被污染的变量.
  • 程序语句的分析.在确定如何记录污染信息后,将对程序语句进行静态分析.通常我们主要关注赋值语句、控制转移语句以及过程调用语句三类.

  • 代码的遍历.一般情况下,常常使用流敏感的方式或者路径敏感的方式进行遍历,并分析过程中的代码.如果使用流敏感的方式,可以通过对不同路径上的分析结果进行汇集,以发现程序中的数据净化规则.如果使用路径敏感的分析方式,则需要关注路径条件,如果路径条件中涉及对污染变量取值的限制,可认为路径条件对污染数据进行了净化,还可以将分析路径条件对污染数据的限制进行记录,如果在一条程序路径上,这些限制足够保证数据不会被攻击者利用,就可以将相应的变量标记为未污染的. 过程间的分析与数据流过程间分析类似,使用自底向上的分析方法,分析调用图中的每一个过程,进而对程序进行整体的分析.

(2)基于依赖关系的污点分析

在基于依赖关系的污点分析中,首先利用程序的中间表示、控制流图和过程调用图构造程序完整的或者局部的程序的依赖关系.在分析程序依赖关系后,根据污点分析规则,检测 Sink 点处敏感操作是否依赖于 Source 点.

分析程序依赖关系的过程可以看做是构建程序依赖图的过程.程序依赖图是一个有向图.它的节点是程序语句,它的有向边表示程序语句之间的依赖关系.程序依赖图的有向边常常包括数据依赖边和控制依赖边.在构建有一定规模的程序的依赖图时,需要按需地构建程序依赖关系,并且优先考虑和污点信息相关的程序代码.

动态污点分析

动态污点分析是在程序运行的基础上,对数据流或控制流进行监控,从而实现对数据在内存中的显式传播、数据误用等进行跟踪和检测.动态污点分析与静态污点分析的唯一区别在于静态污点分析技术在检测时并不真正运行程序,而是通过模拟程序的执行过程来传播污点标记,而动态污点分析技术需要运行程序,同时实时传播并检测污点标记.

  • 动态污点分析技术可分为三个部分:
  • 动态污点分析的优缺点:

动态污点分析的方法实现

  • (1)污点数据标记
  • (2)污点动态跟踪
  • (3)污点误用检查

动态污点分析的实例分析

下面我们来看一个使用动态污点分析的方法检测缓冲区溢出漏洞的例子.

void fun(char *str)
{
    char temp[15];
    printf("in strncpy, source: %s\n", str);
    strncpy(temp, str, strlen(str));        // Sink 点
}
int main(int argc, char *argv[])
{
    char source[30];
    gets(source);                           // Source 点
    if (strlen(source) < 30)
        fun(source);
    else
        printf("too long string, %s\n", source);
    return 0;
}

漏洞很明显, 调用 strncpy 函数存在缓冲区溢出.

程序接受外部输入字符串的二进制代码如下:

0x08048609 <+51>:    lea    eax,[ebp-0x2a]
0x0804860c <+54>:    push   eax
0x0804860d <+55>:    call   0x8048400 <gets@plt>
...
0x0804862c <+86>:    lea    eax,[ebp-0x2a]
0x0804862f <+89>:    push   eax
0x08048630 <+90>:    call   0x8048566 <fun>

程序调用 strncpy 函数的二进制代码如下:

0x080485a1 <+59>:    push   DWORD PTR [ebp-0x2c]
0x080485a4 <+62>:    call   0x8048420 <strlen@plt>
0x080485a9 <+67>:    add    esp,0x10
0x080485ac <+70>:    sub    esp,0x4
0x080485af <+73>:    push   eax
0x080485b0 <+74>:    push   DWORD PTR [ebp-0x2c]
0x080485b3 <+77>:    lea    eax,[ebp-0x1b]
0x080485b6 <+80>:    push   eax
0x080485b7 <+81>:    call   0x8048440 <strncpy@plt>

首先,在扫描该程序的二进制代码时,能够扫描到 call gets@plt ,该函数会读入外部输入,即程序的攻击面.确定了攻击面后,我们将分析污染源数据并进行标记,即将 [ebp-0x2a] 数组(即源程序中的source)标记为污点数据.程序继续执行,该污染标记会随着该值的传播而一直传递.在进入 fun() 函数时,该污染标记通过形参实参的映射传递到参数 str 上.然后运行到 Sink 点函数 strncpy().该函数的第二个参数即 str 和 第三个参数 strlen(str) 都是污点数据.最后在执行 strncpy() 函数时,若设定了相应的漏洞规则(目标数组小于源数组),则漏洞规则将被触发,检测出缓冲区溢出漏洞.

总结

污点分析作为信息流分析的一种实践技术,被广泛应用于互联网及移动终端平台上应用程序的信息安全保障中.本文介绍了污点分析的基本原理和通用技术,并针对近年来污点分析在解决实际应用程序安全问题时遇到的问题和关键解决技术进行了分析综述.不同于基于安全类型系统的信息流分析技术,污点分析可以不改变程序现有的编程模型或语言特性,并提供精确信息流传播跟踪. 在实际应用过程中,污点分析还需要借助传统的程序分析技术的支持,例如静态分析中的数据流分析、动态分析中的代码重写等技术.另外,结合测试用例生成技术、符号执行技术以及虚拟机技术,也会给污点分析带来更多行之有效的解决方案.