如何在运行时检测 KASLR 是否启用或禁用?

如何在运行时检测 KASLR 是否启用或禁用?

如何在运行时检测 KASLR 是否启用或禁用?

答案1

我对之前的答案并不满意,因为他们并没有真正验证 KASLR 的意义,尤其是那些没有实现相同内核命令行界面的嵌入式或自定义内核(例如,ARM64 要求在内核启动时存在一个名为 kaslr-seed 的设备树选择节点。这通常由引导加载程序使用安全随机数生成器来实现)。

在运行时我知道您可以检查两件事:

  1. /proc/kallsyms文件查看虚拟内存地址空间中的符号地址。
  2. lsmod查看虚拟内存地址空间中的内核模块地址。笔记:在某些机器上,lsmod可能无法显示地址。在这种情况下,请尝试cat /proc/modules以 root 身份使用。如果不使用 root,地址可能全为零(出于安全原因已清除)。~~感谢用户 @crass 的评论!~~

1 和 2 是类似的检查,但根据您系统上可用的功能,您可能需要使用其中一个。

1. /proc/kallsyms

为此,只需查看前几行/proc/kallsyms

root@device:~# head -n 3 /proc/kallsyms
ffffff8008080000 t _head
ffffff8008080000 T _text
ffffff8008080800 T do_undefinstr

请注意,例如的地址_headffff ff80 0808 0000

现在重新启动您的机器并再次检查。

root@device:~# head -n 3 /proc/kallsyms
ffffff9fc8c80000 t _head
ffffff9fc8c80000 T _text
ffffff9fc8c80800 T do_undefinstr

注意,例如的地址_head现在是ffff ff9f c8c8 0000
比较高级字节并发现,ffffff80080 != 0xffffff9fc8c因此地址在重启后会发生变化 => KASLR 已启用。

2. lsmod

与上面的方法类似/proc/kallsyms:检查 lsmod,重新启动,再次检查 lsmod,并比较地址。

root@device:~# lsmod
iptable_filter 16384 0 - Live 0xffffffa1c49b9000
ip_tables 28672 1 iptable_filter, Live 0xffffffa1c49ad000

请注意,例如的地址iptable_filterffff ffa1 c49b 9000

现在重新启动您的机器并再次检查。

root@device:~# lsmod
iptable_filter 16384 0 - Live 0xffffff2100716000
ip_tables 28672 1 iptable_filter, Live 0xffffff210070a000

注意,例如的地址iptable_filter现在是ffff ff21 0071 6000
比较高级字节并发现,ffffff2100716 != 0xffffffa1c49b9因此地址在重启后会发生变化 => KASLR 已启用。

您可以反复进行这些测试以确定质量随机性。重启后地址有何不同?是否存在明显的模式?KASLR 的安全优势与随机性或熵的质量成正比。

参考:
使用 KASL 调试 Linux 内核
RANDOMIZE_BASE 的 Linux 内核驱动程序数据库

答案2

回答这个问题:

$ cat /proc/cmdline
BOOT_IMAGE=/boot/vmlinuz-4.14.27-041427-generic root=UUID=f3f8e7bc-b337-4194-88b8-3a513f6be55b ro quiet splash loglevel=0 vga=current udev.log-priority=3 fastboot kaslr acpiphp.disable=1 crashkernel=384M-2G:128M,2G-:256M vt.handoff=7

答案3

检查你的内核命令行。(以 Debian 8 为例)

$ cat /proc/cmdline
BOOT_IMAGE=/vmlinuz-`uname -r` root=/dev/mapper/`hostname`-root ro quiet

kASLR 从 Ubuntu 14.10 开始可用,但默认情况下不启用。在内核命令行上指定“kaslr”选项以使用 kASLR。

笔记:启用 kASLR 将禁用进入休眠模式的能力。

来源:https://wiki.ubuntu.com/Security/Features

答案4

我喜欢 @bhass1 的回答,但是我不想重启电脑才能进行测试。因此,您可以在虚拟机中执行基本相同的测试(如果可以的话)。我使用的是和qemu选项,下面是我操作的方法:-kernel-initrd

首先,我通过查看来检查你正在运行哪个内核cat /proc/cmdline

$ cat /proc/cmdline 
BOOT_IMAGE=/boot/vmlinuz-5.2.0-42-generic root=/dev/sda1 ro vt.handoff=7

所以我用核心 vmlinuz-5.2.0-42-generic

我们需要使用 initrd 运行内核,这样才能拥有一个最小的环境来检查地址。我使用与我的内核相对应的 initrd,以使模拟更加真实,但这实际上并不重要。我还使用正在运行的内核的内核命令行,以使模拟尽可能接近正在运行的内核,并添加break=top到内核命令行以尽快进入 shell。

接下来我运行qemu虚拟机:

sudo qemu-system-x86_64 -m 1024 -kernel /boot/vmlinuz-5.2.0-42-generic \
  -append "$(cat /proc/cmdline) break=top" -initrd /boot/initrd.img-5.2.0-42-generic

当我进入 shell 时,我得到了已加载的模块地址:

(initramfs) cat /proc/modules
usbhid 57344 0 - Live 0xffffffffc0269000
hid 131072 1 usbhid, Live 0xffffffffc0248000

现在我将检查正在运行的系统以查看其中一个模块的模块地址是否不同:

sudo grep hid /proc/modules 
hid_generic 16384 0 - Live 0xffffffffc20ac000
usbhid 57344 0 - Live 0xffffffffc1a09000
hid 131072 2 hid_generic,usbhid, Live 0xffffffffc1c96000

所以我们在这里可以看到隐藏模块不同(运行:0xffffffffc1c96000和虚拟:)0xffffffffc0248000。所以我的内核运行的是 kASLR,虽然它不在内核命令行上(现在在某些发行版上它默认打开)。

您可以在另一个实例中再次检查模块地址qemu,并验证模块地址在每次 qemu 运行时是否发生变化。此外,您可以添加nokaslr到内核命令行(选项-append qemu)并运行qemu几次以验证模块地址不要改变。

相关内容