Stack Canaries
StackGuard和StackShield
StackGuard在EIP(扩展指令指针)之前插入一个特殊值,称为canary,具体为0x000aff0d
(表示空值、换行符、EOF、回车),以防止缓冲区溢出。然而,像recv()
、memcpy()
、read()
和bcopy()
这样的函数仍然容易受到攻击,它不保护EBP(基指针)。
StackShield采用比StackGuard更复杂的方法,维护一个全局返回堆栈,存储所有返回地址(EIPs)。这种设置确保任何溢出都不会造成伤害,因为它允许对存储的和实际的返回地址进行比较,以检测溢出事件。此外,StackShield可以将返回地址与边界值进行比较,以检测EIP是否指向预期数据空间之外。然而,这种保护可以通过Return-to-libc、ROP(Return-Oriented Programming)或ret2ret等技术绕过,这表明StackShield也不保护本地变量。
栈破坏保护器(ProPolice)-fstack-protector
:
-fstack-protector
:此机制在EBP之前放置一个canary,并重新组织本地变量,将缓冲区定位在更高的内存地址,防止它们覆盖其他变量。它还安全地复制传递在本地变量上方堆栈上传递的参数,并使用这些副本作为参数。然而,它不保护少于8个元素的数组或用户结构中的缓冲区。
canary是从/dev/urandom
派生的随机数,或者默认值为0xff0a0000
。它存储在TLS(线程本地存储)中,允许跨线程共享内存空间具有线程特定的全局或静态变量。这些变量最初从父进程复制,子进程可以修改它们的数据而不影响父进程或同级进程。然而,如果在不创建新canary的情况下使用fork()
,所有进程(父进程和子进程)共享相同的canary,使其容易受到攻击。在i386架构上,canary存储在gs:0x14
,在x86_64上存储在fs:0x28
。
此本地保护识别容易受攻击的缓冲区的函数,并在这些函数的开头注入代码以放置canary,并在结尾验证其完整性。
当Web服务器使用fork()
时,可以通过逐字节猜测canary来进行暴力攻击。然而,在fork()
后使用execve()
会覆盖内存空间,从而抵消攻击。vfork()
允许子进程执行而不复制,直到尝试写入时创建副本,提供了一种不同的进程创建和内存处理方法。
长度
在x64
二进制文件中,canary cookie是一个**0x8
字节qword。前七个字节是随机的,最后一个字节是空字节**。
在x86
二进制文件中,canary cookie是一个**0x4
字节dword。前三个字节是随机的,最后一个字节是空字节**。
两个canary的最低有效字节是空字节,因为它将是来自较低地址的栈中的第一个字节,因此读取字符串的函数将在读取它之前停止。
绕过
泄露canary,然后用其自身的值覆盖它(例如缓冲区溢出)。
如果canary在子进程中被fork,可能可以逐字节暴力破解:
如果二进制文件中存在一些有趣的泄漏或任意读取漏洞,可能可以泄漏它:
覆盖存储在栈中的指针
易受栈溢出攻击的栈可能包含可以被覆盖的字符串或函数地址,以便利用漏洞而无需达到栈canary。查看:
Pointer Redirecting修改主canary和线程canary
受canary保护的线程函数中的缓冲区溢出可用于修改线程的主canary。结果,该缓解措施无效,因为检查使用两个相同的canary(尽管已修改)。
此外,受canary保护的线程函数中的缓冲区溢出可用于修改存储在TLS中的主canary。这是因为可能可以通过线程的栈中的缓冲区溢出到达存储TLS的内存位置(因此,canary)。 结果,该缓解措施无效,因为检查使用两个相同的canary(尽管已修改)。 此攻击在以下文档中执行:http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads
还请查看https://www.slideshare.net/codeblue_jp/master-canary-forging-by-yuki-koike-code-blue-2015的演示文稿,其中提到通常TLS由**mmap
存储,当创建线程的栈**时也是由mmap
生成的,根据这一点,可能允许如前述文档中所示的溢出。
修改
__stack_chk_fail
的GOT表项
如果二进制文件具有Partial RELRO,则可以使用任意写入来修改**__stack_chk_fail
的GOT表项**,使其成为一个虚拟函数,如果canary被修改,则不会阻止程序。
此攻击在以下文档中执行:https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/
参考资料
最后更新于