Example #1
0
 def success(self, msg: ResultObject):
     if isinstance(msg, ResultObject):
         msg = msg.output()
     elif isinstance(msg, dict):
         pass
     else:
         raise PluginCheckError('self.success() not ResultObject')
     KB.output.success(msg)
Example #2
0
    def audit(self):

        callbaks = ["callback", "cb", "json"]
        params = self.requests.params
        isBreak = True
        for p in params.keys():
            if p.lower() in callbaks:
                isBreak = False
                break
        if isBreak:
            return
        result = self.check_sentive_content(self.response.text)
        if not result:
            return
        p = urlparse(self.requests.url)
        fake_domain = "{}://{}".format(p.scheme, p.netloc) + random_str(4,
                                                                        string.ascii_lowercase + string.digits) + ".com/"
        headers = self.requests.headers
        headers["Referer"] = fake_domain
        req = requests.get(self.requests.url, headers=headers)
        result2 = self.check_sentive_content(req.text)
        if not result2:
            return
        result = ResultObject(self)
        result.init_info(self.requests.url, "jsonp敏感信息", VulType.SENSITIVE)
        result.add_detail("payload探测", self.requests.raw, self.response.raw,
                          "发现敏感信息:{}".format(repr(result2)), "", "", PLACE.GET)
        self.success(result)
Example #3
0
    def audit(self):

        vul_reg = [r"(\.html\([^\)]\))"]

        if self.check_jquery():

            for _ in vul_reg:
                text = re.findall(_, self.response.text, re.M | re.I)
                issuc = False

                if text:
                    for t in set(text):
                        ignores = ['function']
                        iscontinue = True

                        for i in ignores:
                            if i in t:
                                iscontinue = False
                                break
                        if not iscontinue:
                            continue

                        result = ResultObject(self)
                        result.init_info(self.requests.url, "页面中存在.HTML绕过",
                                         VulType.SENSITIVE)
                        result.add_detail("payload探测", self.requests.raw,
                                          self.response.raw,
                                          "根据正则:{} 发现敏感信息:{}".format(_, text),
                                          "", "", PLACE.GET)
                        self.success(result)
                        issuc = True
                        break

                if issuc:
                    break
Example #4
0
    def audit(self):
        if self.requests.suffix != ".js":
            return

        regx = [
            # 匹配url
            # r'(\b|\'|")(?:http:|https:)(?:[\w/\.]+)?(?:[a-zA-Z0-9_\-\.]{1,})\.(?:php|asp|ashx|jspx|aspx|jsp|json|action|html|txt|xml|do)(\b|\'|")',
            # 匹配邮箱
            r'[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)+',
            # 匹配token或者密码泄露
            # 例如token = xxxxxxxx, 或者"apikey" : "xssss"
            r'\b(?:secret|secret_key|token|secret_token|auth_token|access_token|username|password|aws_access_key_id|aws_secret_access_key|secretkey|authtoken|accesstoken|access-token|authkey|client_secret|bucket|email|HEROKU_API_KEY|SF_USERNAME|PT_TOKEN|id_dsa|clientsecret|client-secret|encryption-key|pass|encryption_key|encryptionkey|secretkey|secret-key|bearer|JEKYLL_GITHUB_TOKEN|HOMEBREW_GITHUB_API_TOKEN|api_key|api_secret_key|api-key|private_key|client_key|client_id|sshkey|ssh_key|ssh-key|privatekey|DB_USERNAME|oauth_token|irc_pass|dbpasswd|xoxa-2|xoxrprivate-key|private_key|consumer_key|consumer_secret|access_token_secret|SLACK_BOT_TOKEN|slack_api_token|api_token|ConsumerKey|ConsumerSecret|SESSION_TOKEN|session_key|session_secret|slack_token|slack_secret_token|bot_access_token|passwd|api|eid|sid|api_key|apikey|userid|user_id|user-id)["\s]*(?::|=|=:|=>)["\s]*[a-z0-9A-Z]{8,64}"?',
            # 匹配IP地址
            r'\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b',
            # 匹配云泄露
            r'[\w]+\.cloudfront\.net',
            r'[\w\-.]+\.appspot\.com',
            r'[\w\-.]*s3[\w\-.]*\.?amazonaws\.com\/?[\w\-.]*',
            r'([\w\-.]*\.?digitaloceanspaces\.com\/?[\w\-.]*)',
            r'(storage\.cloud\.google\.com\/[\w\-.]+)',
            r'([\w\-.]*\.?storage.googleapis.com\/?[\w\-.]*)',
            # 匹配手机号
            r'(?:139|138|137|136|135|134|147|150|151|152|157|158|159|178|182|183|184|187|188|198|130|131|132|155|156|166|185|186|145|175|176|133|153|177|173|180|181|189|199|170|171)[0-9]{8}'
            # 匹配域名
            r'((?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+(?:biz|cc|club|cn|com|co|edu|fun|group|info|ink|kim|link|live|ltd|mobi|net|online|org|pro|pub|red|ren|shop|site|store|tech|top|tv|vip|wang|wiki|work|xin|xyz|me))',
        ]
        for _ in regx:
            texts = re.findall(_, self.response.text, re.M | re.I)
            issuc = False
            if texts:
                for text in set(texts):
                    ignores = [
                        'function', 'encodeURIComponent', 'XMLHttpRequest'
                    ]
                    iscontinue = True

                    for i in ignores:
                        if i in text:
                            iscontinue = False
                            break
                    if not iscontinue:
                        continue

                    result = ResultObject(self)
                    result.init_info(self.requests.url, "js文件中存在敏感信息",
                                     VulType.SENSITIVE)
                    result.add_detail("payload探测", self.requests.raw,
                                      self.response.raw,
                                      "根据正则:{} 发现敏感信息:{}".format(_, text), "",
                                      "", PLACE.GET)
                    self.success(result)
                    issuc = True
                    break
            if issuc:
                break
