UEditor SSRF漏洞(JSP版本)分析与复现
前些时间测试的时候遇到了一个系统采用了UEditor编辑器,版本为1.4.3。已知该编辑器v1.4.3版本(jsp)存在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
方法。
1 | private boolean validHost ( String hostname ) { |
新增了对ip地址是否为内部地址的判断。而在v1.4.3中仅仅是做了是否为过滤的ip地址。
1 | private boolean validHost ( String 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
。
1 | public State capture ( String[] list ) { |
在invoke
中调用了capture
.
1 | public String invoke() { |
当调用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”时表示该主机存在,且对应的端口为开放状态。
代码如下:
1 | __Date__="20180524" |
由于返回的结果为
{"state": "SUCCESS", list: [{"state": "..."} ]}
并不能直接用json来解析,需要将list替换为”list”后才可以作为json来解析。当然也可以直接使用burp来测试。
在实际测试中的测试结果如下:
0x05 综合利用
对于这样的Bool型SSRF ,页面仅返回了状态,而没有更多别的信息,要想进一步利用,可以根据如下的思路:
内网探测->应用识别->攻击Payload->查看结果
内网探测
首先进行内网探测,查看内网开放的主机和端口。这里以本地为例。
执行命令:
python SSRF_Ueditor_jsp.py http://localhost:8088/ 192.168.135.155
1 | 192.168.135.155 80 is Open |
发现端口80 和 8080 开放,然后进行应用的识别。
应用识别
80端口由于没有可以识别的特征,所以未识别到应用的类型,而8080端口可以识别出来为tomcat服务器。
然后尝试查看是否存在Struts2漏洞。
攻击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
,是由于在抓取图片时会判断图片链接的后缀是否为图片格式。当然还有其他的写法,例如
然后再次利用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
查看结果
然后访问http://localhost:8088/ueditor/jsp/upload/image/20180525/1527181480175039672.png
查看是否攻击成功。
表明攻击成功。
0x06 总结
由于UEditor在v1.4.3之前没有加入对内部IP的限制,所以在使用抓取图片的功能时,造成SSRF漏洞。可以进行内网服务器的探测。然后根据内网服务器的特征(如/jmx-console/images/logo.gif
, /tomcat.png)
,判断其使用的组件,并猜测可能存在的漏洞,然后进行进一步的渗透。