5.SSRF服务器端请求伪造

2023-03-12,,

SSRF(服务端请求伪造):是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。

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

SSRF形成的原因:服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。

比如从指定URL地址获取网页文本内容,加载指定地址的图片,下载等等。利用的是服务端的请求伪造。ssrf是利用存在缺陷的web应用作为代理攻击远程和本地的服务器

看不懂????

换种理解就是,html,php,asp,jsp 具有这些文件后缀的文件通常储存在web服务器(网站服务器)中,而且web服务器都具有独立ip

其中网站访问大致步骤:

用户在地址栏输入网址    ------>     向目标网站发送请求 ------->   目标网站接受请求并在服务器端验证请求是否合法,然后返回用户所需要的页面 ------->    用户接收页面并在浏览器中显示

这里假设请求的网址为:www.xxx.com/a.php?image=http://www.abc.com/1.jpg

那么产生SSRF漏洞的环节在哪里呢?目标网站接受请求后在服务器端验证请求是否合法

产生的原因:服务器端的验证并没有对其请求获取图片的参数(image=)做出严格的过滤以及限制,导致可以从其他服务器的获取一定量的数据

例如:   www.xxx.com/a.php?image=http://www.abc.com/1.jpg

如果我们将http://www.abc.com/1.jpg  换为与该服务器相连的内网服务器地址会产生什么效果呢?

如果存在该内网地址就会返回1xx,2xx 之类的状态码,不存在就会其他的状态码

终极简析: SSRF漏洞就是通过篡改获取资源的请求发送给服务器,但是服务器并没有发现在这个请求是合法的,然后服务器以他的身份来访问其他服务器的资源。

主要攻击方式:

1.可以对外网、服务器所在内网、本地进行端口扫描,获取一些服务的banner信息;

2.攻击运行在内网或本地的应用程序(比如溢出);

3.对内网web应用进行指纹识别,通过访问默认文件实现;

4.攻击内外网的web应用,主要是使用get参数就可以实现的攻击(比如struts2,sqli等);

5.利用file协议读取本地文件等。

常用的后端实现:

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

这段代码使用file_get_contents获取用户指定图片的内容,然后随机命名保存在硬盘里,最后展示给用户。

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

这段代码跟服务器建立tcp链接,发送原始数据,通过发送http信息,来获取返回信息。

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

通过curl获取信息。

<?php
if (isset($_POST['url'])) {
$link = $_POST['url'];
$filename = './curled/'.rand().'txt';
$curlobj = curl_init($link);
$fp = fopen($filename,"w");
curl_setopt($curlobj, CURLOPT_FILE, $fp);
curl_setopt($curlobj, CURLOPT_HEADER, 0);
curl_exec($curlobj);
curl_close($curlobj);
fclose($fp);
$fp = fopen($filename,"r");
$result = fread($fp, filesize($filename));
fclose($fp);
echo $result;
}
?>

用来端口扫描等

SSRF漏洞的寻找(漏洞常见出没位置):

1)分享:通过URL地址分享网页内容

2)转码服务

3)在线翻译

4)图片加载与下载:通过URL地址加载或下载图片

5)图片、文章收藏功能

6)未公开的api实现以及其他调用URL的功能

7)从URL关键字中寻找 

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

SSRF漏洞的验证方法:

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

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

最后附带一张SSRF漏洞导图:

具体的SSRF漏洞挖掘经验,我会在下面的章节中介绍

防御方法:

1.过滤返回信息,验证远程服务器对请求的响应是比较容易的方法。如果web应用是去获取某一种类型的文件。那么在把返回结果展示给用户之前先验证返回的信息是否符合标准。

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

3.限制请求的端口为http常用的端口,比如,80,443,8080,8090。

4.黑名单内网ip。避免应用被用来获取获取内网数据,攻击内网。

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

5.SSRF服务器端请求伪造的相关教程结束。

《5.SSRF服务器端请求伪造.doc》

下载本文的Word格式文档,以方便收藏与打印。