Example #5
0
 def audit(self):
     if self.requests.suffix.lower() == '.js':
         new_url = self.requests.url + ".map"
         req = requests.get(new_url, headers=self.requests.headers)
         if req.status_code == 200 and 'webpack:///' in req.text:
             result = ResultObject(self)
             result.init_info(self.requests.url, "webpack源文件泄漏",
                              VulType.SENSITIVE)
             result.add_detail("payload探测", req.reqinfo,
                               generateResponse(req), "webpack:/// 在返回文本中",
                               "", "", PLACE.GET)
             self.success(result)
Example #6
0
 def new_result(self) -> ResultObject:
     return ResultObject(self)
Example #7
0
    def audit(self):
        plainArray = [
            "; for 16-bit app support",
            "[MCI Extensions.BAK]",
            "# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.",
            "# localhost name resolution is handled within DNS itself.",
            "[boot loader]"
        ]

        regexArray = [
            '(Linux+\sversion\s+[\d\.\w\-_\+]+\s+\([^)]+\)\s+\(gcc\sversion\s[\d\.\-_]+\s)',
            '(root:\w:\d*:)',
            "System\.IO\.FileNotFoundException: Could not find file\s'\w:",
            "System\.IO\.DirectoryNotFoundException: Could not find a part of the path\s'\w:",
            "<b>Warning<\/b>:\s\sDOMDocument::load\(\)\s\[<a\shref='domdocument.load'>domdocument.load<\/a>\]:\s(Start tag expected|I\/O warning : failed to load external entity).*(Windows\/win.ini|\/etc\/passwd).*\sin\s<b>.*?<\/b>\son\sline\s<b>\d+<\/b>",
            "(<web-app[\s\S]+<\/web-app>)",
            "Warning: fopen\(",
            "open_basedir restriction in effect"
        ]
        iterdatas = self.generateItemdatas()
        payloads = self.generate_payloads()

        for origin_dict, positon in iterdatas:
            payloads = self.paramsCombination(origin_dict, positon, payloads)
            for key, value, new_value, payload in payloads:
                r = self.req(positon, payload)
                if not r:
                    continue
                html1 = r.text
                for plain in plainArray:
                    if plain in html1:
                        result = ResultObject(self)
                        result.init_info(self.requests.url, "目录穿越导致任意文件被读取", VulType.PATH_TRAVERSAL)
                        result.add_detail("payload探测", r.reqinfo, generateResponse(r),
                                          "探测payload:{},并发现回显{}".format(payload, plain), key, new_value, positon)
                        self.success(result)
                        return
                for regex in regexArray:
                    if re.search(regex, html1, re.I | re.S | re.M):
                        result = ResultObject(self)
                        result.init_info(self.requests.url, "目录穿越导致任意文件被读取", VulType.PATH_TRAVERSAL)
                        result.add_detail("payload探测", r.reqinfo, generateResponse(r),
                                          "探测payload:{},并发现正则回显{}".format(payload, regex), key, new_value, positon)
                        self.success(result)
                        return
Example #8
0
File: xss.py Project: dycsy/w13scan
 def init(self):
     self.result = ResultObject(self)
     self.result.init_info(self.requests.url, "XSS脚本注入", VulType.XSS)
