Web笔记(十二)SSRF

这个系列是整理学习安全的笔记,包括Web和PWN的一些知识。本章是SSRF漏洞相关的基础知识和可能产生SSRF漏洞的php函数。

Posted by K4ys0n on December 5, 2020

0x00 SSRF漏洞简介

SSRF(server-site request forgery,服务端请求伪造)是一种构造请求,由服务端发起请求的安全漏洞。

客户端—服务端—内网资源

服务端与内网资源可交互,客户端通过伪造服务端请求内网资源的http请求,来获取内网资源。

0x01 SSRF漏洞原理

1. SSRF形成原因

服务端提供了从其他服务器获取数据的功能,但没有对内网目标地址做过滤和限制。

2. 主要方式

  • 对外网、服务器所在内网、本地进行端口扫描,获取Banner信息。
  • 测试运行在内网或本地的应用程序。
  • 利用file协议读取本地文件等。

3. 漏洞代码

<?php
function curl($url){    // curl函数用来发送请求
    $ch=curl_init();
    curl_setopt($ch,CURLOPT_URL,$url);
    curl_setopt($ch,CURLOPT_HEADER,0);
    curl_exec($ch);
    curl_close($ch);
}
$url = $_GET["url"];    // 用户通过构造url来进行访问
curl($url);
?>

访问链接如:http://ip/ssrf_test/test.php?url=file:///c:/windows/win.ini

即利用file伪协议进行SSRF,攻击内网:

file:///c:/windows/win.ini

0x03 产生SSRF漏洞的PHP函数

很多web应用都提供了从其他的服务器上获取数据的功能。使用用户指定的URL,web应用可以获取图片、下载文件,读取文件内容等。

这个功能如果被恶意使用,可以利用存在缺陷的web应用作为代理,攻击远程和本地的服务器。

这种形式的攻击称为服务端请求伪造攻击(Server-side Request Forgery)。

SSRF攻击可能存在任何语言编写的应用,php中可能存在SSRF漏洞的函数有:

  • file_get_contents()
  • fsockopen()
  • curl_exec()

0x04 file_get_contents()

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

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

0x05 fsockopen()

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

<?php
function GetFile($host, $port, $link){
    $fp = fsockopen($host, intval($port), $errno, $errstr, 30);  // 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 .=($fp,1024);
        }
        fclose($fp);
        return $contents;
    }
}
?>

0x06 curl_exec()

使用curl发送请求获取数据。

<?php
    if(isset($_POST['url'])){
        $link = $_POST['url'];
        $curlobj = curl_init();
        curl_setopt($curlobj,CURLOPT_POST,0);  // 如果最后一个是1或真,那就是POST请求。
        curl_setopt($curlobj, CURLOPT_RETURNTRRANSFER, TRUE);    // TRUE 将curl_exec获取的信息以字符串返回,而不是直接输出。
        $result = curl_exec($cuelobj);
        curl_close($curlobj);
        $filename = './curled/'.rand().'/txt';
        file_put_contents.echo $result;
    }
?>

0x07 SSRF内网资源探测

以下代码存在SSRF漏洞:

<?php
    if(isset($_GET['url'])){
        $link = $_GET['url'];
        $curlobj = curl_init($link);
        curl_setopt($curlobj,CURLOPT_HEADER,0);
        curl_setopt($curlobj,CURLOPT_RETURNTRANSFER,1);    // 设置返回结果为字符串
        $result = curl_exec($curlohj);
        echo $result;
        curl_close($curlobj);
    }
?>

使用NAT网卡模式打开vm windows server 2003。这样windows虚拟机就和PC在同一个局域网下,相当于内网,然后由PC对外有一个ip,修改本地host文件,使本地IP地址与自定义域名映射(运行drivers,然后打开etc文件夹,想办法新建一个hosts文件,写入

127.0.0.1 test.com

即可,浏览器访问test.com就会访问本地网站)。

一般情况下将web应用程序暴露在互联网可以通过web浏览器进行访问。但是会将内网资源封闭起来,避免与外部交互。那么如果网站存在SSRF漏洞,利用SSRF进行内网资源访问。

如:

http://服务器ip/ssrf_test/ssrf.php?url=http://内网资源ip/source.txt

或者利用SSRF进行端口扫描:提交对应参数url包含IP地址:端口号 测试端口状态。比如在浏览器中输入:http://服务器ip/ssrf/ssrf.php?url=http://127.0.0.1:3306 来查看服务器是否开放了3306端口,如果有会把响应直接输出在浏览器上。

0x08 SSRF危害

  • 扫描内部网络
  • 构造数据攻击内部主机
  • 作为网络跳板来攻击其他主机
  • 发起DDOS攻击

0x09 SSRF漏洞利用

  • 对外网、服务器所在内网、本地进行端口扫描,获取一些服务的banner信息
  • 攻击者运行在内网或本地的应用程序(比如溢出)
  • 对内网web应用进行指纹识别,通过访问默认文件实现
  • 攻击内外网的web应用,主要是使用get参数就可以实现的攻击(比如struct2、SQL注入等)
  • 利用file等协议读取本地文件

0x0a SSRF防御

一般防御方法:

  • 使用系统内置函数完成目标URL解析
  • 禁止解析跳转
  • 对返回结果进行过滤,返回结果之前先验证返回的信息是否符合标准
  • 禁用不必要的协议,如file://、gopher://、dict://、ftp://等
  • 设置URL白名单或限制内网IP
  • 只允许请求端口为Web端口,比如80、443、8080、8090
  • 统一错误信息,屏蔽返回的详细信息,避免用户根据错误信息来判断远端服务器的端口状态

0x0b 常见SSRF位置

  • 社交分享功能:获取超链接的标题等内容进行显示
  • 转码服务:通过URL地址把原地址的网页内容调优适合手机屏幕浏览
  • 在线翻译:给网址翻译对应网页的内容
  • 图片加载/下载:富文本编辑器的下载图片;通过URL地址加载或下载图片
  • 图片/文章收藏:会取URL中title以及文本的内容作为显示
  • 云服务厂商:远程执行一些命令来判断网站是否存活
  • 网站采集:一些网络会针对输入的URL进行信息采集工作
  • 数据库内置功能:比如MongoDB的copyDatabase函数
  • 邮件系统:比如接收邮件服务器地址
  • 编码处理,属性信息处理,文件处理:如ffmpg/ImageMagic/docx/pdf/xml处理器等
  • 一些URL的关键词:share、wap、url、link、src、source、target、u、3g、display、sourceURI、imageURL、domain……

0x0c 绕过host限制

1. @绕过

URI = scheme:[//[user[:pass]@]host[:port]path[?query][#fragment]]

例如:

http://baidu.com@127.0.0.1:10080/abc/xxx.php

2. 域名绕过

用域名代替IP。

3. 其他形式的IP地址

  • 十进制
    http://2130706433/
    相当于
    http://127.0.0.1/
    
  • 缩略
    http://127.1/
    
  • localhost
  • [::]:80
  • 短链接

4. 指向任意IP的xip.io

xip.io是一个可以指向任意IP的域名,以下都相当于10.0.0.1

  • 10.0.0.1.xip.io
  • www.10.0.0.1.xip.io
  • mysite.10.0.01.xip.io
  • foo.bar.10.0.0.1.xip.io

0x0d 绕过scheme限制

curl如果允许重定向

curl_setopt($curlobj, CURLOPT_FOLLOWLOCATION,1);

可通过header函数来重定向页面

<?php
    header("Location: http://1.1.1.1/");
?>