CVE于2010年8月份、2012年1月份,分别发布了struts2框架几个远程执行漏洞,说到这几个远程执行漏洞,无一不与OGNL有关,当然,这并不意味着OGNL问题重重,相反,正是作为一款非常优秀的表达式语言,OGNL才被Struts2/XWork所整合使用。OGNL的功能是强大的,解决了MVC模式页面与对象之间的不匹配性,还支持方法调用。在struts2中,请求访问action的所有参数都被当作OGNL表达式来对待,表达式将被写入到ValueStack且被解释执行,上面提到了OGNL具有丰富的功能,所以必须对写入ValueStack的内容进行正确的限制,不幸的是,struts2框架疏忽了这点,所以导致了注入Java代码的漏洞。除请求参数外,cookie在某种情况,也会写入到ValueStack。
下面简单介绍下struts2这几个远程执行漏洞:
正如题目所示,本文就0392漏洞进行分析,笔者搭建了一个WEB应用开发环境,工程中直接引用struts2/xwork源代码,以便跟踪调试,读者有兴趣的话,可以采用同样的方式对其他几个漏洞进行分析。
1.搭建开发环境
1)、下载struts2
按CVE-2012-0392漏洞介绍,该漏洞存在于struts2.3.1.1之前的版本,笔者选择下载了struts2.2.1。其中包含了apps(几个web应用包)、lib(引用的库文件)、src(struts2/xwork源代码)、docs(文档)。
2)、创建web工程
将apps/struts2-blank-2.2.1.war解压,使用myeclipse指定解压后的目录创建web工程。
以下几点需要注意:
拷贝struts2/xwork源代码、资源文件至web应用中的srcWeb工程直接引用struts2/xwork源代码,需要删除lib目录中的
struts2-core-2.2.1.jar、xwork-core-2.2.1.jar,另外,xwork-core-2.2.1.jar中包含了对第三方文件的扩展,但是并未提供该部分源代码,所以不能彻底删除该jar,需要保留这些扩展的class文件,否则编译时会报classnotfound。
3)、部署struts2-blank-2.2.1
笔者使用的应用服务器为apache-tomcat-6.0.29,为了方便开发调试,最好采用部署目录的方式,部署目录直接指定为开发目录。
2.漏洞分析
环境准备好了,现在我们进入正题。
2.1.走读CookieInterceptor.java
通过阅读Cookie拦截器源代码
(org\apache\struts2\interceptor\CookieInterceptor.java),我们发现,拦截器对cookie(name、value)值做了白名单限制(通过struts配置文件进行白名单配置,name白名单、value白名单分别对应cookiesNameSet、cookiesValueSet),CookieInterceptor大概执行流程见图-1。
NVD关于该CVE-2012-0392漏洞的描述是不清晰的,很容易引起误解,描述里提到,struts2.3.1.1之前版本的CookieInterceptor没有使用参数名称白名单,实际上是有的,只是struts把白名单的制定权交在里struts使用者的手里——通过配置文件定制,如果struts使用者对此没有充分的了解,很可能将此忽略或者制定一个安全防护无效的白名单。
配置说明:
CookiesName白名单定义为“*”,即允许任何值CookiesValue白名单定义为”1、2”修改完配置文件,记得redeploy,笔者通常在myeclipse中重启tomcat。
我们先做个简单的测验,如下修改CookieInterceptor.java,然后访问网址,成功弹出计算器,通过这种方法,也可以很方便调试我们编写的OGNL表达式。测试完毕请回退源代码。
2.3.构造请求
借助burpsuite的repeater功能,构造如下请求并发送
之前的小测验非常顺利,可是这次只是收到了响应,却没有弹出计算器,重新发了几次,依然静悄悄,还是看看后台到底发生了什么吧,进入调试模式。
调试模式下监控request请求,见图-2红色圈中部分,cookie已经被截断,计算器自然是弹不出来了。request从哪里来?从客户端到容器,再从容器到Cookie拦截器,中间经过容器处理了一次,那么是不是tomcat在处理请求时丢弃了部分数据,我们换个商业应用服务器weblogic10.3再试一下,此时监控request请求对象,见图-3红色圈中部分,cookie完整正如我们发送的那样,当然,java代码也成功执行,弹出了计算器。至于tomcat6.0.29为什么会截断cookie,本文不做讨论,有兴趣的读者可以研究一下。
2.4.Struts2.3.1.1是如何修复0392号漏洞的?
CookieInterceptor.java增加了cookiename正则表达式校验,正则表达式如下:privatestaticfinalStringACCEPTED_PATTERN="[a-zA-Z0-9\\.\\]\\[_'\\s]+";
本文内容所提及均为本地测试或经过目标授权同意,旨在提供教育和研究信息,内容已去除关键敏感信息和代码,以防止被恶意利用。作者不鼓励或支持任何形式的非法破解行为。