SSRF的概念

其形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能,但又没有对目标地址做严格过滤与限制

导致攻击者可以传入任意的地址来让后端服务器对其发起请求,并返回对该目标地址请求的数据

是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下,SSRF是要目标网站的内部系统。(因为他是从内部系统访问的,所有可以通过它攻击外网无法访问的内部系统,也就是把目标网站当中间人)

数据流:攻击者----->服务器---->目标地址

根据后台使用的函数的不同,对应的影响和利用方法又有不一样

PHP中下面函数的使用不当会导致SSRF:

file_get_contents()

fsockopen()

curl_exec()

如果一定要通过后台服务器远程去对用户指定("或者预埋在前端的请求")的地址进行资源请求,则请做好目标地址的过滤。

1.file_get_contents()

下面的代码使用file_get_contents函数从用户指定的url获取图片。然后把它用一个随即文件名保存在硬盘上,并展示给用户。

<?php
if (isset($_POST['url']))
{
    $content = file_get_contents($_POST['url']);
    $filename ='./images/'.rand().';img1.jpg';
    file_put_contents($filename, $content);
    echo $_POST['url'];
    $img = "<img src=\"".$filename."\"/>";
}
echo $img;
?>

2. fsockopen()

以下代码使用fsockopen函数实现获取用户制定url的数据(文件或者html)。这个函数会使用socket跟服务器建立tcp连接,传输原始数据。

<?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;
    }
}
?>

3. curl_exec()

cURL这是另一个非常常见的实现,它通过 PHP获取数据。文件/数据被下载并存储在“curled”文件夹下的磁盘中,并附加了一个随机数和“.txt”文件扩展名。

<?php
if (isset($_POST['url']))
{
    $link = $_POST['url'];
    $curlobj = curl_init();
    curl_setopt($curlobj, CURLOPT_POST, 0);
    curl_setopt($curlobj,CURLOPT_URL,$link);
    curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1);
    $result=curl_exec($curlobj);
    curl_close($curlobj);

    $filename = './curled/'.rand().'.txt';
    file_put_contents($filename, $result);
    echo $result;
}
?>

注意事项:

一般情况下PHP不会开启fopen的gopher wrapper

file_get_contents的gopher协议不能URL编码

file_get_contents关于Gopher的302跳转会出现bug,导致利用失败

curl/libcurl 7.43 上gopher协议存在bug(%00截断) 经测试7.49 可用

curl_exec() 默认不跟踪跳转,

file_get_contents() file_get_contents支持php://input协议

常见的 SSRF 绕过技巧

服务器可能会做基础校验(如过滤localhost、内网 IP),攻击者常用绕过方法:

IP 地址变形

内网 IP 的十进制 / 八进制 / 十六进制转换:如192.168.1.100转为十进制3232235876、八进制0300.0250.01.0144、十六进制0xC0.0xA8.0x01.0x64

利用域名解析:将内网 IP 绑定到公网域名(如attacker.com解析到192.168.1.100)。

关键字绕过

过滤localhost时,用0(等价于127.0.0.1)、localhost.localdomain127.0.0.0/8内的其他 IP(如127.0.0.2);

过滤192.168时,用192.168.0.0/16的子网变种(如192.168.0.1192.168.0.01)。

协议与特殊符号绕过

利用@符号:http://example.com@192.168.1.100(服务器解析为访问192.168.1.100);

非 HTTP 协议:如gopher://(可构造任意 TCP 请求,攻击 Redis、MySQL)、dict://(端口扫描)、file://(读取服务器本地文件)。

302 跳转绕过构造公网服务器的 302 跳转,指向内网目标:攻击者先搭建http://attacker.com,返回 302 响应跳转到http://192.168.1.100,再让漏洞服务器请求http://attacker.com

SSRF(curl)

进入平台

点击

发现url栏中出现了url地址?url=http://127.0.0.1/pikachu/vul/ssrf/ssrf_info/info1.php

由题目可知则会使一个curl,因为curl支持很多协议,我们就可以做以下尝试:

1.通过网址访问链接

修改url为:url=http://www.baidu.com,访问百度页面

2.利用file协议查看本地文件(前提是那个地方有这个文件)

修改url为:url=file:///D:/download/111.txt,查看文件的内容

3.dict协议扫描内网主机开放端口

使用dict协议可以获取内网主机开放端口相应服务的指纹信息,比如说内网主机开了http端口的话,

可以修改url为:url=dict://自己的主机ip

SSRF(file_get_content)

点击

发现url变成了file,跟上一关类似

1、file读取本地文件(本地必须有该文件)

file=file:///D:/download/111.txt

2、http协议请求内网资源

file=http://127.0.0.1/pikachu/vul/sqli/1.php

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