ASLR

地址空间随机化(Address Space Layout Randomization) 是一种防范缓冲区溢出攻击 的内存机制。其有效性依赖于整个地址空间布局是否对于攻击者保持未知。 只有编译时作为位置无关可执行文件(PIE:Position Independent Executable) 的可执行程序才能得到 ASLR 技术的保护,

ASLR 并不能:

  • 修复漏洞,而是增加漏洞利用的难度
  • 对编译时没有开启 ASLR 支持的二进制文件提供保护

绕过 ASLR 的攻击大致如下:

  • 地址泄露
  • 访问与特定地址关联的数据
  • 猜测地址,例如系统熵过低或 ASLR 实现问题
  • 利用侧信道攻击

通过内核参数 kernel.randomize_va_space 来配置 ASLR 功能::

# cat /proc/sys/kernel/randomize_va_space
2
# sysctl -a --pattern randomize
kernel.randomize_va_space = 2

官方文档如下::

This option can be used to select the type of process address
space randomization that is used in the system, for architectures
that support this feature.

0 - Turn the process address space randomization off.  This is the
    default for architectures that do not support this feature anyways,
    and kernels that are booted with the "norandmaps" parameter.

1 - Make the addresses of mmap base, stack and VDSO page randomized.
    This, among other things, implies that shared libraries will be
    loaded to random addresses.  Also for PIE-linked binaries, the
    location of code start is randomized.  This is the default if the
    CONFIG_COMPAT_BRK option is enabled.

2 - Additionally enable heap randomization.  This is the default if
    CONFIG_COMPAT_BRK is disabled.

    There are a few legacy applications out there (such as some ancient
    versions of libc.so.5 from 1996) that assume that brk area starts
    just after the end of the code+bss.  These applications break when
    start of the brk area is randomized.  There are however no known
    non-legacy applications that would be broken this way, so for most
    systems it is safe to choose full randomization.

    Systems with ancient and/or broken binaries should be configured
    with CONFIG_COMPAT_BRK enabled, which excludes the heap from process
    address space randomization.

关闭 ASLR 并执行 ldd,会看到两次的输出完全一致::

# sysctl -w kernel.randomize_va_space=0
kernel.randomize_va_space = 0
# diff <(ldd /bin/bash) <(ldd /bin/bash)

重新设置为 2 启用 ASLR 后会看到两次执行输出的内存地址不同::

# sysctl -w kernel.randomize_va_space=2
kernel.randomize_va_space = 2
# diff <(ldd /bin/bash) <(ldd /bin/bash)
1,6c1,6
<       linux-vdso.so.1 (0x00007ffd09963000)
<       libreadline.so.7 => /lib64/libreadline.so.7 (0x00007f205edf2000)
<       libdl.so.2 => /lib64/libdl.so.2 (0x00007f205ebee000)
<       libc.so.6 => /lib64/libc.so.6 (0x00007f205e820000)
<       libncurses.so.6 => /lib64/libncurses.so.6 (0x00007f205e5c6000)
<       /lib64/ld-linux-x86-64.so.2 (0x0000561fc213b000)
---
>       linux-vdso.so.1 (0x00007ffc4f781000)
>       libreadline.so.7 => /lib64/libreadline.so.7 (0x00007f89cdef7000)
>       libdl.so.2 => /lib64/libdl.so.2 (0x00007f89cdcf3000)
>       libc.so.6 => /lib64/libc.so.6 (0x00007f89cd925000)
>       libncurses.so.6 => /lib64/libncurses.so.6 (0x00007f89cd6cb000)
>       /lib64/ld-linux-x86-64.so.2 (0x0000561fca491000)