Stack Canaries

从零开始学习AWS黑客技术,成为专家 htARTE(HackTricks AWS Red Team Expert)

支持HackTricks的其他方式:

StackGuard和StackShield

StackGuardEIP(扩展指令指针)之前插入一个特殊值,称为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

此机制在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,可能可以逐字节暴力破解

pageBF Forked & Threaded Stack Canaries
  • 如果二进制文件中存在一些有趣的泄漏或任意读取漏洞,可能可以泄漏它:

pagePrint Stack Canary
  • 覆盖存储在栈中的指针

易受栈溢出攻击的栈可能包含可以被覆盖的字符串或函数地址,以便利用漏洞而无需达到栈canary。查看:

pagePointer 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/

参考资料

从零开始学习AWS黑客技术,成为专家 htARTE (HackTricks AWS Red Team Expert)!

支持HackTricks的其他方式:

最后更新于