20189224 2018-2019-2 《密码与安全新技术专题》论文总结
课程:《密码与安全新技术专题》
班级: 1892
姓名: 史馨怡
学号:20189224
上课教师:王志强
上课日期:2019年5月21日
必修/选修: 选修
论文学习总结:safeinit:Comprehensive and Practical Mitigation of Uninitialized Read Vulnerabilities
未初始化值:使用未初始化的内存会引入漏洞,这些漏洞可以操纵程序的控制流或泄露信息。同时,C / C ++编译器可以在利用读取未初始化的内存这种“未定义的行为”时引入新的漏洞
现存威胁
敏感数据的披露:
1)数据生命周期持续时间长于预期
2)不是所有情况下编译器可以提供memset优化调用
3)未初始化数据的使用受到不可信输入的影响
绕过安全防御
1)现代软件防御依赖于敏感元数据的保护
2)未初始化的值提供了指针公开的丰富资源。
软件开发
1)攻击者直接劫持控制流
2)局部变量没有在全部路径上初始化
堆栈变量
1)内存重用,导致函数堆栈帧提供丰富的敏感数据源
2)即使在函数调用之前/之后清除寄存器和堆栈帧也不足以避免所有潜在的未初始化变量。
3)循环内部的内存重用
未定义行为
编译器将未定义的值解释为使得优化更方便的任何值,使得程序逻辑不一致。
文章实现成果
1)提出了SafeInit,一种基于编译器的解决方案
2)通过确保栈和堆上的初始化来自动减轻未初始化的值读取。
3)提出的优化可以将解决方案的开销降低到最低水平(<5%),并且可以直接在现代编译器中实现基于clang和LLVM的SafeInit原型实现,并表明它可以应用于大多数真实的C / C++应用程序而无需任何额外的手动工作。
4)评估我们在CPU-intensiv占用CPU资源的操作、IO-intensive占用I/O设备的操作以及Linux内核方面的工作,并验证是否成功地减轻了现存的漏洞
safeinit
llvm/clang架构
LLVM包括了一个狭义的LLVM和一个广义的LLVM。广义的LLVM其实就是指整个LLVM编译器架构,包括了前端、后端、优化器、众多的库函数以及很多的模块;而狭义的LLVM其实就是聚焦于编译器后端功能(代码生成、代码优化等)的一系列模块和库。Clang是一个C++编写、基于LLVM的C/C++/Objective-C/Objective-C++编译器。Clang是一个高度模块化开发的轻量级编译器,它的编译速度快、占用内存小、非常方便进行二次开发。上图是LLVM和Clang的关系:Clang其实大致上可以对应到编译器的前端,主要处理一些和具体机器无关的针对语言的分析操作;编译器的优化器部分和后端部分其实就是我们之前谈到的LLVM后端(狭义的LLVM);而整体的Compiler架构就是LLVM架构。
safeinit架构
1)通过调整工具链来确保所有堆栈和堆分配始终初始化,从而减轻通用程序中的这些错误。 SafeInit在编译器级别实现。
2)必须在编译器本身内完成。 只需在编译过程中传递额外的加固标记即可启用SafeInit。
如图编译器在获得C/C++文件后,编译器前端将源文件转换为中间语言(IR),通过初始化、代码优化结合现存编译器的优化器,之后通过无效数据消除、强化分配器最后获得二进制文件。Safeinit在整个过程中所添加的就是 初始化全部变量、优化以及强化分配器,来避免或缓解未初始化值。最后,SafeInit优化器提供了非侵入式转换和优化,它们与现有的编译器优化(必要时自行修改)以及最终组件(现有“死存储消除”优化的扩展)一起运行。这些构建在我们的初始化传递和分配器之上,执行更广泛的删除不必要的初始化代码,证明我们的解决方案的运行时开销可以最小化。
初始化:保证堆和栈内的局部变量全部初始化
SafeInit在首次使用之前初始化所有局部变量,将局部变量看做新分配的变量处理。SafeInit通过修改编译器编译代码的中间表示(IR),在每个变量进入作用域后进行初始化(例如内置memset)。
强化分配器
1)SafeInit的强化分配器可确保在返回应用程序之前将所有新分配的内存清零。——敏感数据的保护
2)通过修改现代高性能堆分配器tcmalloc来实现我们的强化分配器。——提高性能
3)修改了LLVM,以便在启用SafeInit时将来自新分配的内存的读取视为返回零而不是undef。 ——初始化数据
优化器:可在提高效率和非侵入性的同时提高SafeInit的性能。优化器的主要目标是更改现有编译器中可用的其他标准优化,以消除任何不必要的初始化。
1)存储下沉:存储到本地的变量应尽可能接近它的用途。
2)检测初始化:检测初始化数组(或部分数组)的典型代码
字符串缓冲区
3)用于存储C风格的以空字符结尾的字符串的缓冲区通常仅以“安全”方式使用,其中永远不会使用超出空终止符的内存中的数据。传递给已知C库字符串函数(例如strcpy和strlen)的缓冲区是“安全的”,优化器检测到该缓冲区始终被初始化,可以删除掉该缓冲区的初始化代码。
无效存储消除(DSE):可以删除总是被另一个存储覆盖而不被读取的存储。
1)堆清除:所有堆分配都保证初始化为零,使用零存储删除堆内存
2)非恒定长度存储清除:为了删除动态堆栈分配和堆分配的不必要初始化
3)交叉块DSE:可以跨多个基本块执行无效存储消除
4)只写缓冲区:通过指定该缓冲区只用来存储而不是删除,就可以将该缓冲区删除
评估
本测试的基线配置是clang/LLVM的未修改版本,以及tcmalloc未修改版本。
基准测试运行在(4核)Intel i7-3770上,内存为8GB,运行(64位)Ubuntu 14.04.1。 禁用CPU频率缩放,并启用超线程。
安全
开销
Baseline Linux系统本身
w/Optimizer 加入强化分配器safeinit编译Linux内核
Stack safeinit 利用简单safeinit编译Linux内核