SSRF学习

关于SSRF

服务端请求伪造漏洞,用户通过WEB访问/上传/发出请求,绕过服务器防火墙,获取服务器及其内网信息。SSRF可以说是一个媒介,结合服务器中的服务,常常可以形成一条完整的攻击链。

 

相关函数:

file_get_contents(),fsockopen(),curl_exec()三个函数使用不当时将会造成ssrf
file_get_contents() 支持php://input协议
curl_exec()  支持file, dict, gopher, http,ftp协议
fsockopen()    大部分 PHP 并不会开启 fopen 的 gopher wrapper
file_get_contents 情况使用 gopher 协议不能 URLencode

原理:

通过控制功能中的发起请求的服务来当作跳板攻击内网中其他服务。比如,通过控制前台的请求远程地址加载的响应,来让请求数据由远程的URL域名修改为请求本地、或者内网的IP地址以及服务,来造成内网系统的攻击。

危害:

1.内外网的端口和服务扫描

2.攻击运行在内网或本地的应用程序

3.对内网web应用进行指纹识别,识别企业内部的资产信息

4.攻击内网的web应用,主要是使用GET参数就可以实现的攻击(比如Struts2漏洞利用,SQL注入等)

5.利用file协议读取本地敏感数据文件等

 

SSRF利用方式

gohper协议:

介绍:

Gopher 协议是 HTTP 协议出现之前,在 Internet 上常见且常用的一个协议。当然现在 Gopher 协议已经慢慢淡出历史。

Gopher 协议可以做很多事情,特别是在 SSRF 中可以发挥很多重要的作用。利用此协议可以攻击内网的 FTP、Telnet、Redis、Memcache,也可以进行 GET、POST 请求。这无疑极大拓宽了 SSRF 的攻击面。

Gopher 可以模仿 POST 请求,故探测内网的时候不仅可以利用 GET 形式的 PoC(经典的 Struts2),还可以使用 POST 形式的 PoC。

局限:

大部分 PHP 并不会开启 fopen 的 gopher wrapper

file_get_contents 的 gopher 协议不能 URLencode

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

PHP 的 curl 默认不 follow 302 跳转

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

 

具体攻击手法:

利用 Gopher 协议拓展攻击面

 

file协议:

用来进行任意文件读取

http://xxx.com/ssrf.php?url=file:///etc/passwd

Dict协议:

探测端口操作,以及版本信息

详见 端口扫描部分:CTFHub-ssrf

 

FTP协议:

只能探测是否存在ftp,不能进行暴力破解

 

Http协议:

用来探测是否存在ssrf

 

 

漏洞的产生:

1、php file_get_contents:

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

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

 

2、php 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);
            while(!feof($fp)){
                $contents.=fgets($fp,1024);
            }
            fclose($fp);
            return $contents;
        }
    }
?>

这段代码使用fsockopen函数实现获取用户指定url的数据。这个函数会使用socket跟服务器建立tcp连接,传输原始数据。

 

3、php curl_exec():

<?php
    funciotn curl($url){
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HEADER, 0);
    curl_exec($ch);
    curl_close($ch);
}
$url = $_GET['url'];
curl($url);
?>

使用curl请求

 

防御方式:

 

1、过滤返回的信息,如果web应用是去获取某一种类型的文件。那么在把返回结果展示给用户之前先验证返回的信息是否符合标准。

2、统一错误信息,避免用户可以根据错误信息来判断远程服务器的端口状态。

3、限制请求的端口,比如80,443,8080,8090。

4、禁止不常用的协议,仅仅允许http和https请求。可以防止类似于file:///,gopher://,ftp://等引起的问题。

5、使用DNS缓存或者Host白名单的方式。

 

 

posted @ 2021-03-19 20:18  夜布多  阅读(224)  评论(0编辑  收藏  举报