Stack Canaries
Reading time: 8 minutes
tip
学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。
StackGuard 和 StackShield
StackGuard 在 EIP (扩展指令指针) 之前插入一个特殊值,称为 canary,具体为 0x000aff0d
(表示空值、换行符、EOF、回车)以防止缓冲区溢出。然而,像 recv()
、memcpy()
、read()
和 bcopy()
这样的函数仍然存在漏洞,并且它不保护 EBP (基指针)。
StackShield 采用比 StackGuard 更复杂的方法,通过维护一个 全局返回栈,存储所有返回地址 (EIPs)。这种设置确保任何溢出不会造成伤害,因为它允许比较存储的和实际的返回地址以检测溢出发生。此外,StackShield 可以检查返回地址与边界值,以检测 EIP 是否指向预期数据空间之外。然而,这种保护可以通过 Return-to-libc、ROP(面向返回的编程)或 ret2ret 等技术绕过,这表明 StackShield 也不保护局部变量。
Stack Smash Protector (ProPolice) -fstack-protector
:
该机制在 EBP 之前放置一个 canary,并重新组织局部变量以将缓冲区放置在更高的内存地址,防止它们覆盖其他变量。它还安全地复制传递到局部变量上方的堆栈参数,并使用这些副本作为参数。然而,它不保护少于 8 个元素的数组或用户结构中的缓冲区。
canary 是从 /dev/urandom
派生的随机数或默认值 0xff0a0000
。它存储在 TLS (线程局部存储) 中,允许跨线程共享内存空间具有线程特定的全局或静态变量。这些变量最初从父进程复制,子进程可以在不影响父进程或兄弟进程的情况下更改其数据。然而,如果 fork()
在不创建新 canary 的情况下使用,所有进程(父进程和子进程)共享相同的 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。前三个字节是随机的,最后一个字节是 空字节。
caution
两个 canary 的最低有效字节是空字节,因为它将是来自较低地址的堆栈中的第一个,因此 读取字符串的函数将在读取之前停止。
绕过
泄露 canary 然后用其自身的值覆盖它(例如,缓冲区溢出)。
- 如果 canary 在子进程中被 fork,可能可以 逐字节暴力破解 它:
BF Forked & Threaded Stack Canaries
- 如果二进制文件中存在一些有趣的 泄露或任意读取漏洞,可能可以泄露它:
- 覆盖堆栈存储的指针
易受堆栈溢出影响的堆栈可能 包含可以被覆盖的字符串或函数的地址,以利用该漏洞而无需到达堆栈 canary。检查:
- 修改主 canary 和线程 canary
在受 canary 保护的线程函数中 缓冲区溢出 可以用来 修改线程的主 canary。因此,缓解措施是无效的,因为检查是使用两个相同的(尽管被修改过的)canary。
此外,在受 canary 保护的线程函数中 缓冲区溢出 可以用来 修改存储在 TLS 中的主 canary。这是因为,可能通过线程的 堆栈中的 bof 到达存储 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 条目
如果二进制文件具有部分 RELRO,则可以使用任意写入来修改 __stack_chk_fail
的 GOT 条目,使其成为一个不会在 canary 被修改时阻止程序的虚拟函数。
此攻击在以下写作中进行: https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/
参考
- https://guyinatuxedo.github.io/7.1-mitigation_canary/index.html
- http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads
- https://7rocky.github.io/en/ctf/other/securinets-ctf/scrambler/
tip
学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。