EINSTEIN


paper:

https://www.usenix.org/system/files/usenixsecurity24-johannesmeyer.pdf

paper

introduce

data-only attack 研究现状

许多基于数据流的攻击手法最终目的还是通过篡改关键数据实现对控制流的影响;实际上,他们仍然只能探索很小规模的程序空间,而在一个很小的攻击面寻找可用的数据流攻击,尚且需要很复杂的分析(例如符号执行)来满足复杂的约束限制。

还是搜索空间大了,比如覆盖所有的内存空间,在任何可能的时机使用这个覆盖了的数据等等。

因此必须简化假设:

  1. 攻击必须仅仅覆盖写特定的部分内存空间;
  2. 攻击者必须通过其他的方式到达gadget(应该是特定的代码,即使用被覆盖数据的代码片段)的入口点;
  3. 攻击者必须人工组合代码片段(gadget);

这样也带来了几个缺点:

  1. 限制了exploit的规模;
  2. 留下了大量的人工工作;

轻量化思路

基于以下几个发现:

  1. 污点分析可以简化很多复杂的约束限制;
  2. 表达性(尤其是图灵完备性)是不需要的;
  3. 操纵一个程序的预期路径是不必要的;
  4. 在初始化后,一个程序将许多类型的数据视为不可变的,因此,这些数据有很少(如果有的话)约束。

设计思路:

  1. 首先用一种独一无二的颜色污染所有可能被覆盖写的数据;
  2. 然后跟踪污点流向敏感的系统调用;
  3. 此外也跟踪污点流向某些在系统调用之间共享的库状态;
  4. 最后生成exp,并进行测试验证其有效性;

威胁模型

目标程序:

  1. 有内存破坏漏洞;
  2. 开了很多保护;

对攻击者的假设:

  1. 可以获得等价的二进制文件;
  2. 可以合法地和目标程序进行交互;
  3. 可以通过地址泄露绕过ASLR;
  4. 可以利用静止程序状态下任意写原语的内存损坏漏洞;
  5. 旨在强制目标程序用攻击者控制的参数调用系统调用;

不同于以往研究的几个假设:

  1. 本文强调是静止程序状态下的任意写原语;
  2. 目标是控制系统调用的参数,而不是图灵完备性;

具体步骤

以一个web server 为例,其分为三个状态:

  1. 初始化;
  2. 静态(等待输入)
  3. 响应(处理输入)

分为6个步骤:

  1. 当目标程序处于静止状态时,分析其状态,(这个时候全局变量已经被初始化了);
  2. 建模一个任意内存写的漏洞:标记所有可以被这个漏洞写到的内存;同时会在内存快照中记录受污染的数据;
  3. 和目标程序进行交互,污点随之传播;
  4. 运行过程中发现敏感的syscall,认定这是一个候选gadget,同时记录syscall的相关信息;
  5. 构建exp,生成候选exp,(addr, val)对;
  6. 重启服务,测试exp;

design

污点分析引擎

几个定义:

  1. color:是一个元数据,代表一个可以被攻击者覆盖写的地址;
  2. tag/tagset:color的集合,代表一些可以被攻击者控制的数据;
  3. tagmap:包含了所有程序数据的tag,

就是在影子内存中用不同的color标记污点?

提出了两个新型的挑战:

  1. 首先,由于所有非控制数据都可能成为攻击向量,我们需要一种方法能够对无限量的数据进行无限数量的污点颜色的唯一追踪
  2. 由于程序通常在复杂的点上调用系统调用,程序空间比较大?运行比较复杂?

几个设计关键点:

  1. 访问tagmap:目前已有的方法,一种是访问PT等动态结构,速度慢但是占用空间少;另一种方法是利用影子内存,这是一个静态的索引结构,这样速度快但是空间开销大;本文提出了一种节省内存空间的影子内存方法,通过指示连接器将用户地址空间限制为高4G,(这样就只用32位即可表示所有用户地址了)然后将低地址保留为影子内存,这样可以快速实现用户地址和影子内存地址的映射计算,64位的指针可以轻松压缩成32位的指针。
  2. 初始化tagmap:当前有工作是利用了page fault动态初始化,还有工作是从一个大部分都被污染了的map开始,之后每访问一个未初始化的tag page就要加入一个定制初始化的page进去(说了啥其实没看懂);而本文则借助Linux的userfaultfd这样可以借助page fault迅速识别一个未初始化的页然后以软件的方式解决page fault
  3. 结合tags:支持color的叠加,比如两个污点数据进行运算,就是color的叠加;设置color叠加的上限,如果color叠加超过一个上限则认为这个数据很复杂、受多方支配、攻击者很难利用,

污点传播策略

建模一个任意地址写

不污染stack;

用压缩的地址来标识每一个不同的源byte;

为了跟踪每一个具体值的起源,本文也对所有内存做了一个快照;

所以对于每一个污染的tag,都有(addr, val);

跟踪依赖

为了满足间接依赖(例如,syscall 的参数X使用了地址Y中存储的污点指针中读出来的数据),本文实现了load指针传播,(将所有从污点指针中读出来的数据也污染)

建模系统调用的exploit

在敏感syscall调用前加一个hook,如果发现参数是被污染的,旧纪录以下信息:

  1. syscall的名字、参数、参数的污点以及调用链;
  2. 区别于其他report的信息,例如PID、TID;
  3. 帮助复现exp的信息;

建模系统调用链

重点是系统调用之间的参数传递;

这里关注文件描述符的传递;(你敢说你不是在pwn???)

直接控制:创建文件描述符的syscall;

间接控制:使用已有文件描述符的syscal;

首先跟踪能够创建文件描述符的syscall,然后通过检查其他参数及其污点特性来判断是否可以创建一个输出流;如果攻击者可以创建一个输出流,那么他可以控制该流在FD table中的入口;因此后续对这个流的访问需要标记为污点,


文章作者: q1ming
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 q1ming !
  目录