0x00写在前面
看了p神的博客和其他大佬的博客后,发现自己对通讯这边还是不太懂.
希望摘抄下他们的博客,能够加深理解吧orz
0x01简介
搭过php相关环境的同学应该对fastcgi不陌生,那么fastcgi究竟是什么东西,为什么nginx可以通过fastcgi来对接php?
Fastcgi其实是一个通信协议,和HTTP协议一样,都是进行数据交换的一个通道。
HTTP协议是浏览器和服务器中间件进行数据交换的协议,浏览器将HTTP头和HTTP体用某个规则组装成数据包,以TCP的方式发送到服务器中间件,服务器中间件按照规则将数据包解码,并按要求拿到用户需要的数据,再以HTTP协议的规则打包返回给服务器。
类比HTTP协议来说,fastcgi协议则是服务器中间件和某个语言后端进行数据交换的协议。Fastcgi协议由多个record组成,record也有header和body一说,服务器中间件将这二者按照fastcgi的规则封装好发送给语言后端,语言后端解码以后拿到具体数据,进行指定操作,并将结果再按照该协议封装好后返回给服务器中间件。
和HTTP头不同,record的头固定8个字节,body是由头中的contentLength指定,其结构如下:
1 | typedef struct { |
头由8个uchar类型的变量组成,每个变量1字节。其中,requestId占两个字节,一个唯一的标志id,以避免多个请求之间的影响;contentLength占两个字节,表示body的大小。
语言端解析了fastcgi头以后,拿到contentLength,然后再在TCP流里读取大小等于contentLength的数据,这就是body体。
Body后面还有一段额外的数据(Padding),其长度由头中的paddingLength指定,起保留作用。不需要该Padding的时候,将其长度设置为0即可。
可见,一个fastcgi record结构最大支持的body大小是2^16,也就是65536字节。
0x02PHP的连接方式
apache2-module
把php当作apache的一个模块,实际上php就相当于apache的一个dll或者so文件.
CGI模式
此时php是一个独立的进程比如php-cgi.exe,web服务器也是一个独立的进程比如apache.exe,当web服务器监听到http请求时,会去调用php-cgi进程,他们之间通过cgi协议通信.CGI的缺点也很明显,每次客户端请i去都需要建立和销毁进程.
FastCGI模式
fastcgi本身时一个协议,在cgi协议上进行优化.fastcgi模式是fastcgi进程自己管理自己的cgi进程,而不再是apache去主动调用php-cgi,而fastcgi进程又提供了很多辅助功能比如内存管理,垃圾处理,保障了cgi的高效性,并且CGI此时是常驻在内存中,不会每次请求重新启动
PHP-fpm
fastcgi本身是一个协议,那么就需要有一个程序去实现这个协议,php-fpm就是实现和管理fastcgi协议的进程,fastcgi模式的内存管理等功能,都是由php-fpm进程所实现的
0x03判断连接方式
如果接触不到服务器文件,我们可以通过phpinfo页面的Server API来判断
php-fpm的模式
php-fpm与nginx之间的通信有两种模式,其一为TCP模式,其二是unix套接字模式
TCP模式
TCP模式即是php-fpm进程会监听本机上的一个端口(默认9000),然后nginx会把客户端数据通过fastcgi协议传给9000端口,php-fpm拿到数据后会调用cgi进程解析
Unix Socket
socket,它是unix系统进程间通信(IPC)的一种被广泛采用方式,以文件(一般是.sock)作为socket的唯一标识(描述符),需要通信的两个进程引用同一个socket描述符文件就可以建立通道进行通信了。此通信方式的性能会优于TCP
0x04漏洞产生
php-fpm默认监听端口9000,如果其暴露在公网,那我们就可以构造fastcgi协议,和fpm进行通信.
任意代码执行
理论上是不可以执行任意代码的.
但php.ini中有两个配置项auto_prepend_file
和auto_append_file
.auto_prepend_file
是告诉PHP,在执行目标文件之前,先包含auto_prepend_file
中指定的文件;auto_append_file
是告诉PHP,在执行完成目标文件后,包含auto_append_file
指向的文件。
假设我们设置auto_prepend_file
为php://input
,那么就等于在执行任何php文件时都会包含POST内容.(前提是allow_url_include
开启)
至于怎么设置auto_prepend_file
.php-fpm有两个环境变量,PHP_VALUE
和PHP_ADMIN_VALUE
.这两个变量是用来设置php配置项的吗,PHP_VALUE
可以设置模式为PHP_INI_USER
和PHP_INI_ALL
的选项,PHP_ADMIN_VALUE
可以设置所有选项。
所以,只要传入如此的环境变量即可执行任意代码了.
1 | { |
0x05exp
P神的payload,兼容python2,python3
https://gist.github.com/phith0n/9615e2420f31048f7e30f3937356cf75
参考博客
Fastcgi协议分析 && PHP-FPM未授权访问漏洞 && Exp编写
PHP 连接方式&攻击PHP-FPM&*CTF echohub WP