七、SSRF漏洞
7.1 介绍SSRF漏洞
SSRF(Server-Side Request Forgery,服务器端请求伪造)是一种由攻击者构造请求,由服务端发起请求的安全漏洞。一般情况下,SSRF攻击的目标是外网无法访问的内部系统(正因为请求是由服务器端发起的,所以服务器能请求到与自身相连而与外网隔离的内部系统)。
7.2 SSRF漏洞原理
SSRF的形成大多是是由于服务器端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制。例如,黑客操作服务器端从指定URL地址获取网页文本内容,加载指定地址的图片等,利用的是服务端的请求伪造。SSRF利用存在缺陷的Web应用作为代理攻击远程和本地的服务器。
主要攻击方式如下所示。
-
对外网、服务器所在内网、本地进行端口扫描,获取一些服务的banner信息。
-
攻击运行在内网或本地的应用程序。
-
对内网Web应用进行指纹识别,识别企业内部的资产信息。
-
攻击内外网的Web应用,主要是使用HTTP GET请求就可以实现的攻击(比如struts2、SQli等)。
-
利用file协议读取本地文件等。
7.3 SSRF漏洞利用
SSRF漏洞利用的测试地址Hi:http://127.0.0.1/ssrf/ssrf.php?url=http://127.0.0.1/xss/xss1.php。
页面ssrf.php实现的功能是获取GET参数URL,然后将URL的内容返回网页上。如果将请求的网址篡改为http://www.baidu.com,则页面会显示http://www.baidu.com的网页内容,如图88所示。

但是,当设置参数URL为内网页面时,则会泄露内网信息,例如,当URL=192.168.1.115:3306时,页面返回“当前地址不允许连接到MySQL服务器”,说明192.168.0.2存在MySQL服务,如图89所示。

访问ssrf.php?url=file:///C:/Windows/win.ini即可读取本地文件,如图90所示。

7.4 SSRF漏洞代码分析
在页面SSRF.php中,程序获取GET参数URL,通过curl_init()初始化curl组件后,将参数URL带入curl_setopt($ch,CURLOPT_URL,$url),然后调用curl_exec请求该URL。由于服务器端会将banner信息返回客户端,所以可以根据banner判断主机是否存在某些服务,代码如下。
<?php
function curl($url)
{
//curl 就是模拟浏览器请求的,比如获取获取远程的网页
$ch = curl_init();//初始化一个curl会话
curl_setopt($ch, CURLOPT_URL, $url);//设置抓取的url
curl_setopt($ch, CURLOPT_HEADER, 0);//设置header
curl_exec($ch);//运行curl,请求网页
curl_close($ch);//关闭curl会话
}
$url = $_GET['url'];//从浏览器中传入地址
curl($url); //传入curl函数中
/*
<?php
// 初始化一个 cURL 对象
$curl = curl_init();
// 设置你需要抓取的URL
curl_setopt($curl, CURLOPT_URL, 'http://www.baidu.com');
// 设置header
curl_setopt($curl, CURLOPT_HEADER, 1);
// 设置cURL 参数,要求结果保存到字符串中还是输出到屏幕上。
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
// 运行cURL,请求网页
$data = curl_exec($curl);
// 关闭URL请求
curl_close($curl);
// 显示获得的数据
var_dump($data);
?>
*/
?>
7.5 SSRF漏洞修复建议
针对SSRF漏洞的修复,笔者给出以下几点建议。
-
限制请求的端口只能为Web端口,只允许访问HTTP和HTTPS的请求。
-
限制不能访问内网的IP,以防止对内网进行攻击。
-
屏蔽返回的详细信息。