SSRF 服务器端请求伪造
0x01 定义
SSRF(Server-Side Request Forgery:服务器端请求伪造) 是一种由攻击者构造,形成由服务端发起请求的一个安全漏洞。一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。(正是因为它是由服务端发起的,所以它能够请求到与它相连而与外网隔离的内部系统)
SSRF 形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。比如从指定URL地址获取网页文本内容,加载指定地址的图片,下载等等。
0x02 SSRF 的危害
- 内网端口和服务扫描
- 主机本地敏感数据的读取
- 内外网主机应用程序漏洞的利用
- 内外网Web站点漏洞利用
可能出现的地方:
-
社交分享功能:获取超链接的标题等内容进行显示
-
转码服务:通过URL地址把原地址的网页内容调优使其适合手机屏幕浏览
-
在线翻译:给网址翻译对应网页的内容
-
图片加载/下载:例如富文本编辑器中的点击下载图片到本地;通过URL地址加载或下载图片
-
图片/文章收藏功能:主要其会取URL地址中title以及文本的内容作为显示以求一个好的用具体验
-
网站采集,网站抓取的地方:一些网站会针对你输入的url进行一些信息采集工作
-
邮件系统:比如接收邮件服务器地址
简单验证流程
http://www.douban.com/***/service?image=http://www.baidu.com/img/bd_logo1.png
- 我们先验证,请求是否是服务器端发出的,可以右键图片,使用新窗口打开图片,如果浏览器上地址栏是
http://www.baidu.com/img/bd_logo1.png
,说明不存在SSRF漏洞。 - 可以在Firebug 或者burpsuite抓包工具,查看请求数据包中是否包含
http://www.baidu.com/img/bd_logo1.png
这个请求。由于SSRF是服务端发起的请求,因此在加载这张图片的时候本地浏览器中不应该存在图片的请求。 - 在验证完是由服务端发起的请求之后,此处就有可能存在SSRF,接下来需要验证此URL是否可以来请求对应的内网地址。首先我们要获取内网存在HTTP服务且存在favicon.ico文件地址,才能验证是否是SSRF。
0x03 漏洞利用
由于服务端提供了从其他服务器应用获取数据的功能且没有对用户可控的目标地址做过虑与限制。
在PHP中的curl()
,file_get_contents()
,fsockopen()
等函数是几个主要产生ssrf漏洞的函数。
file_get_contents()
file_get_contents是把文件写入字符串,当把url是内网文件的时候,他会先去把这个文件的内容读出来再写入,导致了文件读取。
<?php
if(isset($_POST['url']))
{
$content=file_get_contents($_POST['url']);
$filename='./images/'.rand().'.img';\
file_put_contents($filename,$content);
echo $_POST['url'];
$img="<img src=\"".$filename."\"/>";
}
echo $img;
?>
fsockopen()
fsockopen()
函数本身就是打开一个网络连接或者Unix套接字连接。
<?php
$host=$_GET['url'];
$fp = fsockopen("$host", 80, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
$out = "GET / HTTP/1.1\r\n";
$out .= "Host: $host\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
while (!feof($fp)) {
echo fgets($fp, 128);
}
fclose($fp);
}
?>
curl()
这应该是大家最熟悉的一个函数了,因为利用方式很多最常见的是通过file、dict、gopher这三个协议来进行渗透,接下来也主要是集中讲对于curl()
函数的利用方式。
function curl($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url); // 需要获取的 URL 地址
curl_setopt($ch, CURLOPT_HEADER, 0); // 启用时会将头文件的信息作为数据流输出
curl_exec($ch);
curl_close($ch);
}
$url = $_GET['url'];
curl($url);
利用方式
Gopher
互联网上使用的分布型的文件搜集获取网络协议,出现在http协议之前。(可以模拟GET/POST请求,换行使用%0d%0a,空白行%0a)。
gopher协议的格式:
gopher://<host>:<port>/<gopher-path>_后接TCP数据流
gopher协议在curl命令中的使用方式:
curl gopher://localhost:2222/hello%0agopher
在浏览器中访问:
dict
词典网络协议,在RFC 2009中进行描述。它的目标是超越Webster protocol,并允许客户端在使用过程中访问更多字典。Dict服务器和客户机使用TCP端口2628。
因为ssrf.php的漏洞代码有回显,所以curl命令直接访问
curl -v http://localhost/ssrf/ssrf.php?url=dict://127.0.0.1:6379/info
即可看到redis
的相关配置。
curl -v http://localhost/ssrf/ssrf.php?url=dict://127.0.0.1:22/info
即可看到ssh
的banner信息。
如果ssrf.php中加上一行屏蔽回显的代码curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
,那么这种方式就失效了,和gopher一样,只能利用nc监听端口,反弹传输数据了。
file
本地文件传输协议,主要用于访问本地计算机中的文件。
因为ssrf.php的漏洞代码有回显,所以浏览器直接访问: