0x01Brief Descriptionhtml
最近面试几家公司,不少都问到了s2漏洞的原理,以前调试分析过java反序列化的漏洞,以为s2漏洞应该不会太难,今天就分析了一下,而后发现其实漏洞的原理不难,可是搭建j2ee调试的环境花了将近半天的时间QAQ.java
Struts 是Apache软件基金会(ASF)赞助的一个开源项目,经过采用JavaServlet/JSP技术,实现基于Java EEWeb应用的MVC设计模式的应用框架,Struts 2是Struts的下一代产品,是在 Struts 1和WebWork的技术基础上进行了合并的全新的Struts 2框架。
Struts2框架普遍应用于政府、公安、交通、金融行业和运营商的网站建设,做为网站开发的底层模板使用。Struts2漏洞,主要指的是J2EE开源框架struts2出现的命令执行漏洞,危害巨大,可致使远程执行任意系统命令,进而获取系统控制权,数据库控制权,致使信息泄露。全部使用struts2框架开发的系统都会受到影响。(copy from Link),以前大学的时候学习过,工做以后就不多接触过了,基本上就是用用工具测试一下s2的漏洞。git
OGNL是Object-Graph Navigation Language的缩写,它是一种功能强大的表达式语言,经过它简单一致的表达式语法,能够存取对象的任意属性,调用对象的方法,遍历整个对象的结构图,实现字段类型转化等功能。它使用相同的表达式去存取对象的属性。OGNL通常是配合struts框架一块儿使用的,表达式语言通常是为了方便数据的存取所自定义的语言,然而邪恶攻击者却在Struts2中Ognl执行Java代码,一样的Elasticsearch能够用Groovy能够实现任意Java功能。更多ognl的介绍可参考 Link百科。github
0x02 s2-032漏洞分析面试
s2-032漏洞影响的s2版本:Struts 2.3.20 - Struts 2.3.28 (except 2.3.20.3 and 2.3.24.3)数据库
官方的公告:https://struts.apache.org/docs/s2-032.htmlapache
这次漏洞存在于struts2的动态方法引用功能。只要在struts2配置文件中开启该功能,就可能被利用。设计模式
在配置了 Struts2 DMI 为 True 的状况下,可使用 method:<name> Action 前缀去调用声明为 public 的函数,DMI 的相关使用方法可参考官方介绍(Dynamic Method Invocation),这个 DMI 的调用特性其实一直存在,只不过在低版本中 Strtus2 不会对 name 方法值作 OGNL 计算,而在高版本中会。因此只要找到目标应用中有效的 Action 例如 index.action,那么直接使用 DMI 在 method: 后面带上须要执行 OGNL 表达式便可。
好比这样的ognl 表达式: #_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,#f=@java.lang.Runtime@getRuntime().exec(#parameters.cmd[0]),#f.close&cmd=open /Applications/Calculator.app 经过反射调用(关于java的反射调用能够参考以前的一篇文章Link)Runtime类的exec方法进行命令执行,这里是打开计算器的操做。session
ognl表达式分析:app
@符号的做用:在对静态方法或者变量访问的时候使用@class@member或者@class@method(args),因此这里就是经过反射调用了Runtime class的exec method(后者)。
一、“#”符号有三种用途:
(1)、访问非根对象(struts中值栈为根对象)如OGNL上下文和Action上下文,#至关于ActionContext.getContext();下表有几个ActionContext中有用的属性:
parameters
包含当前HTTP请求参数的Map
#parameters.id[0]做用至关于request.getParameter("id")
request
包含当前HttpServletRequest的属性(attribute)的Map
#request.userName至关于request.getAttribute("userName")
session
包含当前HttpSession的属性(attribute)的Map
#session.userName至关于session.getAttribute("userName")
application
包含当前应用的ServletContext的属性(attribute)的Map
#application.userName至关于application.getAttribute("userName")
注:attr 用于按request > session > application顺序访问其属性(attribute),#attr.userName至关于按顺序在以上三个范围(scope)内读取 userName属性,直到找到为止。用于过滤和投影(projecting)集合,如books.{?#this.price<100};构造 Map,如#{'foo1':'bar1', 'foo2':'bar2'}。
(2)、用于过滤和投影(projecting)集合,如: books.{?#this.price>35}
books.{?#this.price>35}
(3)、构造Map,如: #{'foo1':'bar1', 'foo2':'bar2'}
#{'foo1':'bar1', 'foo2':'bar2'}这种方式经常使用在给radio或select、checkbox等标签赋值上。若是要在页面中取一个map的值能够这样写:
<s:property value="#myMap['foo1']"/>
<s:property value="#myMap['foo1']"/>
将_memberAccess赋值成DEFAULT_MEMBER_ACCESS是为绕过SecurityMemberAccess为false的限制。
简单的payload分析以后,咱们来调试一下代码。
首先添加存在漏洞版本的struts2包(这里使用的是2.3.28)以及对应的source Attachement(为方便调试查看到源代码)。以下图所示。
而后呢,构造一个有效的Action,这里就不实现具体的功能。
struts.xml中配置action对应的处理方法。
下一步就是下断点,断点下在哪里?参考他人的文章,聪明的咱们天然就下在了该下的地方,让它在该断下的地方断下(这不废话么。。)
1.在DefaultActionMapper.java中,DefaultActionMapper方法将method的值存入到ActionMapping的method属性中。
2.在DefaultActionProxyFactory.java中,DefaultActionProxy方法将ActionMapping的method值通过escapeEcmaScript,escapeHtml4过滤后传到了ActionProxy的method属性中。
3.最后DefaultActionInvocation.java中的invokeAction将ActionProxy的method值放入到了ognlUtil.getValue()方法中执行表达式。
最终,执行完这一步就执行了咱们的命令。
0x03 关于escapeHtml4的疑问
咱们注意到在整个参数的传递过程当中有这样一个函数escapeHtml4的函数会对传输的参数进行处理,查看文档能够知道这个函数的做用是对特殊的符号进行过滤,那么咱们的payload中有那么多的特殊符号,像#@,([])/&._= 按理说应该是会被html encode的啊
关于html4 entities 可参考 https://www.w3schools.com/charsets/ref_html_entities_4.asp
为什么还能成功,咱们尝试在payload中添加双引号,而后再跟一下执行过程。
http://localhost:8080/Demo/index.action?method:#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS"",#f=@java.lang.Runtime@getRuntime().exec(#parameters.cmd[0]),#f.close&cmd=open /Applications/Calculator.app
跟踪发现,双引号在这里确实是进行了html encode
为什么&不会呢?在此猜想应该是#$等符号是ognl里面的一些符号,因此这个函数并不会对这些符号进行htmlencode。
0x03Diff Patch
可见,修复的版本在对method参数进行了cleanActionName的过滤,具体的过滤是
protected Pattern allowedActionNames = Pattern.compile(“[a-zA-Z0-9._!/\\-]*”);,这样咱们payload中的]./等就被过滤掉了。
0x04 Reference
1.http://rickgray.me/2016/05/06/review-struts2-remote-command-execution-vulnerabilities.html
2.http://dogewatch.github.io/2016/04/29/struts2/
3.http://blog.topsec.com.cn/ad_lab/apache-structs2-s2-032%E6%8A%80%E6%9C%AF%E5%88%86%E6%9E%90%E5%8F%8A%E6%BC%8F%E6%B4%9E%E6%A3%80%E6%B5%8B%E8%84%9A%E6%9C%AC/
4.http://www.cnblogs.com/LittleHann/p/4606891.html