Web安全—SSRF服务器端请求伪造

0x00漏洞概述

服务端请求伪造(Server-side Request Forge)

服务器会根据用户提交的URL发送一个HTTP请求。使用用户指定的URL,Web应用可以获取图片或者文件资源等。典型的例子是百度视图功能。

image-20211106151511688

如果没有对用户提交URL和远端服务器所返回的信息做合适的验证或过滤,就有可能存在“请求伪造”的缺陷

“请求伪造”,顾名思义就是攻击者伪造正常的请求,以达到攻击的目的。如果“请求伪造“发生在服务器端,那这个漏洞就叫做”服务器端请求伪造“

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

漏洞拓扑图

image-20211106161558153

0x01漏洞原理

服务器接受了来自于客户端任意输入的URL地址,并由服务器代客户端发送请求。

对用户输入的URL,没有进行恰当的过滤,导致任意URL输入。

没对响应的结果进行检验,直接输出。

0x02存在漏洞的位置

Web功能

分享:通过URL地址分享网页内容
转码服务
在线翻译
在线识图
图片加载与下载:通过URL地址加载或下载图片
图片、文章收藏功能
未公开的api实现以及其他调用URL的功能
...

从URL上面去寻找

share
wap
url
link
src
source
target
u
3g
display
sourceURL
imageURL
domain
...

0x03漏洞经典代码审计

相关危险函数

再次强调一下,并不是有这些函数就会造成漏洞,这只是涉及的。

SSRF涉及到的危险函数主要是网络访问,支持伪协议的网络读取的函数以PHP为例子,涉及到的函数有

  • file_get_contents()——是把文件写入字符串,当把url是内网文件的时候,会先去把这个文件的内容读出来再写入,导致了文件读取
  • fsockopen()——fsockopen
  • curl_exec()——利用方式很多,最常见的是通过file、dict、gopher这三个协议来进行渗透

image-20211106161530204

curl_exec()核心代码

需要curl组件(7.2版本)支持

<?php
    if(isset($_REQUEST['url'])){
        $link = $_REQUEST['url'];		//接收参数url
        $fileName = './curled/'.time().".txt";		//新建变量$fileName = curled/12312312.txt
        $curlObj = curl_init($link);		//curl_init初始化一个新的会话,创建一个新的CURL对象
        $fp = fopen($fileName,'w');			//写入上面的文件中
        
        curl_setopt($culrObj,CURLOPT_FILE,$fp);
        curl_setopt($curlObj,CURLOPT_HEADER,0);
        curl_setopt($curlObj,CURLOPT_FOLLOWLOCATION,TRUE);
       //这三行暂时不用去理解,中间是curl的组件设置,这是它帮我们发送请求的一个组件,对CURL对象的设置,固定写法
        curl_exec($curlObj);	//发送传递过来的URL请求
        curl_close($curlObj);	//之后关闭
        fclose($fp);			//关闭文件
            
        if(getimagesize($fileName)){		//如果请求的资源是一张图片
            header("Content-Type:image/png");	//就加一个文件头
        }    
            
        $fp = fopen($fileName,'r');
        $result = fread($fp,filesize($fileName));
        fclose($fp);
        echo $result;
    }
	else
	{
        echo "?>url=[url]";
    }
    ?>
  • 我们提交了一个请求,这个php脚本会自动帮我们发送这个请求,

  • 发送完请求后,会帮我们保存在curled/中

  • 之后帮我们读取这个请求资源,所以是服务器帮我们发送的URL请求,而不是我们客户自己的浏览器。说白了就是url传到服务器上,服务器上的curl代码帮我们发送的请求。

仔细想一下,是谁给百度发送的请求呢?就是16.103这个主机帮我们给百度发起的请求,请求百度的首页文件,我们看到的内容其实是代码新建的txt文件里面的内容

image-20211106155052209

file_get_contents()核心代码

<?php
    if(isset($_POST['url']))				#确认通过POST方式接收到url参数
    {
        $content=file_get_contents($_POST['url']);	#远程获取URL链接上的内容
        $filename='./images/'.rand().'img1.jpg';	#生成一个随机的图片路径与名称
        file_put_contents($filename,$content);		#将图片内容放入这个名称中,绑定路径、名称、内容
        echo $_POST['url'];							#输出URL用于测试
        $img = "<img src="\".$filename."\">";		#组合成一个img标签
    }	
    echo $img;										#输出显示在页面中
    ?>

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

