SSRF
由攻击者构造,服务器端发起请求的安全漏洞,漏洞属于信息泄露的一种。
一般情况下,SSRF的攻击目标大多是网站的内部系统(正因为请求是由服务器端发起的,所以服务器能请求到与自身相连而与外网隔离的内部系统),只要当前服务器有向其他服务器发送请求的地方都可能存在SSRF漏洞。
先来看一下关于造成SSRF常见的函数
fsockopen()
file_get_contents()
curl_exec()
漏洞复现
(1)fsockopen()
<?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);
}
?>
(2)file_get_contents()
<?php
$url = $_GET['url'];
echo file_get_contents($url);
?>
(3)curl_exec()
<?php
if(isset($_GET['url']))
{
$link=$_GET['url'];
$curlobj=curl_init($link);
$result=curl_exec($curlobj);
curl_exec($curlobj);
curl_close($curlobj);
echo $result;
}
?>
SSRF形成的原因
大多数都是由服务端提供了从其他服务器应用获取数据的操作,且没有对目标地址做过滤与限制,比如从指定URL地址获取网页文本内容,加载指定地址的图片文档等等
举个例子:假设现在有两个网站,一个网站是所有人都可以访问的外网,一个是只有内部访问的内网,并且当用户请求资源时,外网会向内网请求数据,最后返还给用户。如果外网没有对用户请求的资源进行过滤,用户请求不合法时,就会以外网的身份去访问内网,导致信息泄露。
SSRF的用途(攻击者利用SSRF实现攻击的主要用途)
-
对外网、服务器所在内网、本地进行端口扫描,获取一些服务的banner信息
-
攻击者运行在内网或本地的应用程序(如溢出)
-
对内网进行指纹识别
-
利用各种如file协议读取本地文件等操作
SSRF漏洞的寻找
-
分享链,通过URL地址分享网页的内容
-
转码服务
-
在线翻译
-
图片加载与下载处
-
图片、文章收藏功能
-
从URL关键字寻找:share/wap/url/link/src/source/target/u/3g/display/sourceURL/imageURL/domain/... ...
SSRF常见的绕过方式
(一)更改ip地址写法绕过
一些开发者会通过对传递的URL参数进行正则表达式过滤,代码如下
10(\.([2][0-4]\d|[2][5][0-5]|[01]?\d?\d)){3}$
172\.([1][6-9]|[2]\d|3[01])(\.([2][0-4]\d|[2][5][0-5]|[01]?\d?\d)){2}$
这时候,我们可以通过修改进制的方式绕过,如192.168.0.1这个ip地址,就可以改写成
八进制:0300.0250.0.1
十进制整数:3232235521
十六进制/整数:0xC0.0xA8.0.1/0xC0A80001
(二)URL解析绕过
举例:传入url的值为http://www.baidu.com@dl01.rong360.com/
此时通过url解析出来的host为dl01.rong360.com
CTF下的SSRF
(1)从内网访问flag.php
利用伪协议读取flag.php
常见的伪协议
(1)file:// 本地文件传输协议,file协议可以尝试从文件系统中获取文件,就如同在Wins资源管理器中打开文件一样,那为什么在上面实验中是file:///而不是file://呢? 这个得从URI的结构来看 URL结构: scheme://[user:password@]host[:port]path?query 如果有host的时候,前面是要加//的,因此对于http,https等这些网络地址来讲 http://www.baidu.com:80/abab/abab 写成这样很自然。 那么如果是文件呢?文件因为没有 host,所以中间的部分就不要了,那么就变成了 file:///abab/abab
(2)dict:// dict协议。字典服务器器协议,dict是基于查询响应的TCP协议,它的目标是超越Webster protocol,并允许客户端在使用过程中访问更多字典。
(3)dict服务器和客户机使用TCP端口2628 sftp:// sftp代表SSH文件传输协议。一种运行在安全连接上与SSH打包在一起的单独协议
(4)ldap:// ldap代表轻量级目录访问协议。用于管理和访问分布式目录信息服务的应用程序协议
(5)tftp:// tftp(简单文件传输协议)一种简单的基于lockstep机制的文件传输协议。允许客户端从远程主机获取文件或将文件上传至远程主机。
(2)利用ssrf进行端口扫描
设置端口号
利用爆破探测开放的端口
(3)URL重定向
某些情况下,后端程序可能户对访问的URL进行解析,对解析出来的host地址进行过滤,这时候可能会出现URL参数解析不当导致绕过
(4)ip进制转换绕过
首先当访问127.0.0.1的时候,发现过滤了127,172和@,这次ban掉了127以及172.不能使用点分十进制的IP了,但是又要访问127.0.0.1,该怎么办呢
对于这种过滤我们可以采用改变IP的写法的方式进行绕过,例如127.0.0.1这个IP地址我们可以改写成:
-
8进制格式:0177.00.00.01
-
16进制格式:0x7f.0x0.0x0.0x1
-
10进制整数格式:2130706433
(5)302跳转
短地址跳转,将127.0.0.1/flag.php改写为短地址,可以利用一些专门转换短链接的网站转换绕过
SSRF防护的方法
防护措施
(1)黑名单
-
过滤10.0.0.0/8、172.16.0.0/12/192.168.0.0/16、localhost等等
-
过滤各种协议如file://、dict://、ftp://
-
对回显内容进行过滤
-
内网服务开启鉴权(Mencached,Redis,Elasticsearch and MongoDB)
(2)使用白名单,如果出现需要请求资源而无法使用白名单的情况,首先禁用CURLOPT_FOLLOWLOCATION,然后通过域名获取目标ip,并过滤内部ip,最后对比返回内容是否与假定一致