Open bsauce opened 6 months ago
https://bsauce.github.io/2024/05/18/K-LEAK/
【bsauce读论文】2024-NDSS-K-LEAK:Linux内核infoleak利用自动生成基本信息 原文标题:K-LEAK: Towards Automating the Generation of Multi-Step Infoleak Exploits against the Linux Kernel 原文作者:Zhengchuan Liang, Xiaochen Zou, Chengyu Song, Zhiyun Qian 作者单位:加州大学河滨分校(UC Riverside) 关键词:信息泄露, Linux内核, 自动化, 安全漏洞 原文链接:DOI link 开源代码:GitHub link1. 论文要点论文简介:K-LEAK工具是一种基于图的数据流分析框架,针对Linux内核中的内存漏洞(UAF/OOB),辅助生成infoleak的利用,绕过内核KASLR防护。本文将infoleak利用生成问题看作是数据流搜索问题,通过对内存错误引入的非预期数据流,以及现有内存错误如何转化为新的内存错误进行建模,K-LEAK能够系统性的搜索出多步infoleak数据流路径。特点: (1)统一处理预期和非预期数据流片段,将内核敏感信息连接到泄露点(eg, copy_to_user()); (2)支持跨syscall边界的推理; (3)允许在发现最终的信息泄露之前推理中间原语(也即新的内存错误)。测试:测试了250个由syzbot fuzz出来的Linux内核内存漏洞,找到40个漏洞的infoleak路径,为20个漏洞生成EXP。2. Introduction主要介绍数据流分析和points-to分析。DFG问题:当前的DFG图没有考虑内存错误,作者引入了M-DFG(Memory-error-augmented data-flow graph),能捕获内核中预期和非预期的数据流,其中node表示程序点,edge表示预期和非预期的数据流。可以通过M-DFG来搜索infoleak路径和能获得新内存错误的可控寄存器。Points-to分析很难用于Linux内核的原因:Linux有一个特性,multi-interaction[13],也即多个程序入口,用户程序可以调用多个syscall和内核交互,多个syscall可通过共享内存来传播数据流。这会给infoleak路径搜索带来一个问题,敏感信息的数据流可能会跨多个syscall,例如在syscall A中将敏感信息存入全局内存,在syscall B中读取敏感信息并传播到泄露点,导致搜索空间变大。本文思路:本文的points-to分析采用了SUTURE,数据流分析采用的是M-DFG。SUTURE[51]解决了multi-interaction问题,它对每个syscall入口单独进行points-to分析和数据流分析,对每个syscall生成points-to总结和数据流总结。两种分析都是inter-procedural flow-, context-, field-sensitive。在points-to分析中,它对每个入口创建抽象内存对象,使用访问路径来确定内存对象的别名(例如,A入口中的内存对象o1和B入口的内存对象o2是别名);在数据流分析中(主要采用污点分析),在获得所有入口的data-flow总结后,就会连接不同入口的数据流,构成跨syscall的数据流。3. 研究内容挑战: (1)对内存错误带来的非预期数据流进行建模。内存错误的本质是错误指针的引用(指针越界或指向空闲/未初始化内存),会导致load读和store写操作之间新的数据流。也就是说,错误指针会导致load和store指针的非预期的别名。需设计针对错误指针的别名分析。 (2)对跨syscall数据流进行建模。非预期的跨syscall数据流是指,某syscall利用内存错误,非预期的读或写另一个syscall使用的内存。 (3)对额外内存错误进行建模。内存错误有时需要转化后才能实现infoleak,例如elastic对象。本文实现迭代搜索算法,不仅搜索infoleak路径,还搜索攻击者可控的指针,并检查通过可控指针是否能获得新的内存错误。工作过程:方框表示分析组件,椭圆表示输入/输出数据。内核源码编译为LLVM中间码,经过points-to分析构建M-DFG图,引入初始内存错误后扩展为M-DFG,通过迭代搜索来搜索infoleak路径和攻击者可控的指针,如果发现新的内存错误,就根据该信息扩展出新的M-DFG进行迭代。案例分析:参加Listing 2 代码图。 UAF读:12行处存在UAF读,ax25_dev ax25_dev指向已被释放的对象,读取的值被存入ax25_cb ax25对象中; 堆喷占用:为了泄露信息,需先堆喷struct usb_bus对象占据空闲的ax25_cb对象,往漏洞对象写敏感数据(ubus指针,17行); 泄露:28行会将ubus指针赋给另一变量,29行泄露出来。M-DFG示例:水平线表示infoleak路径,包含3段,对应3个syscall入口。虚线是pointer edge(地址的存储与载入),实线是data edge(数据的存储与载入)。 mon_bus_init()——17行,store点将敏感指针存入struct mon_bus对象; ax25_setsockopt()——12行,从地址&ax25_dev->values[N2]读取,由于 &mbus->u_bus和&ax25_dev->values[N2]别名(重分配导致内存重叠),所以引入红色箭头(由UAF内存错误导致的非预期边),连接上一次的store和本次load,也称为写后读依赖(read-after-write data edge); ax25_getsockopt()——28行,临时寄存器值保存到栈地址valptr=&val,copy_to_user将valptr地址的内容拷贝到用户空间。所以说,M-DFG引入了内存错误带来的数据流边(read-after-write data edge),这样ax25_cb和struct mon_bus就因为UAF而形成别名。总目标就是,找到一条从敏感信息到泄露点的infoleak路径。3-1. M-DFG生成原理:基于两个信息生成,(1)LLVM的SSA静态单赋值,(2)SUTURE[51]的指向分析结果。M-DFG包含三类node:variable node / load node / store loadM-DFG包含两类edge:针对不同的指令(BinOp / ConOp / Phi / Call / Load / Store)分别进行分析,确定添加哪种边。copy_to_user()当作一类特殊的load/store指令。如果store的指针和load的指针是别名,则添加一条data edge。不处理栈上的,栈指针和栈帧指针。 data edge —— 直接数据流传递,实心边; pointer edge —— 特殊的数据流边,只针对store/load指令,虚线边。3-2. M-DFG搜索M-DFG优势: (1)对比SUTURE[51]:SUTURE使用污点分析来解决数据依赖问题,创建污点总结(污点source到污点sink),这种数据结构不高效、占用内存大; (2)对比SVF:SVF使用变量节点来表示顶层变量和内存节点,M-DFG去掉内存节点并引入load/store节点和pointer edge,M-DFG可以用stored_value->store_node->load_node->loaded_value来表示 read-after-write,类似于stored_value->memory_node->loaded_value,但M-DFG的优势是能够解释如何构造新的内存错误,因为M-DFG比普通DFG多了一个pointer edge(新的内存错误,表示攻击者是否可通过一个pointer edge来控制一个load/store节点)。搜索infoleak路径:找到从敏感信息(内核指针,也即函数指针、数据指针,keys,network&IPC消息)到泄露点(见Table III)的路径。并使用SyzScope[54]中的符号执行引擎来验证路径可达性。搜索新内存错误:等效于搜索一条路径,从用户可控的数据节点(copy_from_user())到指针变量节点,该指针稍后会被load/store使用。如果存在该数据流路径,且指针变量可指向非预期内存位置,则表示可构造新内存错误。迭代搜索:每次迭代,先用新内存错误来扩展M-DFG,然后搜索infoleak路径和新内存错误,新找到的内存错误添加到下一轮迭代。可利用性验证:为了简化验证,本文假设堆喷成功,利用gdb将敏感信息写入待读的地址。例如,本来需堆喷mbus占据ax25_dev对象,现在使用GDB将mbus->ubus指针写入load指令(也即tmp = mbus->u_bus)。如果能通过测试用例泄露敏感信息,则可利用。4. 实现总体采用静态分析和符号执行实现,组件包含 M-DFG builder 和 Graph Searcher。 采用Syzscope[54]来获得初始的内存错误;M-DFG builder 是基于SUTURE实现;Graph Searcher中,采用BFS来搜索infoleak路径和新的内存错误,采用Angr符号执行来验证路径可达性。5. 实验对syzbot上的250个UAF/OOB漏洞进行测试,能够找到40个infoleak路径,生成21个EXP。
https://bsauce.github.io/2024/05/18/K-LEAK/
【bsauce读论文】2024-NDSS-K-LEAK:Linux内核infoleak利用自动生成基本信息 原文标题:K-LEAK: Towards Automating the Generation of Multi-Step Infoleak Exploits against the Linux Kernel 原文作者:Zhengchuan Liang, Xiaochen Zou, Chengyu Song, Zhiyun Qian 作者单位:加州大学河滨分校(UC Riverside) 关键词:信息泄露, Linux内核, 自动化, 安全漏洞 原文链接:DOI link 开源代码:GitHub link1. 论文要点论文简介:K-LEAK工具是一种基于图的数据流分析框架,针对Linux内核中的内存漏洞(UAF/OOB),辅助生成infoleak的利用,绕过内核KASLR防护。本文将infoleak利用生成问题看作是数据流搜索问题,通过对内存错误引入的非预期数据流,以及现有内存错误如何转化为新的内存错误进行建模,K-LEAK能够系统性的搜索出多步infoleak数据流路径。特点: (1)统一处理预期和非预期数据流片段,将内核敏感信息连接到泄露点(eg, copy_to_user()); (2)支持跨syscall边界的推理; (3)允许在发现最终的信息泄露之前推理中间原语(也即新的内存错误)。测试:测试了250个由syzbot fuzz出来的Linux内核内存漏洞,找到40个漏洞的infoleak路径,为20个漏洞生成EXP。2. Introduction主要介绍数据流分析和points-to分析。DFG问题:当前的DFG图没有考虑内存错误,作者引入了M-DFG(Memory-error-augmented data-flow graph),能捕获内核中预期和非预期的数据流,其中node表示程序点,edge表示预期和非预期的数据流。可以通过M-DFG来搜索infoleak路径和能获得新内存错误的可控寄存器。Points-to分析很难用于Linux内核的原因:Linux有一个特性,multi-interaction[13],也即多个程序入口,用户程序可以调用多个syscall和内核交互,多个syscall可通过共享内存来传播数据流。这会给infoleak路径搜索带来一个问题,敏感信息的数据流可能会跨多个syscall,例如在syscall A中将敏感信息存入全局内存,在syscall B中读取敏感信息并传播到泄露点,导致搜索空间变大。本文思路:本文的points-to分析采用了SUTURE,数据流分析采用的是M-DFG。SUTURE[51]解决了multi-interaction问题,它对每个syscall入口单独进行points-to分析和数据流分析,对每个syscall生成points-to总结和数据流总结。两种分析都是inter-procedural flow-, context-, field-sensitive。在points-to分析中,它对每个入口创建抽象内存对象,使用访问路径来确定内存对象的别名(例如,A入口中的内存对象o1和B入口的内存对象o2是别名);在数据流分析中(主要采用污点分析),在获得所有入口的data-flow总结后,就会连接不同入口的数据流,构成跨syscall的数据流。3. 研究内容挑战: (1)对内存错误带来的非预期数据流进行建模。内存错误的本质是错误指针的引用(指针越界或指向空闲/未初始化内存),会导致load读和store写操作之间新的数据流。也就是说,错误指针会导致load和store指针的非预期的别名。需设计针对错误指针的别名分析。 (2)对跨syscall数据流进行建模。非预期的跨syscall数据流是指,某syscall利用内存错误,非预期的读或写另一个syscall使用的内存。 (3)对额外内存错误进行建模。内存错误有时需要转化后才能实现infoleak,例如elastic对象。本文实现迭代搜索算法,不仅搜索infoleak路径,还搜索攻击者可控的指针,并检查通过可控指针是否能获得新的内存错误。工作过程:方框表示分析组件,椭圆表示输入/输出数据。内核源码编译为LLVM中间码,经过points-to分析构建M-DFG图,引入初始内存错误后扩展为M-DFG,通过迭代搜索来搜索infoleak路径和攻击者可控的指针,如果发现新的内存错误,就根据该信息扩展出新的M-DFG进行迭代。案例分析:参加Listing 2 代码图。 UAF读:12行处存在UAF读,ax25_dev ax25_dev指向已被释放的对象,读取的值被存入ax25_cb ax25对象中; 堆喷占用:为了泄露信息,需先堆喷struct usb_bus对象占据空闲的ax25_cb对象,往漏洞对象写敏感数据(ubus指针,17行); 泄露:28行会将ubus指针赋给另一变量,29行泄露出来。M-DFG示例:水平线表示infoleak路径,包含3段,对应3个syscall入口。虚线是pointer edge(地址的存储与载入),实线是data edge(数据的存储与载入)。 mon_bus_init()——17行,store点将敏感指针存入struct mon_bus对象; ax25_setsockopt()——12行,从地址&ax25_dev->values[N2]读取,由于 &mbus->u_bus和&ax25_dev->values[N2]别名(重分配导致内存重叠),所以引入红色箭头(由UAF内存错误导致的非预期边),连接上一次的store和本次load,也称为写后读依赖(read-after-write data edge); ax25_getsockopt()——28行,临时寄存器值保存到栈地址valptr=&val,copy_to_user将valptr地址的内容拷贝到用户空间。所以说,M-DFG引入了内存错误带来的数据流边(read-after-write data edge),这样ax25_cb和struct mon_bus就因为UAF而形成别名。总目标就是,找到一条从敏感信息到泄露点的infoleak路径。3-1. M-DFG生成原理:基于两个信息生成,(1)LLVM的SSA静态单赋值,(2)SUTURE[51]的指向分析结果。M-DFG包含三类node:variable node / load node / store loadM-DFG包含两类edge:针对不同的指令(BinOp / ConOp / Phi / Call / Load / Store)分别进行分析,确定添加哪种边。copy_to_user()当作一类特殊的load/store指令。如果store的指针和load的指针是别名,则添加一条data edge。不处理栈上的,栈指针和栈帧指针。 data edge —— 直接数据流传递,实心边; pointer edge —— 特殊的数据流边,只针对store/load指令,虚线边。3-2. M-DFG搜索M-DFG优势: (1)对比SUTURE[51]:SUTURE使用污点分析来解决数据依赖问题,创建污点总结(污点source到污点sink),这种数据结构不高效、占用内存大; (2)对比SVF:SVF使用变量节点来表示顶层变量和内存节点,M-DFG去掉内存节点并引入load/store节点和pointer edge,M-DFG可以用stored_value->store_node->load_node->loaded_value来表示 read-after-write,类似于stored_value->memory_node->loaded_value,但M-DFG的优势是能够解释如何构造新的内存错误,因为M-DFG比普通DFG多了一个pointer edge(新的内存错误,表示攻击者是否可通过一个pointer edge来控制一个load/store节点)。搜索infoleak路径:找到从敏感信息(内核指针,也即函数指针、数据指针,keys,network&IPC消息)到泄露点(见Table III)的路径。并使用SyzScope[54]中的符号执行引擎来验证路径可达性。搜索新内存错误:等效于搜索一条路径,从用户可控的数据节点(copy_from_user())到指针变量节点,该指针稍后会被load/store使用。如果存在该数据流路径,且指针变量可指向非预期内存位置,则表示可构造新内存错误。迭代搜索:每次迭代,先用新内存错误来扩展M-DFG,然后搜索infoleak路径和新内存错误,新找到的内存错误添加到下一轮迭代。可利用性验证:为了简化验证,本文假设堆喷成功,利用gdb将敏感信息写入待读的地址。例如,本来需堆喷mbus占据ax25_dev对象,现在使用GDB将mbus->ubus指针写入load指令(也即tmp = mbus->u_bus)。如果能通过测试用例泄露敏感信息,则可利用。4. 实现总体采用静态分析和符号执行实现,组件包含 M-DFG builder 和 Graph Searcher。 采用Syzscope[54]来获得初始的内存错误;M-DFG builder 是基于SUTURE实现;Graph Searcher中,采用BFS来搜索infoleak路径和新的内存错误,采用Angr符号执行来验证路径可达性。5. 实验对syzbot上的250个UAF/OOB漏洞进行测试,能够找到40个infoleak路径,生成21个EXP。