Example #9
0
File: xss.py Project: dycsy/w13scan
class W13SCAN(PluginBase):
    name = 'XSS语义化探测插件'

    def init(self):
        self.result = ResultObject(self)
        self.result.init_info(self.requests.url, "XSS脚本注入", VulType.XSS)

    def getSSTIPayload(self, randint1=444, randint2=666) -> list:
        '''
        顺便检测下模板注入~
        return ['{123*1111}', '<%=123*1111%>', '#{123*1111}', '${{123*1111}}', '{{123*1111}}', '{{= 123*1111}}', '<# 123*1111>', '{@123*1111}', '[[123*1111]]', '${{"{{"}}123*1111{{"}}"}}']

        :return: list
        '''
        r = []
        payloads = [
            "{%d*%d}",
            "<%%=%d*%d%%>",
            "#{%d*%d}",
            "${{%d*%d}}",
            "{{%d*%d}}",
            "{{= %d*%d}}",
            "<# %d*%d>",
            "{@%d*%d}",
            "[[%d*%d]]",
            "${{\"{{\"}}%d*%d{{\"}}\"}}",
        ]
        for item in payloads:
            r.append(item % (randint1, randint2))
        return r

    def audit(self):

        parse_params = set(getParamsFromHtml(self.response.text))
        resp = self.response.text
        params_data = {}
        self.init()
        iterdatas = []
        if self.requests.method == HTTPMETHOD.GET:
            parse_params = (parse_params | TOP_RISK_GET_PARAMS) - set(
                self.requests.params.keys())
            for key in parse_params:
                params_data[key] = random_str(6)
            params_data.update(self.requests.params)
            resp = requests.get(self.requests.netloc,
                                params=params_data,
                                headers=self.requests.headers).text
            iterdatas = self.generateItemdatas(params_data)
        elif self.requests.method == HTTPMETHOD.POST:
            parse_params = (parse_params) - set(self.requests.post_data.keys())
            for key in parse_params:
                params_data[key] = random_str(6)
            params_data.update(self.requests.post_data)
            resp = requests.post(self.requests.url,
                                 data=params_data,
                                 headers=self.requests.headers).text
            iterdatas = self.generateItemdatas(params_data)

        for origin_dict, positon in iterdatas:
            # 先不支持uri上的xss,只支持get post cookie上的xss
            if positon == PLACE.URI:
                continue
            for k, v in origin_dict.items():
                v = unquote(v)
                if v not in resp:
                    continue
                data = copy.deepcopy(origin_dict)
                # 探测回显
                xsschecker = "0x" + random_str(6, string.digits + "abcdef")
                data[k] = xsschecker
                r1 = self.req(positon, data)

                if not re.search(xsschecker, r1.text, re.I):
                    continue
                html_type = r1.headers.get("Content-Type", "").lower()

                XSS_LIMIT_CONTENT_TYPE = conf.XSS_LIMIT_CONTENT_TYPE
                if XSS_LIMIT_CONTENT_TYPE and 'html' not in html_type:
                    continue

                # 反射位置查找
                locations = SearchInputInResponse(xsschecker, r1.text)

                if len(locations) == 0:
                    # 找不到反射位置,找下自己原因?
                    flag = random_str(5)
                    payload = "<{}//".format(flag)
                    data[k] = payload
                    req = self.req(positon, data)
                    if payload in req.text:
                        self.result.add_detail(
                            "html代码未转义", req.reqinfo, generateResponse(req),
                            "可使用<svg onload=alert`1`// 进行攻击测试,注意返回格式为:" +
                            html_type, k, data[k], positon)

                for item in locations:
                    _type = item["type"]
                    details = item["details"]

                    if _type == "html":
                        if details["tagname"] == "style":
                            payload = "expression(a({}))".format(
                                random_str(6, string.ascii_lowercase))
                            data[k] = payload
                            req = self.req(positon, data)
                            _locations = SearchInputInResponse(
                                payload, req.text)
                            for _item in _locations:
                                if payload in _item["details"][
                                        "content"] and _item["details"][
                                            "tagname"] == "style":
                                    self.result.add_detail(
                                        "IE下可执行的表达式", req.reqinfo,
                                        generateResponse(req.text),
                                        "IE下可执行的表达式 expression(alert(1))", k,
                                        data[k], positon)
                                    break
                        flag = random_str(7)
                        payload = "</{}><{}>".format(
                            random_upper(details["tagname"]), flag)
                        truepayload = "</{}>{}".format(
                            random_upper(details["tagname"]),
                            "<svg onload=alert`1`>")
                        data[k] = payload
                        req = self.req(positon, data)
                        _locations = SearchInputInResponse(flag, req.text)
                        for i in _locations:
                            if i["details"]["tagname"] == flag:
                                self.result.add_detail(
                                    "html标签可被闭合", req.reqinfo,
                                    generateResponse(req),
                                    "<{}>可被闭合,可使用{}进行攻击测试,注意返回格式为:{}".format(
                                        details["tagname"], truepayload,
                                        html_type), k, data[k], positon)
                                break
                    elif _type == "attibute":
                        if details["content"] == "key":
                            # test html
                            flag = random_str(7)
                            payload = "><{}".format(flag)
                            truepayload = "><svg onload=alert`1`>"
                            data[k] = payload
                            req = self.req(positon, data)
                            _locations = SearchInputInResponse(flag, req.text)
                            for i in _locations:
                                if i["details"]["tagname"] == flag:
                                    self.result.add_detail(
                                        "html标签可被闭合", req.reqinfo,
                                        generateResponse(req),
                                        "<{}>可被闭合,可使用{}进行攻击测试,注意返回格式为:{}".
                                        format(details["tagname"], truepayload,
                                               html_type), k, data[k], positon)
                                    break
                            # test attibutes
                            flag = random_str(5)
                            payload = flag + "="
                            data[k] = payload
                            req = self.req(positon, data)
                            _locations = SearchInputInResponse(flag, req.text)
                            for i in _locations:
                                for _k, v in i["details"]["attibutes"]:
                                    if _k == flag:
                                        self.result.add_detail(
                                            "可自定义任意标签事件", req.reqinfo,
                                            generateResponse(req),
                                            "可以自定义类似 'onmouseover=prompt(1)'的标签事件,注意返回格式为:"
                                            + html_type, k, payload, positon)
                                        break
                        else:
                            # test attibutes
                            flag = random_str(5)
                            for _payload in ["'", "\"", ""]:
                                payload = _payload + flag + "=" + _payload
                                truepayload = "{payload} onmouseover=prompt(1){payload}".format(
                                    payload=_payload)
                                data[k] = payload
                                req = self.req(positon, data)
                                _occerens = SearchInputInResponse(
                                    flag, req.text)
                                for i in _occerens:
                                    for _k, _v in i["details"]["attibutes"]:
                                        if _k == flag:
                                            self.result.add_detail(
                                                "引号可被闭合,可使用其他事件造成xss",
                                                req.reqinfo,
                                                generateResponse(req),
                                                "可使用payload:{},注意返回格式为:{}".
                                                format(truepayload, html_type),
                                                k, payload, positon)
                                            break
                            # test html
                            flag = random_str(7)
                            for _payload in [r"'><{}>", "\"><{}>"]:
                                payload = _payload.format(flag)
                                data[k] = payload
                                req = self.req(positon, data)
                                _occerens = SearchInputInResponse(
                                    flag, req.text)
                                for i in _occerens:
                                    if i["details"]["tagname"] == flag:
                                        self.result.add_detail(
                                            "html标签可被闭合", req.reqinfo,
                                            generateResponse(req),
                                            "可测试payload:{}".format(
                                                _payload.format(
                                                    "svg onload=alert`1`")) +
                                            ",返回格式为:" + html_type, k, data[k],
                                            positon)
                                        break
                            # 针对特殊属性进行处理
                            specialAttributes = [
                                'srcdoc', 'src', 'action', 'data', 'href'
                            ]  # 特殊处理属性
                            keyname = details["attibutes"][0][0]
                            tagname = details["tagname"]
                            if keyname in specialAttributes:
                                flag = random_str(7)
                                data[k] = flag
                                req = self.req(positon, data)
                                _occerens = SearchInputInResponse(
                                    flag, req.text)
                                for i in _occerens:
                                    if len(i["details"]["attibutes"]) > 0 and i["details"]["attibutes"][0][
                                        0] == keyname and \
                                            i["details"]["attibutes"][0][1] == flag:
                                        truepayload = flag
                                        if i["details"]["attibutes"][0][
                                                0] in specialAttributes:
                                            truepayload = "javascript:alert(1)"

                                        self.result.add_detail(
                                            "值可控", req.reqinfo,
                                            generateResponse(req),
                                            "{}的值可控,可能被恶意攻击,payload:{},注意返回格式为:{}"
                                            .format(keyname, truepayload,
                                                    html_type), k, data[k],
                                            positon)
                                        break
                            elif keyname == "style":
                                payload = "expression(a({}))".format(
                                    random_str(6, string.ascii_lowercase))
                                data[k] = payload
                                req = self.req(positon, data)
                                _occerens = SearchInputInResponse(
                                    payload, req.text)
                                for _item in _occerens:
                                    if payload in str(_item["details"]) and len(_item["details"]["attibutes"]) > 0 and \
                                            _item["details"]["attibutes"][0][0] == keyname:
                                        self.result.add_detail(
                                            "IE下可执行的表达式", req.reqinfo,
                                            generateResponse(req.text),
                                            "IE下可执行的表达式 payload:expression(alert(1))",
                                            k, data[k], positon)
                                        break
                            elif keyname.lower() in XSS_EVAL_ATTITUDES:
                                # 在任何可执行的属性中
                                payload = random_str(6, string.ascii_lowercase)
                                data[k] = payload
                                req = self.req(positon, data)
                                _occerens = SearchInputInResponse(
                                    payload, req.text)
                                for i in _occerens:
                                    _attibutes = i["details"]["attibutes"]
                                    if len(_attibutes) > 0 and _attibutes[0][
                                            1] == payload and _attibutes[0][
                                                0].lower() == keyname.lower():
                                        self.result.add_detail(
                                            "事件的值可控", req.reqinfo,
                                            generateResponse(req),
                                            "{}的值可控,可能被恶意攻击,注意返回格式为:{}".format(
                                                keyname, html_type), k,
                                            data[k], positon)
                                        break
                    elif _type == "comment":
                        flag = random_str(7)
                        for _payload in ["-->", "--!>"]:
                            payload = "{}<{}>".format(_payload, flag)
                            truepayload = payload.format(
                                _payload, "svg onload=alert`1`")
                            data[k] = payload
                            req = self.req(positon, data)
                            _occerens = SearchInputInResponse(flag, req.text)
                            for i in _occerens:
                                if i["details"]["tagname"] == flag:
                                    self.result.add_detail(
                                        "html注释可被闭合", req.reqinfo,
                                        generateResponse(req),
                                        "html注释可被闭合 测试payload:{},注意返回格式为:{}".
                                        format(truepayload,
                                               html_type), k, data[k], positon)
                                    break
                    elif _type == "script":
                        # test html
                        flag = random_str(7)
                        script_tag = random_upper(details["tagname"])
                        payload = "</{}><{}>{}</{}>".format(
                            script_tag, script_tag, flag, script_tag)
                        truepayload = "</{}><{}>{}</{}>".format(
                            script_tag, script_tag, "prompt(1)", script_tag)
                        data[k] = payload
                        req = self.req(positon, data)
                        _occerens = SearchInputInResponse(flag, req.text)
                        for i in _occerens:
                            if i["details"]["content"] == flag and i[
                                    "details"]["tagname"].lower(
                                    ) == script_tag.lower():
                                self.result.add_detail(
                                    "可以新建script标签执行任意代码", req.reqinfo,
                                    generateResponse(req),
                                    "可以新建script标签执行任意代码 测试payload:{},注意返回格式为:{}"
                                    .format(truepayload,
                                            html_type), k, data[k], positon)
                                break

                        # js 语法树分析反射
                        source = details["content"]
                        _occurences = SearchInputInScript(xsschecker, source)
                        for i in _occurences:
                            _type = i["type"]
                            _details = i["details"]
                            if _type == "InlineComment":
                                flag = random_str(5)
                                payload = "\n;{};//".format(flag)
                                truepayload = "\n;{};//".format('prompt(1)')
                                data[k] = payload
                                resp = self.req(positon, data).text
                                for _item in SearchInputInResponse(flag, resp):
                                    if _item["details"]["tagname"] != "script":
                                        continue
                                    resp2 = _item["details"]["content"]
                                    output = SearchInputInScript(flag, resp2)
                                    for _output in output:
                                        if flag in _output["details"][
                                                "content"] and _output[
                                                    "type"] == "ScriptIdentifier":
                                            self.result.add_detail(
                                                "js单行注释bypass", req.reqinfo,
                                                generateResponse(req),
                                                "js单行注释可被\\n bypass,注意返回格式为:" +
                                                html_type.format(truepayload),
                                                k, data[k], positon)
                                            break

                            elif _type == "BlockComment":
                                flag = "0x" + random_str(4, "abcdef123456")
                                payload = "*/{};/*".format(flag)
                                truepayload = "*/{};/*".format('prompt(1)')
                                data[k] = payload
                                resp = self.req(positon, data).text
                                for _item in SearchInputInResponse(flag, resp):
                                    if _item["details"]["tagname"] != "script":
                                        continue
                                    resp2 = _item["details"]["content"]
                                    output = SearchInputInScript(flag, resp2)
                                    for _output in output:
                                        if flag in _output["details"][
                                                "content"] and _output[
                                                    "type"] == "ScriptIdentifier":
                                            self.result.add_detail(
                                                "js块注释可被bypass", req.reqinfo,
                                                generateResponse(req),
                                                "js单行注释可被\\n bypass,注意返回格式为:" +
                                                html_type.format(truepayload),
                                                k, data[k], positon)
                                            break
                            elif _type == "ScriptIdentifier":
                                self.result.add_detail(
                                    "可直接执行任意js命令", req.reqinfo,
                                    generateResponse(req),
                                    "ScriptIdentifier类型 测试payload:prompt(1);//,注意返回格式为:"
                                    + html_type, k, data[k], positon)
                            elif _type == "ScriptLiteral":
                                content = _details["content"]
                                quote = content[0]
                                flag = random_str(6)
                                if quote == "'" or quote == "\"":
                                    payload = '{quote}-{rand}-{quote}'.format(
                                        quote=quote, rand=flag)
                                    truepayload = '{quote}-{rand}-{quote}'.format(
                                        quote=quote, rand="prompt(1)")
                                else:
                                    flag = "0x" + random_str(4, "abcdef123456")
                                    payload = flag
                                    truepayload = "prompt(1)"
                                data[k] = payload
                                resp = self.req(positon, data).text
                                resp2 = None
                                for _item in SearchInputInResponse(
                                        payload, resp):
                                    if payload in _item["details"][
                                            "content"] and _item[
                                                "type"] == "script":
                                        resp2 = _item["details"]["content"]

                                if not resp2:
                                    continue
                                output = SearchInputInScript(flag, resp2)

                                if output:
                                    for _output in output:
                                        if flag in _output["details"][
                                                "content"] and _output[
                                                    "type"] == "ScriptIdentifier":
                                            self.result.add_detail(
                                                "script脚本内容可被任意设置",
                                                req.reqinfo,
                                                generateResponse(req),
                                                "测试payload:{},注意返回格式为:{}".
                                                format(truepayload, html_type),
                                                k, data[k], positon)
                                            break

                # ssti检测
                randnum1 = random.randint(50, 500)
                randnum2 = random.randint(80, 400)
                checksum = str(randnum1 * randnum2)
                ssti_payloads = self.getSSTIPayload(randnum1, randnum2)
                for payload in ssti_payloads:
                    data[k] = payload
                    # 不编码请求
                    r1 = self.req(positon, url_dict2str(data, positon))
                    if checksum in r1.text:
                        result = self.new_result()
                        result.init_info(self.requests.url, "SSTI模板注入",
                                         VulType.XSS)
                        result.add_detail(
                            "payload请求", r1.reqinfo, generateResponse(r1),
                            "payload:{} 会回显{} 不编码payload".format(
                                payload, checksum), k, payload, positon)
                        self.success(result)
                    # url编码请求
                    r1 = self.req(positon, data)
                    if checksum in r1.text:
                        result = self.new_result()
                        result.init_info(self.requests.url, "SSTI模板注入",
                                         VulType.XSS)
                        result.add_detail(
                            "payload请求", r1.reqinfo, generateResponse(r1),
                            "payload:{} 会回显{} url编码payload".format(
                                payload, checksum), k, payload, positon)
                        self.success(result)
                    # html编码请求
                    r1 = self.req(positon, data)
                    if checksum in r1.text:
                        result = self.new_result()
                        result.init_info(self.requests.url, "SSTI模板注入",
                                         VulType.XSS)
                        result.add_detail(
                            "payload请求", r1.reqinfo, generateResponse(r1),
                            "payload:{} 会回显{} html编码payload".format(
                                payload, checksum), k, payload, positon)
                        self.success(result)

        if len(self.result.detail) > 0:
            self.success(self.result)
