S2-016调试学习

Posted nobgr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了S2-016调试学习相关的知识,希望对你有一定的参考价值。

前段时间发现某目标一系列S2-016的站,于是:

1、漏洞信息

官方说明:

技术图片

就是通过控制参数前缀redirect:action:redirectAction: 最后远程代码执行。官方的poc

2、搭建环境

ide用的是idea2019.3,用的jar包是vulhub里s2-016的jar包。

在idea选择创建struts2项目,之后再放入vulhub里s2-016的jar包,再配置一下xml,之后写个action(就是一个struts2的HelloWorld项目)。

技术图片

技术图片

POC 验证,redirect:${3*4}url编码redirect%3a%24%7b3*4%7d,执行了OGNL表达式:

技术图片

3、调试追踪

https://cwiki.apache.org/confluence/display/WW/S2-016 看,是 DefaultActionMapper 处理重定向前缀参数出的问题。在DefaultActionMapper构造方法里面,有new了一个PrefixTrie对象。

技术图片

这里选择重定向前缀redirect:也是REDIRECT_PREFIX的那个put方法下个断点。

技术图片

216行再下个断点,可以看到payload设置到了mapping的result里的location里面。

技术图片

往下走,到了handleSpecialParameters方法,功能大概是处理一下参数(参数唯一什么的):
技术图片技术图片

继续往下走,来到getMapping函数,先处理了一下action后缀名,发现之后调用了handleSpecialParameters,之后设置mapping的name和method然后return了。
技术图片

之后来到findActionMapping函数,最后返回了个ActionMapping对象。
技术图片

下来到了StrutsPrepareAndExecuteFilter过滤器,发现执行了execute.executeAction()函数。
技术图片

继续F8下去,来到ServletRedirectResult的doExecute函数,发现已经执行了payload(ognl表达式:${3*4},finalLocation值为执行结果,payload换为执行whoami命令行,finalLocation存储执行结果)。
技术图片

返回execute.executeAction()调试,f7跟进,发现执行了serviceAction方法。
技术图片

再f7跟进,一直f8下来,执行了result.execute()
技术图片

执行了父类StrutsResultSupport的 execute 方法,进入,可以看到payload在location。
技术图片

进入conditionalParse,发现执行了TextParseUtil.translateVariables之后return,继续往下,发现payload已经执行,parsedValue存储执行结果。
技术图片

继续看TextParseUtil.translateVariables函数

    public static Object translateVariables(char[] openChars, String expression, final ValueStack stack, final Class asType, final TextParseUtil.ParsedValueEvaluator evaluator, int maxLoopCount) {
        TextParseUtil.ParsedValueEvaluator ognlEval = new TextParseUtil.ParsedValueEvaluator() {
            public Object evaluate(String parsedValue) {
                Object o = stack.findValue(parsedValue, asType);
                if (evaluator != null && o != null) {
                    o = evaluator.evaluate(o.toString());
                }

                return o;
            }
        };
        TextParser parser = (TextParser)((Container)stack.getContext().get("com.opensymphony.xwork2.ActionContext.container")).getInstance(TextParser.class);
        XWorkConverter conv = (XWorkConverter)((Container)stack.getContext().get("com.opensymphony.xwork2.ActionContext.container")).getInstance(XWorkConverter.class);
        Object result = parser.evaluate(openChars, expression, ognlEval, maxLoopCount);
        return conv.convertValue(stack.getContext(), result, asType);
    }

再跟入parser.evaluate函数,发现执行evaluator.evaluate(var),此时var为`3*4
技术图片

一直往下,OgnlValueStack类的getValue函数获得值,最后由ognlUtil.getValue执行ognl表达式返回结果。
技术图片

三、参考文章

https://xz.aliyun.com/t/4603

https://www.jianshu.com/p/de165430e8a8

以上是关于S2-016调试学习的主要内容,如果未能解决你的问题,请参考以下文章

S2-052 漏洞复现

漏洞分析.Struts2

PHP代码-psysh调试代码片段工具

方便调试使用的代码片段

python学习笔记012——pdb调试

Struts S2-052漏洞利用方式实验解析(附EXP)