到目前为止,已经了解了库的基本概念、加载的工作原理以及劫持恶意二进制文件中的搜索顺序如何导致完全的系统接管。
译者注:
在
windows
下也有这种情况,叫dll hell
。有兴趣的粉丝可以看一下我 <
coredump问题原理探究
>的windows
版本
当启动这个实验室并寻找 suid
二进制文件时(第一步),发现了一个不寻常的二进制文件 /usr/bin/welcome
由用户和组 root
拥有。
无法运行welcome
,因为它抛出了一个错误,即找不到 libwelcome.so
库。在使用 ldd
和 readelf
的-d
选项检查时,确认二进制文件需要 libwelcome.so
。幸运的是,它并不在系统里。
为了检查库搜索顺序,从 /etc/ld.so.conf
开始,然后浏览了 /etc/ld.so.conf.d/
目录中的文件。在那里找到了一个让人觉得奇怪的文件 custom.conf
。
发现库搜索也尝试在 /home/student/lib
中搜索。要确认这一点,可以运行 LD_DEBUG=libs /usr/bin/welcome
。
该目录直接由当前登录的用户控制,在加载库时,它专注于加载部分而不是检查文件所有权。所以写了一个恶意代码来在设置root
用户的uid
和gid
后得到一个交互式bash shell
#include <stdlib.h>
#include <unistd.h>void _init() {
setuid(0);
setgid(0);
system("/bin/bash -i");
}
注意:在这种情况下使用了
_init
来证明, 是预防在有旧版本的GCC
,它也可以工作。但建议使用__attribute__((constructor))
从上面来看,看来是缺少一个welcome
函数,改一下。编译代码并将其保存在 /home/student/lib
中,以便 ld.so.conf.d/custom.conf
应该能够找到它。
再次运行 /usr/bin/welcome
,将获得具有 root
用户权限的 shell
当这个实验室开始时,检查了 suid
二进制文件并发现 /usr/local/bin/token
看起来不像通常的二进制文件。
由于 $PATH
环境变量包含 /usr/local/bin
目录的条目,可以直接执行这个文件。
就像上面的实验室中讨论的那样,在这种情况下,系统中也缺少库。如果是这种情况,可能有一些方法可以将恶意共享库加载或注入到进程中。
这次在 /etc/ld.so.conf
文件和 /etc/ld.so.conf.d
目录中找不到任何漏洞。在检查动态部分时,发现该文件包含设置为 /tmp/lib/
目录的 RPATH
值。
好吧,这很有意思,还记得 RPATH
的优先级高于 ld configs
。因此,如果创建共享库 /tmp/lib/librandom.so
,进程将尝试加载该库。
重用上面实验室中的相同代码。运行下面命令在 RPATH
中创建恶意共享库。
$ mkdir -p /tmp/lib
$ gcc -shared -fPIC -o /tmp/lib/librandom.so exploit.c
运行代码时,发现该符号未实现, 尝试定义一个变量。
向 random_token
变量添加一个简单值。
int random_token = 123456;
检查下符号是否正确实施。
成功执行,现在将 constructor
属性添加到 token
函数
再次运行可执行文件,这次将获得具有root
用户权限的shell
在这个案例下,在寻找 suid
二进制文件时,发现安装了 sudo
但没有找到可疑的 suid
二进制文件。
在检查当前的 sudo
权限时,一切看起来都正常,但 env_keep+=LD_PRELOAD
引起了注意。通常,父进程会向子进程传递环境变量,但在 sudo
的情况下,只向子进程传递在env_keep
配置的环境变量。
所以,写了一个调用system
函数的程序。由于sudo
原因,程序将以 root
用户身份运行。也就可以忽略多余的 setuid()
和 setgid()
调用。
如果想知道为什么必须在调用 system()
之前取消设置 LD_PRELOAD
环境变量,请上一篇文章。
使用 GCC
编译代码,这里不需要 lib
前缀,并在指定 LD_PRELOAD
环境变量后调用 apache
。
$ gcc -shared -fPIC -o inject.so exploit.c
$ sudo LD_PRELOAD=/home/student/inject.so /usr/sbin/apache2
请点一下右下角的“在看”,谢谢!!
暗号:336792