颠覆 Linux 系统上的执行标志。为什么这是可能的?

Edd*_*ett 24 linux security file-permissions shared-libraries

在阅读本文时,我发现了以下漏洞:

% cp /usr/bin/id ~
% chmod -x ~/id
% ls -al ~/id
-rw-r--r-- 1 edd edd 22020 2012-08-01 15:06 /home/edd/id
% ~/id
zsh: permission denied: /home/edd/id
% /lib/ld-linux.so.2 ~/id
uid=1001(edd) gid=1001(edd) groups=1001(edd),1002(wheel)
Run Code Online (Sandbox Code Playgroud)

这个片段表明我们可以作为普通的非特权用户轻松地回避文件系统的执行权限。我在 Ubuntu 12.04 上运行了这个。

虽然 Linux 加载器根据 file(1) 是一个共享对象,但它也有一个允许直接执行的入口点。当以这种方式执行时,Linux 加载器充当 ELF 二进制文件的解释器。

然而,在我的 OpenBSD 机器上,此漏洞利用并不有效,因为您可能不会将加载程序作为程序执行。OpenBSD 手册页说:“ld.so 本身是一个最初由内核加载的共享对象。”。

在 Solaris 9 上试试这个,你会得到一个段错误。我不确定其他地方会发生什么。

因此,我的问题是:

  • 为什么 Linux 加载程序(直接执行时)在解释 ELF 二进制文件之前检查文件系统属性?
  • 为什么要实现一种设计为不允许执行文件的机制,如果它是如此微不足道的回避?我错过了什么吗?

Mec*_*ail 34

execute权限的目的一般不是阻止执行。它是 (1) 告诉程序要执行哪些文件,以及 (2)当 setuid 位(等)被指定时,防止以特权用户身份执行。

链接器黑客攻击不像看起来那么容易。您可以更轻松地执行您有权读取的任何非可执行文件:

$ cp unexecutable_file ~/runme
$ chmod +x ~/runme
$ ~/runme
Run Code Online (Sandbox Code Playgroud)

请参阅Arch Linux 论坛上的此讨论

总之:

标记应该执行的文件

编写 shell 脚本时,可以将其标记为可执行文件chmod +x。这向您的 shell 暗示您希望它是可执行的(否则对于所有 shell 来说,它只是另一个纯文本文件)。然后,当您键入./Tab.

类似地:something.d目录(例如init.d)包含通常由守护程序自动执行的启动或控制 shell 脚本。您可能希望将注释或 README 文件作为纯文本文件放在目录中。或者您可能想要暂时禁用其中一个脚本。您可以通过清除该特定文件的执行位来实现。这告诉守护进程跳过它。

防止特权执行

setuid位表示当您执行文件时,它以指定用户(例如 root)的身份执行。

论坛帖子解释得很好:

您希望某个用户的可执行文件为 setuid,但您只希望来自特定组的人能够将其作为 setuid 执行。他们仍然可以通过复制来执行它,但是 setuid 标志丢失了,所以他们将以自己的身份执行它,而不是拥有原始文件的用户。

  • 谢谢——我忽略了这样一个事实,即用户可以复制他可以读取的任何文件,因此可以选择任意权限。 (2认同)

Red*_*ick 10

如果您对文件具有读访问权限,则可以随时复制该文件。

如果您可以制作个人副本,则始终可以将该副本标记为可执行。

这并不能解释 ld-linux 的行为,但确实表明它可能不是一个非常有用的安全漏洞。

如果您想要更严格的安全性,请考虑SELinux