缓解措施

应用层安全防护

1、Aslr(地址空间布局随机化)随机防止数据区域的地址空间来防止攻击者跳转到内存的特定位置。在windows上ASLR主要包括堆栈随机化、PEB与TEB随机化、映像随机化。Linux Alsr主要包括栈地址随机化,LIBS/MMAP随机化,EXEC随机化,BRK随机化、VDSO随机化。在没有ASLR的情况下让程序跳转到一个已存在的系统函数的漏洞利用方式被称为ret2libc

LIBS/MMAP随机化:程序每次执行动态库都被加载到不同的内存位置

EXEC随机化:程序每次执行都将加载到不同的内存位置

Brk随机化:brk用来分配堆空间,当brk aslr关闭时,start_brk和brk都是指向bss段的尾部的;当brk ALSR开启的时候,初始位置变为bss段尾部加上一个不确定的偏移地址

VDSO随机化: VDSO(虚拟动态共享库)将内核的调用映射到用户态的地址空间,使得调用开销更小,路径更好 相当于共享库地址随机化

Linux中的ASLR的等级:在linux系统中ASLR被分为0,1,2三个等级,可以通过sudo bash -c "echo 2 > /proc/sys/kernel/randomize_va_space"设置。

0:没有随机化。即关闭ASLR。

1:保留的随机化。共享库、栈、mmap()分配的内存空间以及VDSO将被随机化。

2:完全的随机化。在1的基础上,通过 brk()分配的内存空间也将被随机化

2、NX(内存不可执行)类似于windows中DEP

 

编译器安全防护

1、Built as PIE:    就是前面说的EXEC的随机化,实际上更准确的说法是PIE(Position Independent Executables,位置无关可执行文件)

2、Built as RELRO:RELRO(RELocation Read-Only,只读重定位)让加载器将重定位表中加载时解析的符号标记为只读,这减少了GOT覆写攻击的面积。RELRO可以分为Partial RELRO(部分RELRO)和Full RELRO(完整RELRO)。开启Partial RELRO的话GOT表是可写的;开启FULL RELRO的话GOT表是只读的

3、Stack Canary(Protector):类似于GS,在栈中加入一段验证,在函数返回时对这段cookie值进行验证,

 

内核安全防护:

  1. KPTI:(Kernel PageTable Isolation,内核页表隔离),进程地址空间被分成了内核地址空间和用户地址空间,内核地址空间映射到了整个物理地址空间,而用户地址空间只能映射到指定的物理地址空间,内核地址空间和用户地址空间共用一个页全局目录表。为了彻底防止用户程序获取内核数据,可以领内核地址空间和用户地址空间使用两组页表集
  2. KASLR:K指kernel,也就是内核地址,也就是内核地址空间布局随机化
  3. SMAP/SMEP:SMAP(Supervisor Mode Access Prevention,管理模式访问保护)和SMEP(Supervisor Mode Execution Prevention,管理模式执行保护)的作用分别是禁止内核访问用户空间的数据和禁止内核执行用户空间的代码。arm里面叫PXN(Privilege Execute Never)和PAN(Privileged Access Never)。SMEP类似于前面说的NX,不过一个是在内核态中,一个是在用户态中。和NX一样SMAP/SMEP需要处理器支持,可以通过cat /proc/cpuinfo查看,在内核命令行中添加nosmap和nosmep禁用。windows系统从win8开始启用SMEP,windows内核枚举哪些处理器的特性可用,当它看到处理器支持SMEP时通过在CR4寄存器中设置适当的位来表示应该强制执行SMEP,可以通过ROP或者jmp到一个RWX的内核地址绕过。linux内核从3.0开始支持SMEP,3.7开始支持SMAP。

在没有SMAP/SMEP的情况下把内核指针重定向到用户空间的漏洞利用方式被称为ret2usr。physmap是内核管理的一块非常大的连续的虚拟内存空间,为了提高效率,该空间地址和RAM地址直接映射。RAM相对physmap要小得多,导致了任何一个RAM地址都可以在physmap中找到其对应的虚拟内存地址。另一方面,我们知道用户空间的虚拟内存也会映射到RAM。这就存在两个虚拟内存地址(一个在physmap地址,一个在用户空间地址)映射到同一个RAM地址的情况。也就是说,我们在用户空间里创建的数据,代码很有可能映射到physmap空间。基于这个理论在用户空间用mmap()把提权代码映射到内存,然后再在physmap里找到其对应的副本,修改EIP跳到副本执行就可以了。因为physmap本身就是在内核空间里,所以SMAP/SMEP都不会发挥作用。这种漏洞利用方式叫ret2dir

  1. Stack canary(protector):内核地址随机化,内核随机化选项
  2. Address protection:由于内核空间:由于内核空间和用户空间共享虚拟内存地址,因此需要防止用户空间mmap的内存从0开始,从而缓解NULL解引用攻击。windows系统从win8开始禁止在零页分配内存。

 

系统调用API函数,栈空间的分配情况,开辟栈空间,然后为eax分配一个系统调用的API的序号,然后执行int 0x2e指令自陷进入内核态

Int中断指令,进入内核执行真正的代码

SafeSEH 需要 OS 和 Compiler 的双重支持,该选项会将所有异常处理函数地址提取出来,编入 SEH 表中,并将这张表放到程序的映像里。异常调用时,就与这张预先存好的表中的地址进行校验。

 

绕过 SafeSEH

方法一:覆盖函数返回地址。若攻击对象启用了 SafeSEH 但是 没有启用 GS 或者存在未受 GS 保护的函数,则可用这个方法。

方法二:攻击虚函数表来绕过 SafeSEH。

方法三:将 shellcode 部署在堆中以绕过 SafeSEH。

方法三:利用未启用 SafeSEH 的模块绕过 SafeSEH。(针对上述的 RtlIsValidHandler() 函数的第二种放行可能)

方法四:DEP 关闭时,可以利用加载模块之外的指令作为跳板

 

SEHOP的全称是Structured Exception Handler Overwrite Protection(结构化异常处理覆盖保护),SEH攻击是指通过栈溢出或者其他漏洞,使用精心构造的数据覆盖结构化异常处理链表上面的某个节点或者多个节点,从而控制EIP(控制程序执行流程)。而SEHOP则是是微软针对这种攻击提出的一种安全防护方案。

现在看看SEHOP的新颖之处:程序中的各S.E.H函数是以单链表的形式存放在栈中的,而这个链表的末端是程序的默认异常处理,它负责处理前面S.E.H函数都不能处理的异常

SEHOP的核心任务就是检查这条S.E.H链的完整性,在程序转入异常处理前SEHOP会检查S.E.H链上最后一个异常处理函数是否为系统固定的终极异常处理函数。如果是,则说明S.E.H链没有被破坏,程序可以去执行当前的异常处理函数;如果检测到最后一个异常处理函数不是终极BOSS,则说明S.E.H链被破坏,可能发生了S.E.H覆盖攻击,程序将不会去执行当前的异常处理函数。

 

绕过SEHOP

  1. 覆盖函数返回地址。若攻击对象启用了 SafeSEH 但是 没有启用 GS 或者存在未受 GS 保护的函数,则可用这个方法。
  2. 攻击虚函数表来绕过 SafeSEH。
  3. 利用未启用 SafeSEH 的模块绕过 SafeSEH。(针对上述的 RtlIsValidHandler() 函数的第二种放行可能)
  4. 伪造SHE链表
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章