Example #10
0
 def init(self):
     self.result = ResultObject(self)
     self.result.init_info(self.requests.url, "模板注入", VulType.SSTI)
Example #11
0
class W13SCAN(PluginBase):
    name = 'SSTI模板注入探测插件'

    def init(self):
        self.result = ResultObject(self)
        self.result.init_info(self.requests.url, "模板注入", VulType.SSTI)

    def getSSTIPayload(self, randint1=444, randint2=666) -> list:
        '''
        顺便检测下模板注入~
        return ['{123*1111}', '<%=123*1111%>', '#{123*1111}', '${{123*1111}}', '{{123*1111}}', '{{= 123*1111}}', '<# 123*1111>', '{@123*1111}', '[[123*1111]]', '${{"{{"}}123*1111{{"}}"}}']

        :return: list
        '''
        r = []
        payloads = [
            "{%d*%d}",
            "<%%=%d*%d%%>",
            "#{%d*%d}",
            "${{%d*%d}}",
            "{{%d*%d}}",
            "{{= %d*%d}}",
            "<# %d*%d>",
            "{@%d*%d}",
            "[[%d*%d]]",
            "${{\"{{\"}}%d*%d{{\"}}\"}}",
        ]
        for item in payloads:
            r.append(item % (randint1, randint2))
        return r

    def audit(self):

        parse_params = set(getParamsFromHtml(self.response.text))
        resp = self.response.text
        params_data = {}
        self.init()
        iterdatas = []
        if self.requests.method == HTTPMETHOD.GET:
            parse_params = (parse_params | TOP_RISK_GET_PARAMS) - set(
                self.requests.params.keys())
            for key in parse_params:
                params_data[key] = random_str(6)
            params_data.update(self.requests.params)
            resp = requests.get(self.requests.netloc,
                                params=params_data,
                                headers=self.requests.headers).text
            iterdatas = self.generateItemdatas(params_data)
        elif self.requests.method == HTTPMETHOD.POST:
            parse_params = (parse_params) - set(self.requests.post_data.keys())
            for key in parse_params:
                params_data[key] = random_str(6)
            params_data.update(self.requests.post_data)
            resp = requests.post(self.requests.url,
                                 data=params_data,
                                 headers=self.requests.headers).text
            iterdatas = self.generateItemdatas(params_data)

        for origin_dict, position in iterdatas:
            if position == PLACE.URI:
                continue
            for k, v in origin_dict.items():
                v = unquote(v)
                if v not in resp:
                    continue
                data = copy.deepcopy(origin_dict)
                # ssti检测
                r1 = self.test_ssti(data, k, position)
                if r1:
                    r2 = self.test_ssti(data, k, position)
                    if r2:
                        result = self.new_result()
                        result.init_info(self.requests.url, "SSTI模板注入",
                                         VulType.SSTI)
                        result.add_detail("第一次payload请求", r1["request"],
                                          r1["response"], r1["desc"], k,
                                          r1["payload"], position)
                        result.add_detail("第二次payload请求", r2["request"],
                                          r2["response"], r2["desc"], k,
                                          r2["payload"], position)
                        self.success(result)
                        break

        if len(self.result.detail) > 0:
            self.success(self.result)

    def test_ssti(self, data, k, positon):
        randnum1 = random.randint(1000, 10000)
        randnum2 = random.randint(8888, 20000)
        checksum = str(randnum1 * randnum2)
        ssti_payloads = self.getSSTIPayload(randnum1, randnum2)
        for payload in ssti_payloads:
            data[k] = payload
            # 不编码请求
            r1 = self.req(positon, url_dict2str(data, positon))
            if checksum in r1.text:
                return {
                    "request": r1.reqinfo,
                    "response": generateResponse(r1),
                    "desc":
                    "payload:{} 会回显{} 不编码payload".format(payload, checksum),
                    "payload": payload
                }
            # url编码请求
            r1 = self.req(positon, data)
            if checksum in r1.text:
                return {
                    "request":
                    r1.reqinfo,
                    "response":
                    generateResponse(r1),
                    "desc":
                    "payload:{} 会回显{} url编码payload".format(payload, checksum),
                    "payload":
                    payload
                }
            # html编码请求
            data[k] = html.escape(data[k])
            r1 = self.req(positon, data)
            if checksum in r1.text:
                return {
                    "request":
                    r1.reqinfo,
                    "response":
                    generateResponse(r1),
                    "desc":
                    "payload:{} 会回显{} html编码payload".format(payload, checksum),
                    "payload":
                    payload
                }