0x04漏洞挖掘过程

  1. 抓包找功能点,找参数,寻找传递URL这些参数
  2. 如果是,将URL参数换成127.0.0.1看他能不能发起请求
  3. 如果可以,将URL换成私有IP网段,使用github上的SSRF-Fuzz工具进行逐个探测,给它参数换成内网IP(找服务器对应的内网IP段 根据超时时间、响应内容等)
  4. 内网主机发现,端口探测

挖掘过程详解

  • 寻找输入点,看是否是URL输入点

image-20211028150605364

  • 将URL输入点改成127.0.0.1,看是否能正常发起请求,探测的时间很短,基本上就是可以发起请求。

image-20211028150636134

  • 那么现在开始测试各种私有网段的IP,如果对应的IP网段范围不存在,那就是高延迟的
    • 10.0.0.0/8
    • 172.16.0.0~172.31.255.255
    • 192.168.0.0~192.168.255.255

image-20220111223213434

  • 找到了一个真实存在的,172.16.12.50

image-20220111223254730

0x05漏洞验证

1、因为SSRF漏洞是构造服务器发送请求的安全漏洞,所以可以通过抓包分析发送的请求是否是由服务器端发送的来判断是否存在SSRF漏洞

2、在页面源码中查找访问的资源地址,如果该资源地址类型为http://www.xxx.com/a.php?image=(地址)的可能存在SSRF漏洞

0x06漏洞危害

  1. 主机探测

  2. 端口探测

  3. 攻击内网主机(当然是探测到的主机)

0x07SSRF漏洞防御与修复

过滤用户输入的URL

  • 限制协议,仅允许http或者https协议
  • 限制IP,避免应用被用来获取内网数据,攻击内网
  • 限制端口,限制请求端口为常用端口

过滤输出

  • 过滤返回信息,只要不符合要求的,全部过滤

  • 设置白名单,或者限制内网IP,以防止对内网进行攻击

  • 禁止30x跳转

  • 屏蔽返回的详细信息或者统一错误,让攻击者无法对内网信息进行判断

0x08SSRF与CSRF区别

所有区别类的问题,可以从下面几点论述

1、漏洞概述与原理

SSRF:服务端请求伪造。web应用中的识图、翻译、分享、收藏等可代替用户发起http请求的功能中,用户可以输入任意的URL,服务端处理请求后对输出没有任何的检验并将结果真实地返回给用户,可造成内网沦陷等危害。

CSRF:跨站请求伪造。在身份验证不过期的情况下,攻击者利用客户端的身份验证即cookie信息,执行非用户本意的操作,可导致信息泄漏,公司业务以及信誉度下降的后果。

2、漏洞利用

CSRF的攻击目标为客户端,SSRF则为内网机器

3、代码层危险函数、关键参数

SSRF:curl_exec、fsockopen()、file_get_contents()

CSRF:cookie

4、防御手法

CSRF防御手法上只要围绕着“不可预测性原则”即可,例如添加随机数token

SSRF防御手法上只要围绕着“纵深防御原则”即可,例如过滤输入,检验输出

0x09SSRF与RFI区别

1、漏洞概述与原理

SSRF:服务端请求伪造。web应用中的识图、翻译、分享、收藏等可代替用户发起http请求的功能中,用户可以输入任意的URL,服务端处理请求后对输出没有任何的检验并将结果真实地返回给用户,可造成内网沦陷等危害。

RFI:远程文件包含漏洞。指的是能够包含远程服务器上的文件并执行。可造成getshell、网页挂马、数据泄漏等危害。

2、漏洞利用

RFI的攻击目标为服务端本身,SSRF则借助服务端打内网机器

3、代码层危险函数、关键参数

SSRF:curl_exec、fsockopen()、file_get_contents()

RFI:伪协议等

4、防御手法

RFI防御手法上可用“黑白名单原则”,“纵深防御原则”,php.ini配置文件更改等

SSRF防御手法上只要围绕着“纵深防御原则”即可,例如过滤输入,检验输出

0x10关于SSRF的绕过

1、可以在IP段后添加@紧接着跟上dnslog域名发起请求,查看dnslog有无回显

2、通过将点号转换成句号或者下划线

posted @ 2022-01-11 22:35  谨言慎行啊  阅读(355)  评论(0)    收藏  举报