Linux保护机制
NX
数据不可执行。原理是将数据所在内存页标识为不可执行,防止因为程序运行出现溢出而使得攻击者的shellcode可能会在数据区尝试执行的情况。NX在咱屡战屡败的经典栈溢出实验中有接触过,NX是对栈和堆的一种保护机制。实验需要关闭NX和地址随机化,否则执行shellcode时,CPU就会抛出异常,而不是去执行恶意指令。
Linux系统叫做NX,Windows系统中类似的机制叫DEP(Data Execute Prevention)。
Stack Canary
栈保护。栈溢出保护是一种缓冲区溢出攻击缓解手段。启用栈保护后,函数开始执行的时候会先往栈里插入cookie信息,当函数真正返回的时候会验证cookie信息是否合法,如果不合法就停止程序运行。攻击者在覆盖返回地址的时候往往也会将cookie信息给覆盖掉,导致栈保护检查失败而阻止shellcode的执行。在Linux中我们将cookie信息称为canary。
简单来说就是通过验证cookie,来判断执行的代码是不是恶意代码。
PIE / ASLR
地址随机化。就是保证同一个程序任意两次运行时的堆栈基址是不同的。如果堆栈基址不变会怎样?不变就可能被攻击,因为攻击者能确认程序的内存地址,然后通过覆盖返回地址在等手段执行恶意代码。咱屡战屡败的经典栈溢出实验就是通过覆盖返回地址执行恶意代码。
随机化段 | 设置 | |
---|---|---|
ADLR | 堆、栈、mmap(libc库)、VDSO page | 由操作系统设置 |
PIE | 数据段、代码段 | 由编译器设置 |
Relro
只读重定位。设置符号重定向表格为只读或在程序启动时就解析并绑定所有动态符号,从而减少对GOT攻击。在Linux中有”Partial RELRO” “Full RELRO”两种模式,默认开启Partical RELRO,开启Partical RELRO时,GOT是可写的,开启 FULL RELRO 时,GOT表是只读的。
主要用来保护重定位表段对应数据区域,默认可写
- Partial RELRO: got表不可写,got.plt可写
- Full RELRO: got表,got.plt不可写
部分RELRO 易受到攻击,例如攻击者可以atoi.got为system.plt,进而输入/bin/sh\x00获得shell
完全RELRO 使整个 GOT 只读,从而无法被覆盖,但这样会大大增加程序的启动时间,因为程序在启动之前需要解析所有的符号。
参考:
FORTIFY
在编译的时候检查源码是否存在缓冲区溢出等错误。
简单地说,加了这个保护之后,一些敏感函数如read, fgets,memcpy, printf等等可能导致漏洞出现的函数都会被替换成__read_chk,__fgets_chk, __memcpy_chk, __printf_chk等。
这些带了chk的函数会检查读取/复制的字节长度是否超过缓冲区长度,通过检查诸如%n之类的字符串位置是否位于可能被用户修改的可写地址,避免了格式化字符串跳过某些参数(如直接%7$x)等方式来避免漏洞出现。
BRATH
程序运行时的环境变量,运行时所需要的共享库文件优先从该目录寻找,可以fake lib造成攻击。