Example #12
0
    def audit(self):
        if self.requests.suffix != ".js":
            return

        regs = {
            "Slack Token":
            "(xox[p|b|o|a]-[0-9]{12}-[0-9]{12}-[0-9]{12}-[a-z0-9]{32})",
            "RSA private key":
            "-----BEGIN RSA PRIVATE KEY-----",
            "SSH (DSA) private key":
            "-----BEGIN DSA PRIVATE KEY-----",
            "SSH (EC) private key":
            "-----BEGIN EC PRIVATE KEY-----",
            "PGP private key block":
            "-----BEGIN PGP PRIVATE KEY BLOCK-----",
            "Amazon AWS Access Key ID":
            "AKIA[0-9A-Z]{16}",
            "Amazon MWS Auth Token":
            "amzn\\.mws\\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}",
            "AWS API Key":
            "AKIA[0-9A-Z]{16}",
            "Facebook Access Token":
            "EAACEdEose0cBA[0-9A-Za-z]+",
            "Facebook OAuth":
            "[f|F][a|A][c|C][e|E][b|B][o|O][o|O][k|K].*['|\"][0-9a-f]{32}['|\"]",
            "GitHub":
            "[g|G][i|I][t|T][h|H][u|U][b|B].*['|\"][0-9a-zA-Z]{35,40}['|\"]",
            "Generic API Key":
            "[a|A][p|P][i|I][_]?[k|K][e|E][y|Y].*['|\"][0-9a-zA-Z]{32,45}['|\"]",
            "Generic Secret":
            "[s|S][e|E][c|C][r|R][e|E][t|T].*['|\"][0-9a-zA-Z]{32,45}['|\"]",
            "Google API Key":
            "AIza[0-9A-Za-z\\-_]{35}",
            "Google Cloud Platform API Key":
            "AIza[0-9A-Za-z\\-_]{35}",
            "Google Cloud Platform OAuth":
            "[0-9]+-[0-9A-Za-z_]{32}\\.apps\\.googleusercontent\\.com",
            "Google Drive API Key":
            "AIza[0-9A-Za-z\\-_]{35}",
            "Google Drive OAuth":
            "[0-9]+-[0-9A-Za-z_]{32}\\.apps\\.googleusercontent\\.com",
            "Google (GCP) Service-account":
            "\"type\": \"service_account\"",
            "Google Gmail API Key":
            "AIza[0-9A-Za-z\\-_]{35}",
            "Google Gmail OAuth":
            "[0-9]+-[0-9A-Za-z_]{32}\\.apps\\.googleusercontent\\.com",
            "Google OAuth Access Token":
            "ya29\\.[0-9A-Za-z\\-_]+",
            "Google YouTube API Key":
            "AIza[0-9A-Za-z\\-_]{35}",
            "Google YouTube OAuth":
            "[0-9]+-[0-9A-Za-z_]{32}\\.apps\\.googleusercontent\\.com",
            "Heroku API Key":
            "[h|H][e|E][r|R][o|O][k|K][u|U].*[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}",
            "MailChimp API Key":
            "[0-9a-f]{32}-us[0-9]{1,2}",
            "Mailgun API Key":
            "key-[0-9a-zA-Z]{32}",
            "Password in URL":
            "[a-zA-Z]{3,10}://[^/\\s:@]{3,20}:[^/\\s:@]{3,20}@.{1,100}[\"'\\s]",
            "PayPal Braintree Access Token":
            "access_token\\$production\\$[0-9a-z]{16}\\$[0-9a-f]{32}",
            "Picatic API Key":
            "sk_live_[0-9a-z]{32}",
            "Slack Webhook":
            "https://hooks.slack.com/services/T[a-zA-Z0-9_]{8}/B[a-zA-Z0-9_]{8}/[a-zA-Z0-9_]{24}",
            "Stripe API Key":
            "sk_live_[0-9a-zA-Z]{24}",
            "Stripe Restricted API Key":
            "rk_live_[0-9a-zA-Z]{24}",
            "Square Access Token":
            "sq0atp-[0-9A-Za-z\\-_]{22}",
            "Square OAuth Secret":
            "sq0csp-[0-9A-Za-z\\-_]{43}",
            "Twilio API Key":
            "SK[0-9a-fA-F]{32}",
            "Twitter Access Token":
            "[t|T][w|W][i|I][t|T][t|T][e|E][r|R].*[1-9][0-9]+-[0-9a-zA-Z]{40}",
            "Twitter OAuth":
            "[t|T][w|W][i|I][t|T][t|T][e|E][r|R].*['|\"][0-9a-zA-Z]{35,44}['|\"]"
        }
        finds = []
        msg = ""
        for key in regs:
            results = re.findall(regs[key], self.response.text, re.M | re.I)
            if len(results) != 0:
                for result in results:
                    if len(result) < 100:
                        finds.append(key)
                        msg = msg + "根据{}的正则表达式:{} 发现敏感信息:{} \n".format(
                            key, regs[key], result)
        if len(finds) > 0:
            result = ResultObject(self)
            result.init_info(self.requests.url, "js文件中存在token敏感信息",
                             VulType.SENSITIVE)
            result.add_detail("payload探测", self.requests.raw,
                              self.response.raw, msg, "", "", PLACE.GET)
            self.success(result)
