S2-057

0x01 环境创建

我使用IDEA进行Struts2的环境创建,这其中有坑。

首先便是Struts2必要jar包获取,最终采用了用解压的Struts-Blank.war部署在tomcat服务器的方式。这其中注意事项(也就是我踩过的坑)

  1. JAVA环境变量的JAVA_HOME和JRE_HOME必须设置好且正确,tomcat的startup.bat才不会报错

  2. IDEA创建Struts2项目后,正确配置JDK和Tomcat服务于IDEA,并且导包后是不行的,这里不会进行报错,但是IDEA中Tomcat日志会报错

    java.lang.ClassNotFoundException: org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter

    1574602211700

org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter是S2的核心过滤器,其配置在web.xml中

在第三方包环境是有这个java文件的:

1574602366031

百度得以解决,在IDEA中的WEB-INF中新建lib文件夹并再拷一份第三方lib过去

1574602452641

https://blog.csdn.net/lihuan6656/article/details/53502842

然后自己简单写了点demo跑起来之后看着这里的一个错误的demo配置https://www.freebuf.com/column/208925.html

1574602643216

环境已经搭建完成。

0x02 进还是不进?

在调试过程中多次遇到一个包进不去的情况,原因是因为该包没有被导入该对象属于tomcat底层对象如request

1574824039070

若在对request.setAttribut()使用了F7将进入org.apache.catalina这个包,可是我们只能看到Frame界面其行数但是游标不会进入该包,也看不到其代码。

解决:

1574823539921

可以看到,其归属于tomcat的lib包,在执行过程中tomcat能够进行解析,这就是为什么能执行但是IDEA无法跟进的原因。同样jdk的jar包也是一样,不过只要有该jar导入了IDEA便能让IDEA去反编译它。因此,调试过程中即使使用pom构建方式千万别忘了导入JDK和tomcat的lib包

1574823600298

1574823673569

1574823846537

这样便能跟进tomcat层的jar包了

PS:只能用该种该方式导入,否则如果是在pom库找到的jar包会因版本和代码不一致等问题产生编译错误,IDEA优先选择导入的jar包。程序运行就会报错。

TIPS:除了跟进。还有一种很好的方式可以避免该错误:不进,如果不需要跟到tomcat层的问题。也就是该漏洞不由tomcat产生。推荐使用这种方式。思考有两种实现方式:

  1. 在request的方法同时不要使用F7而使用F8,这样将不会进入方法体或者下断点使用F9
  2. 在调试器设置选择绕过一些jar包(推荐):

1574824760967

0x03开始调试

根据漏洞描述将端点打在了struts2-core-2.3.24-sources.jar!\org\apache\struts2\dispatcher\mapper\DefaultActionMapper.java#parseNameAndNamespace ↓

1574844367174

由于设置了不进入tomcat底层类,可以使用F7调试、不过千万不能忘记从哪里进去的,这样找不到出口还可以用断点+F9补救 ↑

恶意数据存入namespace和mapping ↓

1574844798241

继续F7下去 到达#getMapping方法,其调用的刚刚断点的#parseNameAndNamespace方法: ↓

1574845450229

我们看到这个#handleSpecialParameters方法,考虑是否跟进,语义 处理特殊参数 可跟可不跟,无法确定这个特殊参数会不会处理我们的表达式。节省时间下个断点在265行,再下个在266行,不调用跟踪先。然后F9直接跳断点忽略该方法的跟进。 ↑

然后是266的parseActionName,明显是指引action名字,简单看一下,因为我们如果又要使用断点跳过,在return还要通过useage得到返回 ↓

1574847016917

parseActionName处理看一下有!的情况 ↑

然后返回,上一级继续Return到达了org\apache\struts2\dispatcher\ng\PrepareOperations.java#findActionMapping ↓

1574847239800

这个#findActionMapping就是查看了下前文mapping取到了没,没取到就在值栈中去取,值栈的知识不再赘述的,其是Struts的上下文。 ↓

1574847379519

传入三参数的#findActionMapping,F7一下回到了org\apache\struts2\dispatcher\ng\filter\StrutsPrepareFilter.java#doFilter这里是过滤器处理的类,就在之前调用了#findActionMapping,所以#findActionMapping结束回到了#doFilter ↓

1574847630911

下一步必然执行chain.doFilter(FilterChain) F7一下 ↑

1574847769047

遗憾的来到了这个catalina(tomcat底层包),刚刚那个Step设置有待商榷,解救一下,断点F9

目前位于D:\environment\apache-tomcat-7.0.96\lib\catalina.jar!\org\apache\catalina\core\ApplicationFilterChain.class#doFilter ↑

这里不是我们想看的内容,几次F8一下,我们到了struts2-core-2.3.24-sources.jar!\org\apache\struts2\dispatcher\ServletActionRedirectResult.java#execute ↓

1574848072357

actionName = conditionalParse(actionName, invocation);//使用F8一下,因为actionName和invocation没有我们的ognl表达式 ↑

下面便调了namespace = invocation.getProxy().getNamespace();去取namespace ↓

1574848238718

下面一点,这里不确定是不是,语义分析或者去实现类看下或者F7进去看一下两种方式排查一下并不是执行ognl的地方 ↓

1574848364426

我选择了F7跟进的方式,178和180跟完了都不是 ↓

1574860920812

跟入父类execute执行方法,传入invocation ↑

1574860990012

再调父类 ↑

org\apache\struts2\dispatcher\StrutsResultSupport.java#execute最终执行,传入invocation参数 ↓

1574861111565

再F7跟进一下,到达本类的#conditionalParse方法: ↓

1574861845393

传入了param参数,跟进下TextParseUtil.translateVariables ↑

1574861930644

调了新的#translateVariables方法,构造了一个数组进去,然后又是一个重调用同名不同参函数,传了个最大值进去。 ↑

1574862318352

然后在171行,evaluate有点可疑,跟进下进了com\opensymphony\xwork2\util\OgnlTextParser.java#evaluate,在前面下个断点别跟丢了 ↑

执行了几步,这里就是OGNL值执行地(OgnlTextParser#evaluate) ↓

1574862748988

至此,传入的ognl表达式被com\opensymphony\xwork2\util\OgnlTextParser.java#evaluate予以解析。

本文标题:S2-057

文章作者:

发布时间:2019年12月15日 - 10:33:12

最后更新:2019年12月31日 - 14:10:16

原始链接:http://laker.xyz/2019/12/15/S2-057/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。