1、SSRF概念
SSRF(Server-Side Request Forgery:服务器端请求伪造)是一种由攻击者构造形成并由服务端发起恶意请求的一个安全漏洞。正是因为恶意请求由服务端发起,而服务端能够请求到与自身相连而与外网隔绝的内部网络系统,所以一般情况下,SSRF的攻击目标是攻击者无法直接访问的内网系统。
2、SSRF的原理
SSRF漏洞的形成大多是由于服务端提供了从其他服务器应用获取数据的功能而没有对目标地址做过滤和限制。例如,黑客操作服务端从指定URL地址获取网页文本内容,加载指定地址的图片,下载等,利用的就是服务端请求伪造,SSRF漏洞可以利用存在缺陷的WEB应用作为代理攻击远程和本地的服务器。
3、SSRF的危害
- 对外网、服务器所在内网、服务器本地进行端口扫描,获取一些服务的banner信息等。
- 攻击运行在内网或服务器本地的其他应用程序,如redis、mysql等。
- 对内网Web应用进行指纹识别,识别企业内部的资产信息。
- 攻击内外网的Web应用,主要是使用HTTP GET/POST请求就可以实现的攻击,如sql注入、文件上传等。
- 利用file协议读取服务器本地文件等。
- 进行跳板攻击等。
4、SSRF测试代码
SSRF漏洞相关函数
file_get_contents() 将整个文件或一个url所指向的文件读入一个字符串中。
readfile() 输出一个文件的内容。
fsockopen() 打开一个网络连接或者一个Unix 套接字连接。
curl_exec() 执行一个cURL会话,成功返回true,失败返回false。
curl_setopt() 函数将为一个CURL会话设置选项。option参数是你想要的设置,value是这个选项给定的值。
-
file_get_contents()
测试代码:
<?php
$url = $_GET['url'];
echo file_get_contents($url);
?>
上述测试代码中,file_get_contents()
函数将整个文件或一个url所指向的文件读入一个字符串中,并展示给用户,我们构造好paylaod即可读取服务器本地的任意文件。
也可以进行远程访问:
readfile()函数与filegetcontents()函数相似。
-
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);
}
?>
fsockopen($hostname,$port,$errno,$errstr,$timeout)
用于打开一个网络连接或者一个Unix 套接字连接,初始化一个套接字连接到指定主机(hostname),实现对用户指定url数据的获取。该函数会使用socket跟服务器建立tcp连接,进行传输原始数据。fsockopen()将返回一个文件句柄,之后可以被其他文件类函数调用(例如:fgets(),fgetss(),fwrite(),fclose()还有feof())。如果调用失败,将返回false。
构造 ssrf.php?url=www.baidu.com
即可成功触发ssrf并返回百度主页:
但是该函数的SSRF无法读取本地文件。
-
curl_exec()
测试代码:
<?php
error_reporting(E_ALL ^ E_NOTICE);
function curl($url){
$ch = curl_init();//初始化curl会话
curl_setopt($ch,CURLOPT_URL,$url);//指定请求的url
curl_setopt($ch,CURLOPT_HEADER,0);// 启用时会将头文件的信息作为数据流输出。参数为1表示输出信息头,为0表示不输出
curl_exec($ch);
curl_close($ch);
}
$url = $_GET['url'];
curl($url);
?>
此页面的功能是获取URL参数,然后将URL的内容显示到网页页面上。
利用上面编写好的SSRF漏洞来测试一下:
- 探测一下本地是否存在mysql服务器
出现mysql相关的提示,说明这个服务器上存在mysql。
Tips:如果对url后缀有限制则可以用
?
或者#
绕过,如http://localhost/ssrf/ssrf.php?url=127.0.0.1:3306/?.jpg
- 伪造请求访问百度(用服务器做跳板访问别的网站)
- 伪造请求探测服务器开放的端口
和第一点相同,更改不同的端口号进行遍历来判断端口是否开放。
- 伪造请求读取服务器(内网)敏感资料
5、SSRF漏洞测试
漏洞测试靶场:vulhub之Weblogic SSRF漏洞
SSRF漏洞存在于http://your-ip:7001/uddiexplorer/SearchPublicRegistries.jsp,我们在brupsuite下测试该漏洞。访问一个可以访问的IP:PORT,如http://127.0.0.1:7001:
可访问的端口将会得到错误,一般是返回status code(如下图),如果访问的非http协议,则会返回did not have a valid SOAP content-type。
修改为一个不存在的端口,将会返回could not connect over HTTP to server。
通过错误的不同,即可探测内网状态。
6、SSRF漏洞常见挖掘方法
6.1、SSRF涉及的协议
- file协议:在有回显的情况下,利用 file 协议可以读取任意文件的内容
- dict协议:泄露安装软件版本信息,查看端口,操作内网redis服务等
- gopher协议:gopher支持发出GET、POST请求。可以先截获get请求包和post请求包,再构造成符合gopher协议的请求。gopher协议是ssrf利用中一个最强大的协议(俗称万能协议),可用于反弹shell
- http/s协议:探测内网主机存活
6.2、SSRF常见的种类
- 远程下载SSRF:可以直接操纵服务器远程下载其他服务器的资源,这种可以完全回显所有信息,危害最大。
- 布尔型SSRF:不会回显被攻击的内网信息,是提示true和false,这种对攻击者提供的信息较少,一般只能探测和盲打,利用率不高。
- 无回显SSRF:不回显任何信息的SSRF。只能通过dnslog判断ssrf是否存在,无法用来探测内网,只能配合其他信息泄露来盲打内网。单独存在没有危害。
6.3、SSRF通常可能存在的地方
-
社交分享功能:获取超链接的标题等内容进行显示
-
转码服务:通过URL地址把原地址的网页内容调优使其适合手机屏幕浏览
-
在线翻译:给网址翻译对应网页的内容
-
图片加载/下载:例如富文本编辑器中的点击下载图片到本地;通过URL地址加载或下载图片
-
图片/文章收藏功能:主要其会取URL地址中title以及文本的内容作为显示以求一个好的用具体验
-
云服务厂商:它会远程执行一些命令来判断网站是否存活等,所以如果可以捕获相应的信息,就可以进行ssrf测试
-
网站采集、网站抓取的地方:一些网站会针对你输入的url进行一些信息采集工作
-
数据库内置功能:数据库的比如mongodb的copyDatabase函数
-
邮件系统:比如接收邮件服务器地址
-
编码处理、属性信息处理、文件处理:比如ffpmg,ImageMagick,docx,pdf,xml处理器等
-
未公开的api实现以及其他扩展调用URL的功能:可以利用google 语法加上这些关键字去寻找SSRF漏洞
一些的url中的关键字:share、wap、url、link、src、source、target、u、3g、display、sourceURl、imageURL、domain……
-
从远程服务器请求资源(upload from url 如discuz!;import & expost rss feed 如web blog;使用了xml引擎对象的地方 如wordpress xmlrpc.php)
6.4、SSRF漏洞验证方法
- 排除法:浏览器f12查看源代码看是否是在本地进行了请求
比如:该资源地址类型为 http://www.xxx.com/a.php?image=(地址)的就可能存在SSRF漏洞
- dnslog等工具进行测试,看是否被访问
–可以在盲打后台用例中将当前准备请求的uri 和参数编码成base64,这样盲打后台解码后就知道是哪台机器哪个cgi触发的请求。
- 抓包分析发送的请求是不是由服务器的发送的,如果不是客户端发出的请求,则有可能是,接着找存在HTTP服务的内网地址
–从漏洞平台中的历史漏洞寻找泄漏的存在web应用内网地址
–通过二级域名暴力猜解工具模糊猜测内网地址
- 直接返回的Banner、title、content等信息
- 留意bool型SSRF
6.5、SSRF绕过姿势
更多见 SSRF绕过方法总结 、参考资料[3]
-
进制的转换绕过内网IP
可以使用一些不同的进制替代ip地址,从而绕过WAF。
例如 127.0.0.1 8进制:0177.0.0.1 16进制:0x7f.0.0.1 10进制:2130706433
其他各种指向127.0.0.1的地址
http://localhost/ # localhost就是代指127.0.0.1
http://0/ # 0在window下代表0.0.0.0,而在liunx下代表127.0.0.1
http://0.0.0.0/ # 0.0.0.0这个IP地址表示整个网络,可以代表本机 ipv4 的所有地址http://[0:0:0:0:0:ffff:127.0.0.1]/ # 在liunx下可用,window测试了下不行
http://[::]:80/ # 在liunx下可用,window测试了下不行
http://127。0。0。1/ # 用中文句号绕过
http://①②⑦.⓪.⓪.①
http://127.00000.00000.001/ # 0的数量多一点少一点都没影响,最后还是会指向127.0.0.1
-
利用HTTP基本身份认证的方式绕过
如果目标代码限制访问的域名只能为 http://www.xxx.com ,那么我们可以采用HTTP基本身份认证的方式绕过。即@:http://www.xxx.com@www.evil.com
-
利用302跳转绕过内网IP
(1)网络上存在一个很神奇的服务,网址为 http://xip.io,当访问这个服务的任意子域名的时候,都会重定向到这个子域名,举个例子:
当我们访问:http://127.0.0.1.xip.io/flag.php 时,实际*问的是http://127.0.0.1/1.php 。像这种网址还有http://nip.io,http://sslip.io 。
如下示例(flag.php仅能从本地访问):
(2)短地址跳转绕过,这里也给出一个网址 https://4m.cn/:
直接使用生成的短连接 https://4m.cn/FjOdQ就会自动302跳转到 http://127.0.0.1/flag.php 上,这样就可以绕过WAF了:
7、SSRF漏洞常用防御方法
通过上面的知道了SSRF漏洞最大的成因是URL完全可控,服务器会对用户构造的URL进行响应,所以从防御方面来看我们要禁止服务器随意响应用户构造的URL。
- 过滤。过滤返回的信息,如果web应用是去获取某一种类型的文件。那么在把返回结果展示给用户之前先验证返回的信息是否符合标准。
- 禁止跳转。防止用户利用服务器做跳板机
- 禁止不常用的协议,仅仅允许http和https请求。可以防止类似于file:///,gopher://,ftp://等引起的问题。
- 限制端口。只开放常用端口
- 统一返回的错误信息。这样用户就不可以根据返回信息判断端口情况。
- 使用DNS缓存技术防止DNS解析攻击
- 使用正则防止畸形绕过
8、XSS,CSRF,SSRF异同
XSS,CSRF,SSRF三种常见的Web服务端漏洞均是由于,服务器端对用户提供的可控数据过于信任或者过滤不严导致的。
不同点:
XSS是服务器对用户输入的数据没有进行足够的过滤,导致客户端浏览器在渲染服务器返回的html页面时,出现了预期值之外的 脚本语句被执行。
CSRF是服务器端没有对用户提交的数据进行随机值校验,且对http请求包内的refer字段校验不严,导致攻击者可以 利用用户的Cookie信息伪造用户请求发送至服务器。
SSRF是服务器对 用户提供的可控URL过于信任,没有对攻击者提供的RUL进行地址限制和足够的检测,导致攻击者可以以此为跳板攻击内网或其他服务器。
9、参考资料
[1] SSRF漏洞攻击原理及防御方案
[2] 了解SSRF,这一篇就足够了
[3] 干货 | SSRF漏洞利用总结