原理初步了解:
FastCGI 是一个类似HTTP的通信协议,是数据交换的通道
而FPM就是FastCGI的解析器,服务器中间件将用户的请求按照FastCGI的规则格式化后给FPM,之后呢FPM再对用户的请求解析对应文件
PS:这里是通过TCP协议传输的
那么格式化的规则是什么样的呢?借用文章的一个例子:
用户请求http://127.0.0.1/index.php?a=1&b=2,如果web目录是/var/www/html,那么Nginx会将这个请求变成如下key-value对:
{ 'GATEWAY_INTERFACE': 'FastCGI/1.0', 'REQUEST_METHOD': 'GET', 'SCRIPT_FILENAME': '/var/www/html/index.php', 'SCRIPT_NAME': '/index.php', 'QUERY_STRING': '?a=1&b=2', 'REQUEST_URI': '/index.php?a=1&b=2', 'DOCUMENT_ROOT': '/var/www/html', 'SERVER_SOFTWARE': 'php/fcgiclient', 'REMOTE_ADDR': '127.0.0.1', 'REMOTE_PORT': '12345', 'SERVER_ADDR': '127.0.0.1', 'SERVER_PORT': '80', 'SERVER_NAME': "localhost", 'SERVER_PROTOCOL': 'HTTP/1.1' }
是不是第一眼就感觉很像php的环境变量。这个数组其实就是PHP中$_SERVER数组的一部分。其实环境变量还有一个功能:告诉FPM我要执行什么php文件。在这里就是执行/var/www/html/index.php
攻击原理:
PHP-FPM默认监听9000端口,正常情况只接受127.0.0.1的请求,配置不当也会暴露在公网中,如果没有暴露在公网,只能采取用SSRF去和PHP-FPM通信了。比较新版的FPM设置了默认的一个配置选项security.limit_extensions,只允许后缀为.php的文件,因此要执行服务器上现有的php文件
实现任意代码执行:
先了解一下php的配置项,auto_prepend_file和auto_append_file,这两配置在文件上传中也有,而且是关于.user.ini的配置文件 当然了相对的就是.htaccess文件
要知道nginx的配置文件是.user.ini
apache的配置文件是.htaccess
做文件上传的时候可以通过报错来知道服务器是哪个server
auto_append_file #在执行php文件后自动包含一个指定文件
auto_prepend_file #在执行php文件前自动包含一个指定文件
假如设置了auto_prepend_file 为php://input,(注意要配置远程文件包含选项 allow_url_include ),那么就可以实现文件包含前POST的数据任意执行了。所以要把要执行的代码放在body中。
想要详细了解协议的body以及头部信息,标志什么的可以参考这篇文章 FsatCGI协议分析
将PHP_FPM中的两个环境变量来设置php的配置。配置 PHP_VALUE 为 auto_prepend_file = php://input , PHP_ADMIN_VALUE 为 allow_url_include = On就可以实现任意代码执行了
这边采用gopherus这个工具来实现这一题
1.下载gohperus
2.最好在Linux的环境下执行这个脚本
3.输入命令 python gopherus.py --exploit fastcgi
4.之后输入第一行要求输入路径:/var/www/html/index.php
第二行输入要执行的命令:ls
5.抓一个url包含的包,把_后面的内容全部再url编码一遍再进行传输
6.没有我们要的数据,可以看看根目录 "ls /",也可以使用这条命令 "find / -name flag*"
可以看到flag的名字
7.接下来就是cat flag了
这里有一个注意点就是 cat /flag_73e........... 这个 / 千万不要漏掉