Пример #1
0
    def req(self, position, params, headers=None):
        r = False
        if headers is None:
            headers = self.requests.headers
        if position == PLACE.GET:
            r = requests.get(self.requests.netloc, params=params, headers=headers)
        elif position == PLACE.POST:
            r = requests.post(self.requests.url, data=params, headers=headers)
        elif position == PLACE.COOKIE:
            headers = self.requests.headers
            if 'Cookie' in headers:
                del headers["Cookie"]
            if 'cookie' in headers:
                del headers["cookie"]
            if isinstance(params, dict):
                headers["Cookie"] = url_dict2str(params, PLACE.COOKIE)
            else:
                headers["Cookie"] = params

            if self.requests.method == HTTPMETHOD.GET:
                r = requests.get(self.requests.url, headers=headers)
            elif self.requests.method == HTTPMETHOD.POST:
                r = requests.post(self.requests.url, data=self.requests.post_data, headers=headers,
                                  cookies=params)
        elif position == PLACE.URI:
            r = requests.get(params, headers=self.requests.headers)
        return r
Пример #2
0
 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
             }
Пример #3
0
 def _check_key(self):
     keys = [
         'kPH+bIxk5D2deZiIxcaaaA==',
         '4AvVhmFLUs0KTA3Kprsdag==',
         'WkhBTkdYSUFPSEVJX0NBVA==',
         'RVZBTk5JR0hUTFlfV0FPVQ==',
         'U3ByaW5nQmxhZGUAAAAAAA==',
         'cGljYXMAAAAAAAAAAAAAAA==',
         'd2ViUmVtZW1iZXJNZUtleQ==',
         'fsHspZw/92PrS3XrPW+vxw==',
         'sHdIjUN6tzhl8xZMG3ULCQ==',
         'WuB+y2gcHRnY2Lg9+Aqmqg==',
         'ertVhmFLUs0KTA3Kprsdag==',
         '2itfW92XazYRi5ltW0M2yA==',
         '6ZmI6I2j3Y+R1aSn5BOlAA==',
         'f/SY5TIve5WWzT4aQlABJA==',
         'Jt3C93kMR9D5e8QzwfsiMw==',
         'aU1pcmFjbGVpTWlyYWNsZQ==',
     ]
     for key in keys:
         payload = self.generator_payload(key)
         reqHeader = self.requests.headers
         if "Cookie" not in reqHeader:
             reqHeader["Cookie"] = ""
         _cookie = paramToDict(reqHeader["Cookie"], place=PLACE.COOKIE)
         _cookie["rememberMe"] = payload
         reqHeader["Cookie"] = url_dict2str(_cookie, PLACE.COOKIE)
         req = None
         if self.requests.method == HTTPMETHOD.GET:
             req = requests.get(self.requests.url, headers=reqHeader)
         elif self.requests.method == HTTPMETHOD.POST:
             req = requests.post(self.requests.url,
                                 data=self.requests.post_data,
                                 headers=reqHeader)
         if req and "deleteMe" not in req.headers.get('Set-Cookie', ''):
             result = ResultObject(self)
             result.init_info(self.requests.url, "Shiro Key发现",
                              VulType.CMD_INNJECTION)
             result.add_detail("payload探测", req.reqinfo,
                               generateResponse(req),
                               "Cookie中rememberMe可以被反序列化", "rememberMe",
                               payload, PLACE.COOKIE)
             self.success(result)
             return True
     return False
