linux - ELF 中 set-uid 和 INTERP(动态链接器)的相对路径的安全问题

标签 linux security glibc dynamic-linking setuid

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/

相关文章:

c - glibc 是否有针对 C 的自动调整大小数组/动态数组实现?

mysql - 无法通过套接字 '/var/run/mysqld/mysqld.sock' 连接到本地 MySQL 服务器。

security - 兄弟:只记录一个流

c++ - 带有 LD_PRELOAD 和 boost::interprocess 的 mmap() 不起作用

r - 我可以禁用 R 中的 System() 命令吗?

php - 我应该何时以及如何使用此功能?

attributes - 配置:错误:缺少 __attribute__ ((constructor)) 支持?

linux - 在子目录中的文件上执行程序

c++ - Qt 段错误strtod

linux - x86 英特尔汇编 Linux sys_write + sys_read