ELF 二进制文件的 INTERP 部分中的 set-uid 和相对路径的组合非常危险。
我不太确定应该如何以及在何处报告这个问题,但在我看来,这像是一个关于 linux/glibc 中动态链接如何工作的一般安全问题,所以让我解释一下它是什么:
考虑构建一个动态链接的二进制文件并在 ELF INTERP 部分指定一个相对路径(使用 --dynamic-linker gcc 选项),以便您可以使用动态链接的商业应用程序重新分发自定义 glibc 版本(不允许您这样做)静态链接到 LGPL glibc,但仍然需要使您的二进制文件在具有不同 glibc 版本的不同 linux 发行版上工作。
如果您将二进制文件chown 为root,并将set-uid 标志放在您的二进制文件上,它实际上变成了rootkit。从不同的目录执行它,允许您替换动态链接器可执行文件,它将以 root 权限执行。
为了演示这一点,请查看以下 C 代码 (issue.c):
#include <stdio.h>
//
// build with:
// gcc -DNAME=\"vulnarable\" -o issue -Wl,--dynamic-linker,.lib64/ld-linux-x86-64.so.2 issue.c
// sudo chown root issue
// sudo chmod u+s issue
// now build some code to be executed with root permissions (we use the same issue.c):
// mkdir -p .lib64/
// gcc -DNAME=\"rootkit\" -o .lib64/ld-linux-x86-64.so.2 --static issue.c
//
int main(int argc, char* argv[])
{
printf("(%s) euid:%d\n", NAME, geteuid());
}
如果您现在像这样执行 set-uid 二进制文件
./issue
甚至只是这样做
ldd issue
而不是得到你可能期望的,例如:
(vulnarable) euid:0
你得到:
(rootkit) euid:0
现在的重点是您可以用任何您喜欢的方式替换 ld-linux-x86-64.so.6 二进制文件。
类似的问题似乎已经解决,方法是不解析 RPATH 中的 $ORIGIN 或如果设置了 set-uid 标志则忽略 LD_LIBRARY_PATH。
所以我想知道是否必须忽略 ELF 中的 INTERP,无论何时设置 set-uid 标志(即通过使用默认动态链接器 -/lib32/ld-linux.so.2 或/lib64/ld-linux -x86-64.so.2)?
那么您认为应该在哪里修复或报告此问题 - 在 glibc 还是内核中?
最佳答案
是的,在不安全的位置使用 setuid 二进制文件指定解释器是不安全的(您提到的是相对路径,但世界可写的固定路径也有同样的问题)。但这是 ELF 设计的合乎逻辑的结论,并且为 setuid 二进制文件添加一个特例来处理 INTERP 并不是可行的方法。这是一个“医生,我这样做的时候很疼。 — 不要这样做。”是的,这种组合是不安全的,所以不要使用它!无论如何,干预 ELF 解释器是相当高级的事情,所以除非您了解自己在做什么,否则您不应该这样做,在这种情况下,您可以从逻辑上得出什么是安全的或不应该做的结论。
ELF/POSIX/Unix/任何东西的高级特性给了你搬起石头砸自己脚的强大方法,因为它们很强大。如果您想摆脱每一种可能的糟糕情况,您的系统将变得更加灵活且难以编程,同时仍然存在一些漏洞。
关于linux - ELF 中 set-uid 和 INTERP(动态链接器)的相对路径的安全问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9019083/