Пример #4
0
    def audit(self):
        respHeader = self.response.headers
        isShiro = False
        if "deleteMe" in respHeader.get('Set-Cookie', ''):
            isShiro = True
            result = ResultObject(self)
            result.init_info(self.requests.url, "Shiro框架发现", VulType.BASELINE)
            result.add_detail("payload探测", self.requests.raw,
                              self.response.raw, "在返回的cookie中发现了deleteMe标记",
                              "", "", PLACE.GET)
            self.success(result)
        if WEB_PLATFORM.JAVA not in self.response.programing and conf.level < 2 and not isShiro:
            return
        if not isShiro:
            # 如果不是shiro框架,检测一下
            reqHeader = self.requests.headers
            if "Cookie" not in reqHeader:
                reqHeader["Cookie"] = ""
            _cookie = paramToDict(reqHeader["Cookie"], place=PLACE.COOKIE)
            _cookie["rememberMe"] = "2"
            reqHeader["Cookie"] = url_dict2str(_cookie, PLACE.COOKIE)
            req = None
            if self.requests.method == HTTPMETHOD.GET:
                req = requests.get(self.requests.url, headers=reqHeader)
            elif self.requests.method == HTTPMETHOD.POST:
                req = requests.post(self.requests.url,
                                    data=self.requests.post_data,
                                    headers=reqHeader)
            if req and "deleteMe" in req.headers.get('Set-Cookie', ''):
                isShiro = True
                result = ResultObject(self)
                result.init_info(self.requests.url, "Shiro框架发现",
                                 VulType.BASELINE)
                result.add_detail(
                    "payload探测", req.reqinfo, generateResponse(req),
                    "在cookie中加入rememberMe=1,在返回cookie发现了deleteMe标记,可尝试爆破shiro的key",
                    "", "", PLACE.GET)
                self.success(result)

        # 爆破
        if isShiro:
            self._check_key()
Пример #5
0
    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)
Пример #6
0
    def inject(self, params, positon, k, payload_false, payload_true):
        data = copy.deepcopy(params)
        is_inject = False

        data[k] = payload_false
        r2 = self.req(positon, url_dict2str(data, positon))
        falsePage = self.removeDynamicContent(r2.text)

        try:
            self.seqMatcher.set_seq1(self.resp_str)
            self.seqMatcher.set_seq2(falsePage)
            ratio_false = round(self.seqMatcher.quick_ratio(), 3)
            if ratio_false == 1.0:
                return False
        except (MemoryError, OverflowError):
            return False

        # true page
        data[k] = payload_true
        r = self.req(positon, url_dict2str(data, positon))
        truePage = self.removeDynamicContent(r.text)

        if truePage == falsePage:
            return False

        try:
            self.seqMatcher.set_seq1(self.resp_str or "")
            self.seqMatcher.set_seq2(truePage or "")
            ratio_true = round(self.seqMatcher.quick_ratio(), 3)
        except (MemoryError, OverflowError):
            return False

        if ratio_true > self.UPPER_RATIO_BOUND and abs(
                ratio_true - ratio_false) > self.DIFF_TOLERANCE:
            if ratio_false <= self.UPPER_RATIO_BOUND:
                is_inject = True
        if not is_inject and ratio_true > 0.68 and ratio_true > ratio_false:
            originalSet = set(
                getFilteredPageContent(self.resp_str, True, "\n").split("\n"))
            trueSet = set(
                getFilteredPageContent(truePage, True, "\n").split("\n"))
            falseSet = set(
                getFilteredPageContent(falsePage, True, "\n").split("\n"))

            if len(originalSet - trueSet) <= 2 and trueSet != falseSet:
                candidates = trueSet - falseSet
                if len(candidates) > 0:
                    is_inject = True
                # if candidates:
                #     candidates = sorted(candidates, key=len)
                #     for candidate in candidates:
                #         if re.match(r"\A[\w.,! ]+\Z",
                #                     candidate) and ' ' in candidate and candidate.strip() and len(
                #             candidate) > 10:
                #             is_inject = True
                #             break

        if is_inject:
            ret = []
            ret.append({
                "request": r.reqinfo,
                "response": generateResponse(r),
                "key": k,
                "payload": payload_true,
                "position": positon,
                "desc": "发送True请求包与原网页相似度:{}".format(ratio_true)
            })
            ret.append({
                "request": r2.reqinfo,
                "response": generateResponse(r2),
                "key": k,
                "payload": payload_false,
                "position": positon,
                "desc": "发送False请求包与原网页相似度:{}".format(ratio_false)
            })
            return ret
        else:
            return False