大家好,又见面了,我是你们的朋友全栈君。
0x00:漏洞原理
SSRF(Server-Side Request Forgery)也属于应用层上的一个漏洞类型,用一个最简单的例子来理解这个漏洞:比如一个添加图文的功能,填入标题内容和封面图然后提交在网站前台显示,对于这个功能的图片它除了可以让你上传以外,还支持填入远程图片地址,如果你填入了远程的图片地址,则该网站会加载远程图过来进行显示,而如果程序写法不严谨或者过滤不严格,则加载图片地址的这个功能可能就可以包含进行一些恶意的脚本文件,或者你输入内网的 ip 或者一些系统的文件都会被解析执行,这个我们一般叫它 SSRF 即服务端请求伪造。
而一般我们是无法请求到系统上的文件的,内网的 ip 我们也是无法访问的,有了 SSRF 后,我们提交的加载连接是有服务器进行加载解析,实际上相当于我们以存在 SSRF 这个服务器为跳板进行的一些加载操作,我们在附一张图加深理解。
我们知道了 SSRF 的原理后,自然就能想到其危害点有哪些,比如说可以 1,加载外部的恶意木马文件执行,或者 2,加载内部的敏感文件程序自身的敏感文件,3,来访问内网进行内网端口的扫描、获取内网设备信息、枚举内网服务等。
0x01:漏洞危害
了解了漏洞的形成原因和原理后,我们通过简单的示例来进行一些危害的验证,这里我直接拿一个别人写的程序做下演示,或者也可以下载个 bwapp 练习也行,代码很简单,只有两个文件,一个是提交内容的 html 页面,另外一个是接受提交内容并加载的 php 文件,首先 html 文件内容如下:
<html>
<head>
<style> div.main { margin-left:auto; margin-right:auto; width:50%; } body { background-color: #f5f5f0; }</style>
<title>
Awesome Script!
</title>
</head>
<body>
<div class="main">
<h1>Welcome to the Awesome Script</h1>
<p>Here you will be able to load any page you want. You won't have to worry about revealing your IP anymore! We use the cURL library in order to perform the HTTP requests. Have fun!</p>
<br>
<form method="GET" action="curl.php">
<input type="text" value="Website to load..." name="path">
<input type="submit" value="Submit">
</form>
</div>
</body>
</html>
文件很简单只有一个表单,把用户输入的内容传给了 curl.php 文件,curl.php 是通过 curl 来加载访问用户提交的目标地址,代码如下:
<?php
$location=$_GET['path'];
$curl = curl_init();
curl_setopt ($curl, CURLOPT_URL, $location);
curl_exec ($curl);
curl_close ($curl);
?>
这个 php 文件就是一个 curl 使用的经典过程,初始化,然后设置访问的地址,随后执行,最后关闭。我们运行这个程序,输入一个目标的 url 地址,执行后结果如下图。
通过这个简单的靶机示例,我们可以练习一下 SSRF,我这个 SSRF 靶机程序是在我本机直接运行的,本机访问本机肯定没问题,但大家把它当作 SSRF 就好,我也没开虚拟机,所以就本地演示吧,不要在意这些细节。
首先,我们可以看下这个 SSRF 怎么去扫描内网的开放端口,我们可以尝试输入 localhost 加端口号进行尝试,这里我们为了方便,拦截这个提交的请求,通过 burp 遍历下端口。
我这里只遍历了 100 个端口,可以看到 80 端口是开放的。除此之外,也可以用来读取系统上的文件,例如我 c 盘下的一个 ssrf.txt。
上面我们使用了 http、https、file 这些协议,而在 SSRF 利用这块利用协议也有很多,例如示例中的 CURL,则其支持的协议有 dict, file, ftp, ftps, gopher, http, https, imap, imaps, ldap, pop3, pop3s, rtsp, scp, sftp, smtp, smtps, telnet, tftp 。我们再来看几个常见的,例如 dict 字典协议,这个协议可以获取到指定端口的一些信息。
上面都是常见的协议,这里顺带提一下的是 gopher,一个老协议,在 http 没有出现前,经常用它来发送数据包,对于 ssrf 来说,gopher 也会经常使用,可以使用 gopher 来攻击常见的应用,比如说 mysql,redis 等,我这里环境没有装这些应用,具体我也没有实践过,这里给大家推荐一个脚本 github 地址:https://github.com/tarunkant/Gopherus , 脚本可以生成利用连接,省去了我们很多事,从下图可以看见,它支持了我们常见的一些应用。
除此之外,也可以在 github 上搜索关键字 ssrf 来看一些大家常用的脚本和利用方式,另外也可以看一下猪猪侠的 SSRF 攻击 PPT 总结,也很详细很全面。
0x02:漏洞挖掘
漏洞挖掘的话,我从网上搜集来的方法总结了一下,我这里也没有全部碰到过,贴一张图供大家参考,图片来自于网络。
对于挖掘部分一个是功能上找再一个就是 url 上,总结下就是只要是涉及到的请求地址或功能,就可能存在 SSRF 问题。像翻译功能,很多翻译都有提供 url 地址翻译,输入 url 地址然后把整个网站页面翻译成想要的语言,但输入地址翻译时,后台会去请求这个地址,但又没有经过严格过滤,基本这样就回存在 SSRF 问题,国内比较有名的翻译之前都有存在,后来被提后都修复了,但你搜索在线翻译,结果多往后翻几页,基本都有此问题。
0x03:绕过方法
对于 SSRF 绕过方法也有很多,其基础是程序有一定的防御策略,比如说验证是否为内网 ip,如果是内网 ip 则阻止其内容的读取,而判断方式如果是纯粹的验证是否为 10 开头的 ip 这种的话,则会存在很多方式的绕过。
首先就是 @符,对于一个 url 的访问实际上是以 @符后为准的,比如说 xxxx.com@10.10.10.10,则实际上访问的是 10.10.10.10 这个地址。
第二个是网址后加 xip.io,其原理是例如 10.10.10.10.xip.io 会被解析成 10.10.10.10,详细介绍可以通过 xip.io 这个网站来查看。
第三个就是进制转换,将 ip 转换为八进制十进制十六进制这种,同样也可以正常访问,例如将 10.10.10.10 转换为十进制是 168430090,在浏览器访问 http ://168430090 就回去访问 10.10.10.10 这个地址,转换问题可以在线查看一般有很多网站提供,或者自己算也可以,这里为了方便,我写了一个 js 脚本,代码如下。
<!DOCTYPE html>
<html>
<head>
<title>IP转换进制</title>
<script>
function ip(){
var ipvalue = document.getElementById("ipvalue").value;
var arr = ipvalue.split(".");
var decm = parseInt(arr[0])*256*256*256+parseInt(arr[1])*256*256+parseInt(arr[2])*256+parseInt(arr[3]);
var hex = parseInt(decm).toString(16).toUpperCase();
var binary = parseInt(decm).toString(2).toUpperCase();
document.getElementById("result").innerHTML = '十六进制 = '+hex+'<br> 十进制 = '+decm+"<br> 二进制 = "+binary;
}
</script>
</head>
<body>
<input type="text" name="ip" id="ipvalue" />
<button type="button" onclick="ip()">转换</button>
<div id="result"></div>
</body>
</html>
代码比较简单,输入 ip 后会对 ip 进行进制转换,然后进行输出,效果如下。
还有一个就是短网址绕过,这个在线转换有很多网站提供。
0x04:代码审计
对于代码审计其实没什么好说的,只要能读懂代码,基本这种漏洞一眼就可以看出来,对于网络资源请求且没有过滤的就可能存在 SSRF,我这里也找了几个例子,大体来说涉及到获取内容的函数都有可能存在,例如 file_get_contents,fsockopen,curl_exec 等,示例如下。
例一:
$url = $_GET['url'];
echo file_get_contents($url);
例二:
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;
}
}
例三:
function 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);
0x05:防御方法
对于防御方法,还是网上那一套,总结下就是三点,第一限制 http(s)协议,例如 curl 的设置 curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);这个对于那些 xip.io 之类的绕过就会失效。第二就是禁止 30x 跳转,例如 curl 的设置就需要删掉 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); 这一项。第三就是设置白名单方式,只要不是我指定的地址,就不进行后续操作。
0x06:总结
SSRF 漏洞即使现在来说也并不少见,仍有很多网站和程序存在此问题,相对于跨站注入来说可能也有一部分容易忽略,而危害却很高,且只要涉及到请求资源的功能或地址或者 url 存在连接资源等关键字等,就有可能存在此问题,所以测试时应该和跨站注入并重去测,一样也是我们不容忽视的。
公众号推荐:aFa攻防实验室
分享关于信息搜集、Web安全、内网安全、代码审计、红蓝对抗、Java、Python等方面的东西。
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/152800.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...