起因
这篇文章是在遇到ezphp这道题目的情况下,作为老年人来学习一下现在的新技术。
题目如下:
1 | empty($_GET["env"])) ? highlight_file(__FILE__) : putenv($_GET["env"]) && system('echo hfctf2022'); ( |
乍一看可以设置环境变量,联想到后面的echo,想到能不能通过环境变量替换掉echo这个命令,但是思路戛然而止,没有这方面的知识储备,于是看wp进行学习。
本文包含两部分内容
- p神文章介绍的环境变量造成命令执行
- nginx的缓存文件机制与LD_PRELOAD结合的LFI新姿势
环境变量命令执行
第一部分对p神的文章进行总结,以及思路整理。
文章地址:https://www.leavesongs.com/PENETRATION/how-I-hack-bash-through-environment-injection.html#_1
新知识
对于sh,CentOS中指向bash,而debian系指向dash
CentOS中CentOS7对应版本为bash4.2,CentOS对应版本为bash4.4
glibc包含常见的系统API如
open
、read
、write
、malloc
、printf
、getaddrinfo
、dlopen
、pthread_create
、crypt
、login
、exit
The GNU C Library project provides the core libraries for the GNU system and GNU/Linux systems, as well as many other systems that use Linux as the kernel. These libraries provide critical APIs including ISO C11, POSIX.1-2008, BSD, OS-specific APIs and more. These APIs include such foundational facilities as
open
,read
,write
,malloc
,printf
,getaddrinfo
,dlopen
,pthread_create
,crypt
,login
,exit
and more.PROMPT_COMMAND后门
对于Ubuntu,有如下方法进行环境变量的命令执行
1 | 1.ENV='$(id 1>&2)' dash -i -c 'echo hello', |
对于bash,有如下方法:
1 | Bash没有修复ShellShock漏洞:直接使用ShellShock的POC进行测试,例如TEST=() { :; }; id; |
- bash换成sh也可以
Nginx机制与LD_PRELOAD
在hxp CTF 2021 - A New Novel LFI中介绍了Nginx的机制。
- 当 Nginx 接收来自 FastCGI 的响应时,若大小超过限定值32KB左右不适合以内存的形式来存储的时候,一部分就会以临时文件的方式保存到磁盘上,路径为
/var/lib/nginx/fastcgi
。 - 如果打开一个进程打开了某个文件,某个文件就会出现在
/proc/PID/fd/
目录下,但是如果这个文件在没有被关闭的情况下就被删除了,就会停留在这个目录。 - Nginx 会有很多 Worker 进程,但是一般来说 Worker 数量不会超过 cpu 核心数量,我们可以通过
/proc/cpuinfo
中的 processor 个数得到 cpu 数量,一般来说是8个worker实际本地测试 fd 序号一般不超过 70 ,即使爆破也只是 8*70。
当面对陌生的程序或者cms时,最好的办法就是搭建一个一样的,然后看看什么情况。作者就是搭建了一个nginx来找特征。
解决题目
面对ezphp这道题,总结起来整个过程就是:
- 让后端 php 请求一个过大的文件,这里的文件就是我们的LD_PRELOAD利用的so文件
- Fastcgi 返回响应包过大,导致 Nginx 需要产生临时文件进行缓存
- 虽然 Nginx 删除了
/var/lib/nginx/fastcgi
下的临时文件,但是在/proc/pid/fd/
下我们可以找到被删除的文件 - 遍历 pid 以及 fd ,使用多重链接绕过 PHP 包含策略完成 LFI
唯独你没懂的wp脚本用的下面这个
1 | import threading, requests |
搭配exp.c编译成so
1 |
|
编译
1 | gcc -shared -fPIC exp.c -o exp.so |
data1 = f.read()+b'0'*1024*1000
添加了脏字符__attribute__ ((__constructor__))
使得当前so文件作为共享库被调用时,在main函数之前执行,一旦某些指令需要加载动态链接库时,就会立即执行它。- 使用threading多线程,提高效率