当 ASLR 遇到信息泄露:随机化的盔甲怎么被拆了
地址空间布局随机化(ASLR)是现代操作系统的标配防御——每次启动,栈、堆、共享库的加载地址都不同,攻击者写死地址的 shellcode 基本就废了。但问题在于,ASLR 的随机性只活到第一次内存泄露为止。
原理很简单:ASLR 通常只在不重启时保持不变(同一次运行内地址固定),而实际攻击链几乎都是先拿到一个信息泄露漏洞,再拼出目标地址去触发第二个漏洞。比如格式化字符串漏洞可以让攻击者直接读取栈上残留的指针值;又比如某些漏洞允许越界读,泄露出 libc 的基址后,
更狠的是,即使重启后地址会变,攻击者也有办法绕过:一是利用部分覆写——低 12 位偏移在 ASLR 中不变,只覆盖后半字节就能跳到目标附近的 gadget;二是利用侧信道,比如逐字节爆破地址,对方如果崩了就说明猜错,没崩就继续,几秒就能把基址探出来。在香港 Pwn 题里这已经是基本功。
所以防御思路不能只靠 ASLR 一层。PIE(位置无关可执行文件)把代码段也随机化了;RELRO 把 GOT 表设成只读;CFI 限制间接跳转的目标范围。
#Security
地址空间布局随机化(ASLR)是现代操作系统的标配防御——每次启动,栈、堆、共享库的加载地址都不同,攻击者写死地址的 shellcode 基本就废了。但问题在于,ASLR 的随机性只活到第一次内存泄露为止。
原理很简单:ASLR 通常只在不重启时保持不变(同一次运行内地址固定),而实际攻击链几乎都是先拿到一个信息泄露漏洞,再拼出目标地址去触发第二个漏洞。比如格式化字符串漏洞可以让攻击者直接读取栈上残留的指针值;又比如某些漏洞允许越界读,泄露出 libc 的基址后,
system() 的地址就能算出来。此时 ASLR 的"随机"就变成了"已知"——它只是把一步 RCE 变成了两步而已。更狠的是,即使重启后地址会变,攻击者也有办法绕过:一是利用部分覆写——低 12 位偏移在 ASLR 中不变,只覆盖后半字节就能跳到目标附近的 gadget;二是利用侧信道,比如逐字节爆破地址,对方如果崩了就说明猜错,没崩就继续,几秒就能把基址探出来。在香港 Pwn 题里这已经是基本功。
所以防御思路不能只靠 ASLR 一层。PIE(位置无关可执行文件)把代码段也随机化了;RELRO 把 GOT 表设成只读;CFI 限制间接跳转的目标范围。
#Security