Example #13
0
    def audit(self):
        if self.requests.suffix != ".js":
            return

        regx = {
            # 匹配url
            # r'(\b|\'|")(?:http:|https:)(?:[\w/\.]+)?(?:[a-zA-Z0-9_\-\.]{1,})\.(?:php|asp|ashx|jspx|aspx|jsp|json|action|html|txt|xml|do)(\b|\'|")',
            # 匹配邮箱
            "邮箱信息":
            r'[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)+',
            # 匹配token或者密码泄露
            # 例如token = xxxxxxxx, 或者"apikey" : "xssss"
            "Token或密码":
            r'\b(?:secret|secret_key|token|secret_token|auth_token|access_token|username|password|aws_access_key_id|aws_secret_access_key|secretkey|authtoken|accesstoken|access-token|authkey|client_secret|bucket|email|HEROKU_API_KEY|SF_USERNAME|PT_TOKEN|id_dsa|clientsecret|client-secret|encryption-key|pass|encryption_key|encryptionkey|secretkey|secret-key|bearer|JEKYLL_GITHUB_TOKEN|HOMEBREW_GITHUB_API_TOKEN|api_key|api_secret_key|api-key|private_key|client_key|client_id|sshkey|ssh_key|ssh-key|privatekey|DB_USERNAME|oauth_token|irc_pass|dbpasswd|xoxa-2|xoxrprivate-key|private_key|consumer_key|consumer_secret|access_token_secret|SLACK_BOT_TOKEN|slack_api_token|api_token|ConsumerKey|ConsumerSecret|SESSION_TOKEN|session_key|session_secret|slack_token|slack_secret_token|bot_access_token|passwd|api|eid|sid|api_key|apikey|userid|user_id|user-id)["\s]*(?::|=|=:|=>)["\s]*[a-z0-9A-Z]{8,64}"?',
            # 匹配IP地址
            "IP地址":
            r'\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b',
            # 匹配云泄露
            "Cloudfront云泄露":
            r'[\w]+\.cloudfront\.net',
            "Appspot云泄露":
            r'[\w\-.]+\.appspot\.com',
            "亚马逊云泄露":
            r'[\w\-.]*s3[\w\-.]*\.?amazonaws\.com\/?[\w\-.]*',
            "Digitalocean云泄露":
            r'([\w\-.]*\.?digitaloceanspaces\.com\/?[\w\-.]*)',
            "Google云泄露":
            r'(storage\.cloud\.google\.com\/[\w\-.]+)',
            "Google存储API泄露":
            r'([\w\-.]*\.?storage.googleapis.com\/?[\w\-.]*)',
            # 匹配手机号
            "手机号":
            r'(?:139|138|137|136|135|134|147|150|151|152|157|158|159|178|182|183|184|187|188|198|130|131|132|155|156|166|185|186|145|175|176|133|153|177|173|180|181|189|199|170|171)[0-9]{8}',
            # 匹配域名
            # "域名泄露": r'((?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+(?:biz|cc|club|cn|com|co|edu|fun|group|info|ink|kim|link|live|ltd|mobi|net|online|org|pro|pub|red|ren|shop|site|store|tech|top|tv|vip|wang|wiki|work|xin|xyz|me))',

            # SSH 密钥
            "SSH密钥":
            '([-]+BEGIN [^\\s]+ PRIVATE KEY[-]+[\\s]*[^-]*[-]+END [^\\s]+ '
            'PRIVATE KEY[-]+)',

            # access_key
            "Access Key":
            'access_key.*?["\'](.*?)["\']',
            "Access Key ID 1":
            'accesskeyid.*?["\'](.*?)["\']',
            "Access Key ID 2":
            'accesskeyid.*?["\'](.*?)["\']',

            # 亚马逊 aws api 账号 密钥
            "亚马逊AWS API":
            'AKIA[0-9A-Z]{16}',
            "亚马逊AWS 3S API 1":
            's3\\.amazonaws.com[/]+|[a-zA-Z0-9_-]*\\.s3\\.amazonaws.com',
            "亚马逊AWS 3S API 2":
            '([a-zA-Z0-9-\\.\\_]+\\.s3\\.amazonaws\\.com|s3://[a-zA-Z0-9-\\.\\_]+|s3-[a-zA-Z0-9-\\.\\_\\/]+|s3.amazonaws.com/[a-zA-Z0-9-\\.\\_]+|s3.console.aws.amazon.com/s3/buckets/[a-zA-Z0-9-\\.\\_]+)',
            "亚马逊AWS 3S API 3":
            'amzn\\\\.mws\\\\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}',

            # author 信息
            "作者信息":
            '@author[: ]+(.*?) ',
            "API":
            'api[key|_key|\\s+]+[a-zA-Z0-9_\\-]{5,100}',
            "基础信息":
            'basic [a-zA-Z0-9=:_\\+\\/-]{5,100}',
            "Bearer":
            'bearer [a-zA-Z0-9_\\-\\.=:_\\+\\/]{5,100}',

            # facebook token
            "Facebook Token":
            'EAACEdEose0cBA[0-9A-Za-z]+',
            # github token
            "Github Token":
            '[a-zA-Z0-9_-]*:[a-zA-Z0-9_\\-]+@github\\.com*',
            # google api
            "Google API":
            'AIza[0-9A-Za-z-_]{35}',
            # google captcha 验证
            "Google验证码":
            '6L[0-9A-Za-z-_]{38}|^6[0-9a-zA-Z_-]{39}$',
            # google oauth 权限
            "Google OAuth":
            'ya29\\.[0-9A-Za-z\\-_]+',
            # jwt
            "JWT鉴权":
            'ey[A-Za-z0-9-_=]+\\.[A-Za-z0-9-_=]+\\.?[A-Za-z0-9-_.+/=]*$',
            # mailgun 服务密钥
            "Mailgun服务密钥":
            'key-[0-9a-zA-Z]{32}',
            # paypal braintree 访问凭证
            "Paypal/Braintree访问凭证":
            'access_token\\$production\\$[0-9a-z]{16}\\$[0-9a-f]{32}',
            # PGP 密钥块
            "PGP密钥":
            '-----BEGIN PGP PRIVATE KEY BLOCK-----',
            # possible_creds
            "密码泄露":
            '(?i)(password\\s*[`=:\\"]+\\s*[^\\s]+|password '
            'is\\s*[`=:\\"]*\\s*[^\\s]+|pwd\\s*[`=:\\"]*\\s*[^\\s]+|passwd\\s*[`=:\\"]+\\s*[^\\s]+)',

            # RSA
            "RSA密钥":
            '-----BEGIN EC PRIVATE KEY-----',
            # DSA
            "DSA密钥":
            '-----BEGIN DSA PRIVATE KEY-----',
            # stripe 账号泄露
            "Stripe账号泄露 1":
            'rk_live_[0-9a-zA-Z]{24}',
            "Stripe账号泄露 2":
            'sk_live_[0-9a-zA-Z]{24}',
            # twillio 账号泄露
            "Twillio 账号泄露 1":
            'AC[a-zA-Z0-9_\\-]{32}',
            "Twillio 账号泄露 2":
            'SK[0-9a-fA-F]{32}',
            "Twillio 账号泄露 3":
            'AP[a-zA-Z0-9_\\-]{32}'
        }
        for name, _ in regx.items():
            texts = re.findall(_, self.response.text, re.M | re.I)
            issuc = False
            if texts:
                for text in set(texts):
                    ignores = [
                        'function', 'encodeURIComponent', 'XMLHttpRequest'
                    ]
                    is_continue = True

                    for i in ignores:
                        if i in text:
                            is_continue = False
                            break
                    if not is_continue:
                        continue

                    result = ResultObject(self)
                    result.init_info(self.requests.url, "js文件中存在敏感信息",
                                     VulType.SENSITIVE)
                    result.add_detail("payload探测", self.requests.raw,
                                      self.response.raw,
                                      "根据正则:{} 发现敏感信息:{}".format(_, text), "",
                                      "", PLACE.GET)
                    self.success(result)
                    issuc = True
                    break
            if issuc:
                break