Пример #1
0
 def addStartURL(self, url):
     if self.__checklink(url):
         print(_("Invalid link argument: {0}").format(url))
         sys.exit(0)
     if self.__inzone(url) == 0:
         self.tobrowse.append(HTTP.HTTPResource(url))
     else:
         self.out_of_scope_urls.append(HTTP.HTTPResource(url))
Пример #2
0
    def attackGET(self, http_res):
        url = http_res.path
        resp_headers = http_res.headers
        referer = http_res.referer
        headers = {}
        if referer:
            headers["referer"] = referer

        if url not in self.attackedGET:
            if self.verbose == 2:
                print(u"+ {0}".format(url))

            err1 = self.__returnErrorByCode(resp_headers["status_code"])

            if err1 != "ok":
                test_req = HTTP.HTTPResource(url)
                data1 = self.HTTP.send(test_req, headers=headers).getPage()
                # .htaccess protection detected
                if self.verbose >= 1:
                    self.log(_("HtAccess protection found: {0}"), url)

                evil_req = HTTP.HTTPResource(url, method="ABC")
                data2, code2 = self.HTTP.send(evil_req,
                                              headers=headers).getPageCode()
                err2 = self.__returnErrorByCode(code2)

                if err2 == "ok":
                    # .htaccess bypass success

                    if self.verbose >= 1:
                        self.logC(_("|HTTP Code: {0} : {1}"),
                                  resp_headers["status_code"], err1)

                    if self.verbose == 2:
                        self.logY(_("Source code:"))
                        self.logW(data1)

                    self.logVuln(category=Vulnerability.HTACCESS,
                                 level=Vulnerability.HIGH_LEVEL,
                                 request=evil_req,
                                 info=_("{0} HtAccess").format(err1))
                    self.logR(_("  .htaccess bypass vulnerability: {0}"),
                              evil_req.url)

                    # print output informations by verbosity option
                    if self.verbose >= 1:
                        self.logC(_("|HTTP Code: {0}"), code2)

                    if self.verbose == 2:
                        self.logY(_("Source code:"))
                        self.logW(data2)

                self.attackedGET.append(url)
Пример #3
0
    def __init__(self, http, xmlRepGenerator):
        Attack.__init__(self, http, xmlRepGenerator)
        user_config_dir = os.getenv('HOME') or os.getenv('USERPROFILE')
        user_config_dir += "/config"
        if not os.path.isdir(user_config_dir):
            os.makedirs(user_config_dir)
        try:
            fd = open(os.path.join(user_config_dir, self.CONFIG_FILE))
            reader = csv.reader(fd)
            self.nikto_db = [l for l in reader if l != [] and l[0].isdigit()]
            fd.close()
        except IOError:
            try:
                print(("Problem with local nikto database."))
                print(("Downloading from the web..."))
                nikto_req = HTTP.HTTPResource("http://cirt.net/nikto/UPDATES/2.1.5/db_tests")
                resp = self.HTTP.send(nikto_req)
                page = resp.getRawPage()

                csv.register_dialect("nikto", quoting=csv.QUOTE_ALL, doublequote=False, escapechar="\\")
                reader = csv.reader(page.split("\n"), "nikto")
                self.nikto_db = [l for l in reader if l != [] and l[0].isdigit()]

                fd = open(os.path.join(user_config_dir, self.CONFIG_FILE), "w")
                writer = csv.writer(fd)
                writer.writerows(self.nikto_db)
                fd.close()
            except socket.timeout:
                print(("Error downloading Nikto database"))
Пример #4
0
    def __end_element(self, name):
        if name == self.RESOURCE:
            http_res = HTTP.HTTPResource(self.path,
                                         method=self.method,
                                         encoding=self.encoding,
                                         referer=self.referer,
                                         get_params=self.get_params,
                                         post_params=self.post_params,
                                         file_params=self.file_params)
            http_res.setHeaders(self.headers)

            if self.array is self.to_browse:
                self.to_browse.append(http_res)
            else:
                if self.method == "GET":
                    self.browsed_links.append(http_res)
                elif self.method == "POST":
                    self.browsed_forms.append(http_res)
Пример #5
0
    def attackGET(self, http_res):
        if http_res.file_name == "":
            return

        page = http_res.path
        headers = http_res.headers

        # Do not attack application-type files
        if not "content-type" in headers:
            # Sometimes there's no content-type... so we rely on the document extension
            if (page.split(".")[-1] not in self.allowed) and page[-1] != "/":
                return
        elif not "text" in headers["content-type"]:
            return

        for payload in self.payloads:
            payload = payload.replace("[FILE_NAME]", http_res.file_name)
            url = page.replace(http_res.file_name, payload)

            if self.verbose == 2:
                print(u"+ {0}".format(url))

            if url not in self.attackedGET:
                self.attackedGET.append(url)
                try:
                    evil_req = HTTP.HTTPResource(url)

                    resp = self.HTTP.send(evil_req)
                    data, code = resp.getPageCode()
                    err = self.__returnErrorByCode(code)
                    if err == "ok":
                        self.logR(("Found backup file !"))
                        self.logR(u"    -> {0}".format(evil_req.url))
                        self.logVuln(
                            category=Vulnerability.BACKUP,
                            level=Vulnerability.HIGH_LEVEL,
                            request=evil_req,
                            info=("Backup file {0} found for {1}").format(
                                url, page))

                except socket.timeout:
                    break
Пример #6
0
 def attack(self, get_resources, forms):
     """This method searches XSS which could be permanently stored in the web application"""
     for http_resource in get_resources:
         if http_resource.method != "GET":
             continue
         url = http_resource.url
         target_req = HTTP.HTTPResource(url)
         referer = http_resource.referer
         headers = {}
         if referer:
             headers["referer"] = referer
         if self.verbose >= 1:
             print(u"+ {0}".format(url))
         try:
             resp = self.HTTP.send(target_req, headers=headers)
             data = resp.getPage()
         except requests.exceptions.Timeout, timeout:
             data = ""
         except socket.error, se:
             data = ""
             print(('error: {0} while attacking {1}').format(repr(str(se[1])), url))
Пример #7
0
    def __init__(self, root, http_engine=None):
        self.h = http_engine
        if root.startswith("-"):
            print(_("First argument must be the root url !"))
            sys.exit(0)
        if not "://" in root:
            root = "http://" + root
        if self.__checklink(root):
            print(_("Invalid protocol: {0}").format(root.split("://")[0]))
            sys.exit(0)
        if root[-1] != "/" and not "/" in root.split("://")[1]:
            root += "/"

        self.out_of_scope_urls = []
        self.browsed_links = []
        self.proxies = {}
        self.excluded = []
        self.browsed_forms = []
        self.uploads = []

        self.verbose = 0
        self.auth_basic = []
        self.bad_params = []
        self.timeout = 6.0
        self.global_headers = {}
        self.cookiejar = None
        self.scope = "folder"
        self.link_encoding = {}

        # 0 means no limits
        self.nice = 0
        self.max_link_depth = 40

        server = (root.split("://")[1]).split("/")[0]
        self.root = HTTP.HTTPResource(root)  # Initial URL
        self.server = server  # Domain (with potential :port)
        self.scope_url = root  # Scope of the analysis

        self.tobrowse = [self.root]
        self.persister = CrawlerPersister()
Пример #8
0
                    flash_parser = swf_parser.swf_parser(data)
                    swf_links = flash_parser.getLinks()
                except Exception, err_data:
                    swf_links = err_data[1]
            elif "/x-javascript" in mime_type or "/x-js" in mime_type or "/javascript" in mime_type:
                js_links = lamejs.lamejs(data).getLinks()
            data = ""

        # Manage redirections
        if "location" in info:
            redir = self.correctlink(info["location"], current,
                                     current_full_url, currentdir, proto, None)
            if redir is not None:
                if self.__inzone(redir) == 0:
                    self.link_encoding[redir] = self.link_encoding[url]
                    redir = HTTP.HTTPResource(redir,
                                              link_depth=current_depth + 1)
                    # Is the document not visited yet and not forbidden ?
                    if (redir not in self.browsed_links
                            and redir not in self.tobrowse
                            and not self.isExcluded(redir)):
                        self.tobrowse.append(redir)

        html_source = data
        bs = BeautifulSoup(html_source)
        # Look for a base tag with an href attribute
        if bs.head:
            for base in bs.head.findAll("base"):
                # BeautifulSoup doesn't work as excepted with the "in" statement, keep this:
                if "href" in base.attrs:
                    # Found a base url, now set it as the current url
                    current = base["href"].split("#")[0]
Пример #9
0
    def attackPOST(self, form):
        """This method performs the file handling attack with method POST"""

        # copies
        get_params = form.get_params
        post_params = form.post_params
        file_params = form.file_params
        referer = form.referer

        err = ""
        for params_list in [get_params, post_params, file_params]:
            for i in xrange(len(params_list)):
                timeouted = False
                warn = 0
                inc = 0
                err500 = 0

                saved_value = params_list[i][1]
                if saved_value is None:
                    saved_value = ""
                param_name = self.HTTP.quote(params_list[i][0])

                if params_list is file_params:
                    params_list[i][1] = ["_FILE__", params_list[i][1][1]]
                else:
                    params_list[i][1] = "__FILE__"

                attack_pattern = HTTP.HTTPResource(form.path,
                                                   method=form.method,
                                                   get_params=get_params,
                                                   post_params=post_params,
                                                   file_params=file_params)
                if attack_pattern not in self.attackedPOST:
                    self.attackedPOST.append(attack_pattern)
                    for payload in self.payloads:
                        payload = payload.replace('[FILE_NAME]',
                                                  form.file_name)

                        if params_list is file_params:
                            payload = payload.replace('[VALUE]',
                                                      saved_value[0])
                            payload = payload.replace(
                                '[DIRVALUE]', saved_value[0].rsplit('/', 1)[0])
                            params_list[i][1][0] = payload
                        else:
                            payload = payload.replace('[VALUE]', saved_value)
                            payload = payload.replace(
                                '[DIRVALUE]',
                                saved_value.rsplit('/', 1)[0])
                            params_list[i][1] = payload
                        evil_req = HTTP.HTTPResource(form.path,
                                                     method=form.method,
                                                     get_params=get_params,
                                                     post_params=post_params,
                                                     file_params=file_params,
                                                     referer=referer)
                        if self.verbose == 2:
                            print(u"+ {0}".format(evil_req))
                        try:
                            data, code = self.HTTP.send(evil_req).getPageCode()
                        except requests.exceptions.Timeout:
                            if timeouted:
                                continue
                            code = "408"
                            self.logAnom(category=Anomaly.RES_CONSUMPTION,
                                         level=Anomaly.MEDIUM_LEVEL,
                                         request=evil_req,
                                         parameter=param_name,
                                         info=Anomaly.MSG_PARAM_TIMEOUT.format(
                                             param_name))
                            self.logO(Anomaly.MSG_TIMEOUT, evil_req.path)
                            self.logO(Anomaly.MSG_EVIL_REQUEST)
                            self.logC(evil_req.http_repr)
                            print('')
                            timeouted = True
                        else:
                            err, inc, warn = self.__findPatternInResponse(
                                data, warn)
                        if err != "":
                            info_msg = (
                                "{0} via injection in the parameter {1}")
                            self.logVuln(category=Vulnerability.FILE_HANDLING,
                                         level=Vulnerability.HIGH_LEVEL,
                                         request=evil_req,
                                         parameter=param_name,
                                         info=info_msg.format(err, param_name))
                            self.logR(Vulnerability.MSG_PARAM_INJECT, err,
                                      evil_req.url, param_name)
                            self.logR(Vulnerability.MSG_EVIL_REQUEST)
                            self.logC(evil_req.http_repr)
                            print('')
                            if inc:
                                break

                        else:
                            if code == "500" and err500 == 0:
                                err500 = 1
                                self.logAnom(category=Anomaly.ERROR_500,
                                             level=Anomaly.HIGH_LEVEL,
                                             request=evil_req,
                                             parameter=param_name,
                                             info=Anomaly.MSG_PARAM_500.format(
                                                 param_name))
                                self.logO(Anomaly.MSG_500, evil_req.url)
                                self.logO(Anomaly.MSG_EVIL_REQUEST)
                                self.logC(evil_req.http_repr)
                                print('')
                params_list[i][1] = saved_value
Пример #10
0
    def attackGET(self, http_res):
        """This method performs the cross site scripting attack (XSS attack) with method GET"""

        # copies
        page = http_res.path
        params_list = http_res.get_params
        resp_headers = http_res.headers
        referer = http_res.referer
        headers = {}
        http_code = ""
        if referer:
            headers["referer"] = referer

        param_name = "PHP_SELF"

        # Some PHP scripts doesn't sanitize data coming from $_SERVER['PHP_SELF']
        if page not in self.PHP_SELF:
            evil_req = None
            if page.endswith("/"):
                evil_req = HTTP.HTTPResource(page + self.php_self_payload)
            elif page.endswith(".php"):
                evil_req = HTTP.HTTPResource(page + "/" +
                                             self.php_self_payload)
            if evil_req is not None:
                if self.verbose == 2:
                    print(u"+ {0}".format(evil_req.url))
                try:
                    data, http_code = self.HTTP.send(
                        evil_req, headers=headers).getPageCode()
                except requests.exceptions.Timeout:
                    data = ""
                    self.logO(Anomaly.MSG_TIMEOUT, evil_req.url)
                    self.logO(Anomaly.MSG_EVIL_REQUEST)
                    self.logC(evil_req.http_repr)
                    print('')
                    self.logAnom(
                        category=Anomaly.RES_CONSUMPTION,
                        level=Anomaly.MEDIUM_LEVEL,
                        request=evil_req,
                        parameter=param_name,
                        info=Anomaly.MSG_PARAM_TIMEOUT.format(param_name))

                if self._validXSSContentType(
                        evil_req) and self.php_self_check in data:
                    self.logR(Vulnerability.MSG_PATH_INJECT, self.MSG_VULN,
                              page)
                    self.logR(Vulnerability.MSG_EVIL_URL, evil_req.url)

                    self.logVuln(
                        category=Vulnerability.XSS,
                        level=Vulnerability.HIGH_LEVEL,
                        request=evil_req,
                        parameter=param_name,
                        info=
                        ("XSS vulnerability found via injection in the resource path"
                         ))
                elif http_code == "500":
                    self.logAnom(category=Anomaly.ERROR_500,
                                 level=Anomaly.HIGH_LEVEL,
                                 request=evil_req,
                                 parameter=param_name,
                                 info=Anomaly.MSG_PARAM_500.format(param_name))
                    self.logO(Anomaly.MSG_500, evil_req.url)
                    self.logO(Vulnerability.MSG_EVIL_REQUEST)
                    self.logC(evil_req.http_repr)
                    print('')
            self.PHP_SELF.append(page)

        timeouted = False
        returned500 = False

        # page is the url of the script
        # params_list is a list of [key, value] lists
        if not params_list:
            # Do not attack application-type files
            if not "content-type" in resp_headers:
                # Sometimes there's no content-type... so we rely on the document extension
                if (page.split(".")[-1]
                        not in self.allowed) and page[-1] != "/":
                    return
            elif not "text" in resp_headers["content-type"]:
                return

            url = page + "?__XSS__"
            if url not in self.attackedGET:
                self.attackedGET.append(url)
                code = self.random_string()
                test_req = HTTP.HTTPResource(page + "?" + code)
                self.GET_XSS[code] = (test_req, "QUERY_STRING")
                try:
                    data, http_code = self.HTTP.send(
                        test_req, headers=headers).getPageCode()
                except requests.exceptions.Timeout:
                    data = ""

                if code in data:
                    # Simple text injection worked, let's try with JS code
                    payloads = self.generate_payloads(data, code)
                    for payload in payloads:
                        evil_req = HTTP.HTTPResource(page + "?" +
                                                     self.HTTP.quote(payload))
                        if self.verbose == 2:
                            print(u"+ {0}".format(evil_req))
                        try:
                            dat, http_code = self.HTTP.send(
                                evil_req, headers=headers).getPageCode()
                        except requests.exceptions.Timeout:
                            dat = ""
                            if timeouted:
                                continue
                            self.logO(Anomaly.MSG_TIMEOUT, evil_req.url)
                            self.logO(Anomaly.MSG_EVIL_REQUEST)
                            self.logC(evil_req.http_repr)
                            print('')
                            self.logAnom(category=Anomaly.RES_CONSUMPTION,
                                         level=Anomaly.MEDIUM_LEVEL,
                                         request=evil_req,
                                         parameter=param_name,
                                         info=Anomaly.MSG_PARAM_TIMEOUT.format(
                                             param_name))
                            timeouted = True
                        param_name = "QUERY_STRING"

                        if self._validXSSContentType(
                                evil_req) and dat is not None and len(dat) > 1:
                            if payload.lower() in dat.lower():
                                self.SUCCESSFUL_XSS[code] = payload
                                self.logVuln(
                                    category=Vulnerability.XSS,
                                    level=Vulnerability.HIGH_LEVEL,
                                    request=evil_req,
                                    parameter=param_name,
                                    info=
                                    ("XSS vulnerability found via injection in the query string"
                                     ))

                                self.logR(Vulnerability.MSG_QS_INJECT,
                                          self.MSG_VULN, page)
                                self.logR(Vulnerability.MSG_EVIL_URL,
                                          evil_req.url)
                                # No more payload injection
                                break

                        elif http_code == "500" and not returned500:
                            self.logAnom(
                                category=Anomaly.ERROR_500,
                                level=Anomaly.HIGH_LEVEL,
                                request=evil_req,
                                parameter=param_name,
                                info=Anomaly.MSG_PARAM_500.format(param_name))
                            self.logO(Anomaly.MSG_500, evil_req.url)
                            self.logO(Vulnerability.MSG_EVIL_REQUEST)
                            self.logC(evil_req.http_repr)
                            print('')
                            returned500 = True

        # URL contains parameters
        else:
            for i in xrange(len(params_list)):
                saved_value = params_list[i][1]
                if saved_value is None:
                    saved_value = ""
                param_name = self.HTTP.quote(params_list[i][0])
                params_list[i][1] = "__XSS__"
                url = page + "?" + self.HTTP.encode(params_list)

                if url not in self.attackedGET:
                    self.attackedGET.append(url)
                    code = self.random_string()
                    params_list[i][1] = code
                    test_req = HTTP.HTTPResource(page + "?" +
                                                 self.HTTP.encode(params_list))
                    self.GET_XSS[code] = (test_req, param_name)
                    try:
                        data, http_code = self.HTTP.send(
                            test_req, headers=headers).getPageCode()
                    except requests.exceptions.Timeout:
                        data = ""
                    # is the random code on the webpage ?
                    if code in data:
                        # YES! But where exactly ?
                        payloads = self.generate_payloads(data, code)
                        for payload in payloads:

                            params_list[i][1] = payload

                            evil_req = HTTP.HTTPResource(
                                page + "?" + self.HTTP.encode(params_list))
                            if self.verbose == 2:
                                print(u"+ {0}".format(evil_req))
                            try:
                                dat, http_code = self.HTTP.send(
                                    evil_req, headers=headers).getPageCode()
                            except requests.exceptions.Timeout:
                                dat = ""
                                if timeouted:
                                    continue
                                self.logO(Anomaly.MSG_TIMEOUT, evil_req.url)
                                self.logO(Anomaly.MSG_EVIL_REQUEST)
                                self.logC(evil_req.http_repr)
                                print('')
                                self.logAnom(
                                    category=Anomaly.RES_CONSUMPTION,
                                    level=Anomaly.MEDIUM_LEVEL,
                                    request=evil_req,
                                    parameter=param_name,
                                    info=Anomaly.MSG_PARAM_TIMEOUT.format(
                                        param_name))
                                timeouted = True

                            if self._validXSSContentType(
                                    evil_req
                            ) and dat is not None and len(dat) > 1:
                                if payload.lower() in dat.lower():
                                    self.SUCCESSFUL_XSS[code] = payload
                                    self.logVuln(
                                        category=Vulnerability.XSS,
                                        level=Vulnerability.HIGH_LEVEL,
                                        request=evil_req,
                                        parameter=param_name,
                                        info=
                                        ("XSS vulnerability found via injection"
                                         " in the parameter {0}"
                                         ).format(param_name))

                                    self.logR(Vulnerability.MSG_PARAM_INJECT,
                                              self.MSG_VULN, page, param_name)

                                    self.logR(Vulnerability.MSG_EVIL_URL,
                                              evil_req.url)
                                    # stop trying payloads and jum to the next parameter
                                    break
                            elif http_code == "500" and not returned500:
                                self.logAnom(category=Anomaly.ERROR_500,
                                             level=Anomaly.HIGH_LEVEL,
                                             request=evil_req,
                                             parameter=param_name,
                                             info=Anomaly.MSG_PARAM_500.format(
                                                 param_name))
                                self.logO(Anomaly.MSG_500, evil_req.url)
                                self.logO(Vulnerability.MSG_EVIL_REQUEST)
                                self.logC(evil_req.http_repr)
                                print('')
                                returned500 = True

                # Restore the value of this argument before testing the next one
                params_list[i][1] = saved_value
Пример #11
0
    def attackGET(self, http_res):
        """This method performs the Blind SQL attack with method GET"""
        page = http_res.path
        params_list = http_res.get_params
        resp_headers = http_res.headers
        referer = http_res.referer
        headers = {}
        if referer:
            headers["referer"] = referer

        if not params_list:
            # Do not attack application-type files
            if not "content-type" in resp_headers:
                # Sometimes there's no content-type... so we rely on the document extension
                if (page.split(".")[-1] not in self.allowed) and page[-1] != "/":
                    return
            elif not "text" in resp_headers["content-type"]:
                return

            pattern_url = page + "?__SQL__"
            if pattern_url in self.excludedGET:
                return

            if pattern_url not in self.attackedGET:
                self.attackedGET.append(pattern_url)
                err500 = 0
                for payload in self.blind_sql_payloads:
                    if "[VALUE]" in payload:
                        continue
                    payload = self.HTTP.quote(payload.replace("__TIME__", self.TIME_TO_SLEEP))
                    url = page + "?" + payload
                    evil_req = HTTP.HTTPResource(url)
                    if self.verbose == 2:
                        print(u"+ {0}".format(evil_req.url))
                    try:
                        resp = self.HTTP.send(evil_req, headers=headers)
                        data, code = resp.getPageCode()
                    except requests.exceptions.Timeout:
                        self.logVuln(category=Vulnerability.BLIND_SQL_INJECTION,
                                     level=Vulnerability.HIGH_LEVEL,
                                     request=evil_req,
                                     parameter="QUERY_STRING",
                                     info=("{0} via injection in the query string").format(self.MSG_VULN))
                        self.logR(Vulnerability.MSG_QS_INJECT, self.MSG_VULN, page)
                        self.logR(Vulnerability.MSG_EVIL_URL, evil_req.url)
                        break
                    else:
                        if code == "500" and err500 == 0:
                            err500 = 1
                            self.logAnom(category=Anomaly.ERROR_500,
                                         level=Anomaly.HIGH_LEVEL,
                                         request=evil_req,
                                         parameter="QUERY_STRING",
                                         info=Anomaly.MSG_QS_500)
                            self.logO(Anomaly.MSG_500, page)
                            self.logO(Anomaly.MSG_EVIL_URL, evil_req.url)
        else:
            for i in range(len(params_list)):
                saved_value = params_list[i][1]
                if saved_value is None:
                    saved_value = ""

                param_name = self.HTTP.quote(params_list[i][0])
                params_list[i][1] = "__SQL__"
                pattern_url = page + "?" + self.HTTP.encode(params_list)

                # This field was successfully attacked with a non-blind SQL injection
                if pattern_url in self.excludedGET:
                    params_list[i][1] = saved_value
                    continue

                if pattern_url not in self.attackedGET:
                    self.attackedGET.append(pattern_url)

                    err500 = 0
                    for payload in self.blind_sql_payloads:
                        payload = payload.replace("[VALUE]", saved_value)
                        params_list[i][1] = self.HTTP.quote(payload.replace("__TIME__", self.TIME_TO_SLEEP))
                        url = page + "?" + self.HTTP.encode(params_list)
                        evil_req = HTTP.HTTPResource(url)
                        if self.verbose == 2:
                            print(u"+ {0}".format(evil_req.url))
                        try:
                            resp = self.HTTP.send(evil_req, headers=headers)
                            data, code = resp.getPageCode()
                        except requests.exceptions.Timeout:
                            self.logVuln(category=Vulnerability.BLIND_SQL_INJECTION,
                                         level=Vulnerability.HIGH_LEVEL,
                                         request=evil_req,
                                         parameter=param_name,
                                         info=("{0} via injection in "
                                                "the parameter {1}").format(self.MSG_VULN, param_name))
                            self.logR(Vulnerability.MSG_PARAM_INJECT,
                                      self.MSG_VULN,
                                      page,
                                      param_name)
                            self.logR(Vulnerability.MSG_EVIL_URL, evil_req.url)
                            # One payload worked. Now jum to next field
                            break
                        else:
                            if code == "500" and err500 == 0:
                                err500 = 1
                                self.logAnom(category=Anomaly.ERROR_500,
                                             level=Anomaly.HIGH_LEVEL,
                                             request=evil_req,
                                             parameter=param_name,
                                             info=Anomaly.MSG_PARAM_500.format(param_name))
                                self.logO(Anomaly.MSG_500, page)
                                self.logO(Anomaly.MSG_EVIL_URL, evil_req.url)
                params_list[i][1] = saved_value
Пример #12
0
    def attackPOST(self, form):
        """This method performs the Blind SQL attack with method POST"""

        # copies
        get_params = form.get_params
        post_params = form.post_params
        file_params = form.file_params
        referer = form.referer

        for params_list in [get_params, post_params, file_params]:
            for i in xrange(len(params_list)):
                saved_value = params_list[i][1]
                if saved_value is None:
                    saved_value = ""
                param_name = self.HTTP.quote(params_list[i][0])

                if params_list is file_params:
                    params_list[i][1] = ["_SQL__", params_list[i][1][1]]
                else:
                    params_list[i][1] = "__SQL__"

                attack_pattern = HTTP.HTTPResource(form.path,
                                                   method=form.method,
                                                   get_params=get_params,
                                                   post_params=post_params,
                                                   file_params=file_params)

                if attack_pattern in self.excludedPOST:
                    params_list[i][1] = saved_value
                    continue

                err500 = 0
                if attack_pattern not in self.attackedPOST:
                    self.attackedPOST.append(attack_pattern)
                    for payload in self.blind_sql_payloads:
                        if params_list is file_params:
                            payload = payload.replace("[VALUE]", saved_value[0])
                            params_list[i][1][0] = payload.replace("__TIME__", self.TIME_TO_SLEEP)
                        else:
                            payload = payload.replace("[VALUE]", saved_value)
                            params_list[i][1] = payload.replace("__TIME__", self.TIME_TO_SLEEP)

                        evil_req = HTTP.HTTPResource(form.path,
                                                     method=form.method,
                                                     get_params=get_params,
                                                     post_params=post_params,
                                                     file_params=file_params,
                                                     referer=referer)

                        if self.verbose == 2:
                            print(u"+ {0}".format(evil_req))
                        try:
                            resp = self.HTTP.send(evil_req)
                            data, code = resp.getPageCode()
                        except requests.exceptions.Timeout:
                            # Timeout means time-based SQL injection
                            self.logVuln(category=Vulnerability.BLIND_SQL_INJECTION,
                                         level=Vulnerability.HIGH_LEVEL,
                                         request=evil_req,
                                         parameter=param_name,
                                         info=("{0} via injection in the "
                                                "parameter {1}").format(self.MSG_VULN, param_name))
                            self.logR(Vulnerability.MSG_PARAM_INJECT,
                                      self.MSG_VULN,
                                      evil_req.url,
                                      param_name)
                            self.logR(Vulnerability.MSG_EVIL_REQUEST)
                            self.logC(evil_req.http_repr)
                            print('')
                            break

                        else:
                            if code == "500" and err500 == 0:
                                err500 = 1
                                self.logAnom(category=Anomaly.ERROR_500,
                                             level=Anomaly.HIGH_LEVEL,
                                             request=evil_req,
                                             parameter=param_name,
                                             info=Anomaly.MSG_PARAM_500.format(param_name))
                                self.logO(Anomaly.MSG_500, evil_req.url)
                                self.logO(Anomaly.MSG_EVIL_REQUEST)
                                self.logC(evil_req.http_repr)
                                print('')
                params_list[i][1] = saved_value
Пример #13
0
    def attackGET(self, http_res):
        """This method performs the SQL Injection attack with method GET"""
        page = http_res.path
        params_list = http_res.get_params
        resp_headers = http_res.headers
        referer = http_res.referer
        headers = {}
        if referer:
            headers["referer"] = referer

        # about this payload : http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string
        payload = "\xBF'\"("

        if not params_list:
            # Do not attack application-type files
            if not "content-type" in resp_headers:
                # Sometimes there's no content-type... so we rely on the document extension
                if (page.split(".")[-1] not in self.allowed) and page[-1] != "/":
                    return
            elif not "text" in resp_headers["content-type"]:
                return

            payload = self.HTTP.quote(payload)
            url = page + "?" + payload
            if url not in self.attackedGET:
                self.attackedGET.append(url)
                evil_req = HTTP.HTTPResource(url)

                if self.verbose == 2:
                    print(u"+ {0}".format(url))
                try:
                    resp = self.HTTP.send(evil_req, headers=headers)
                    data, code = resp.getPageCode()
                except requests.exceptions.Timeout:
                    # No timeout report here... launch blind sql detection later
                    code = "408"
                    err = ""
                else:
                    err = self.__findPatternInResponse(data)
                if err != "":
                    self.logVuln(category=Vulnerability.SQL_INJECTION,
                                 level=Vulnerability.HIGH_LEVEL,
                                 request=evil_req,
                                 info=_("{0} via injection in the query string").format(err))
                    self.logR(Vulnerability.MSG_QS_INJECT, err, page)
                    self.logR(Vulnerability.MSG_EVIL_URL, evil_req.url)

                    self.vulnerableGET.append(page + "?" + "__SQL__")

                else:
                    if code == "500":
                        self.logAnom(category=Anomaly.ERROR_500,
                                     level=Anomaly.HIGH_LEVEL,
                                     request=evil_req,
                                     info=Anomaly.MSG_QS_500)
                        self.logO(Anomaly.MSG_500, page)
                        self.logO(Anomaly.MSG_EVIL_URL, evil_req.url)
        else:
            for i in range(len(params_list)):
                param_name = self.HTTP.quote(params_list[i][0])
                saved_value = params_list[i][1]
                if saved_value is None:
                    saved_value = ""
                params_list[i][1] = "__SQL__"
                pattern_url = page + "?" + self.HTTP.encode(params_list)
                if pattern_url not in self.attackedGET:
                    self.attackedGET.append(pattern_url)

                    params_list[i][1] = self.HTTP.quote(payload)
                    url = page + "?" + self.HTTP.encode(params_list)
                    evil_req = HTTP.HTTPResource(url)

                    if self.verbose == 2:
                        print(u"+ {0}".format(evil_req.url))
                    try:
                        resp = self.HTTP.send(evil_req, headers=headers)
                        data, code = resp.getPageCode()
                    except requests.exceptions.Timeout:
                        # No timeout report here... launch blind sql detection later
                        code = "408"
                        err = ""
                    else:
                        err = self.__findPatternInResponse(data)
                    if err != "":
                        self.logVuln(category=Vulnerability.SQL_INJECTION,
                                     level=Vulnerability.HIGH_LEVEL,
                                     request=evil_req,
                                     parameter=param_name,
                                     info=_("{0} via injection in the parameter {1}").format(err, param_name))
                        self.logR(Vulnerability.MSG_PARAM_INJECT,
                                  err,
                                  page,
                                  param_name)
                        self.logR(Vulnerability.MSG_EVIL_URL, evil_req.url)
                        self.vulnerableGET.append(pattern_url)

                    elif code == "500":
                            self.logAnom(category=Anomaly.ERROR_500,
                                         level=Anomaly.HIGH_LEVEL,
                                         request=evil_req,
                                         parameter=param_name,
                                         info=Anomaly.MSG_PARAM_500.format(param_name))
                            self.logO(Anomaly.MSG_500, page)
                            self.logO(Anomaly.MSG_EVIL_URL, evil_req.url)
                params_list[i][1] = saved_value
Пример #14
0
    def attackPOST(self, form):
        """This method performs the SQL Injection attack with method POST"""
        payload = "\xbf'\"("
        filename_payload = "'\"("
        err = ""

        # copies
        get_params = form.get_params
        post_params = form.post_params
        file_params = form.file_params
        referer = form.referer

        for params_list in [get_params, post_params, file_params]:
            for i in xrange(len(params_list)):
                saved_value = params_list[i][1]
                if saved_value is None:
                    saved_value = ""

                if params_list is file_params:
                    params_list[i][1] = ["_SQL__", params_list[i][1][1]]
                else:
                    params_list[i][1] = "__SQL__"

                param_name = self.HTTP.quote(params_list[i][0])
                attack_pattern = HTTP.HTTPResource(form.path,
                                                   method=form.method,
                                                   get_params=get_params,
                                                   post_params=post_params,
                                                   file_params=file_params)
                if attack_pattern not in self.attackedPOST:
                    self.attackedPOST.append(attack_pattern)

                    if params_list is file_params:
                        params_list[i][1][0] = filename_payload
                    else:
                        params_list[i][1] = payload

                    evil_req = HTTP.HTTPResource(form.path,
                                                 method=form.method,
                                                 get_params=get_params,
                                                 post_params=post_params,
                                                 file_params=file_params,
                                                 referer=referer)
                    if self.verbose == 2:
                        print(u"+ {0}".format(evil_req))

                    try:
                        resp = self.HTTP.send(evil_req)
                        data, code = resp.getPageCode()
                    except requests.exceptions.Timeout, timeout:
                        # No timeout report here... launch blind sql detection later
                        code = "408"
                    else:
                        err = self.__findPatternInResponse(data)
                    if err != "":
                        self.logVuln(category=Vulnerability.SQL_INJECTION,
                                     level=Vulnerability.HIGH_LEVEL,
                                     request=evil_req,
                                     parameter=param_name,
                                     info=_("{0} via injection in the parameter {1}").format(err, param_name))
                        self.logR(Vulnerability.MSG_PARAM_INJECT,
                                  err,
                                  evil_req.url,
                                  param_name)
                        self.logR(Vulnerability.MSG_EVIL_REQUEST)
                        self.logC(evil_req.http_repr)
                        print('')
                        self.vulnerablePOST.append(attack_pattern)

                    else:
                        if code == "500":
                            self.logAnom(category=Anomaly.ERROR_500,
                                         level=Anomaly.HIGH_LEVEL,
                                         request=evil_req,
                                         parameter=param_name,
                                         info=Anomaly.MSG_PARAM_500.format(param_name))
                            self.logO(Anomaly.MSG_500, evil_req.url)
                            self.logO(Anomaly.MSG_EVIL_REQUEST)
                            self.logC(evil_req.http_repr)
                            print('')

                params_list[i][1] = saved_value
Пример #15
0
    def attackPOST(self, form):
        """This method performs the command execution with method POST"""

        # copies
        get_params = form.get_params
        post_params = form.post_params
        file_params = form.file_params
        referer = form.referer

        for params_list in [get_params, post_params, file_params]:
            for i in xrange(len(params_list)):
                saved_value = params_list[i][1]
                if saved_value is None:
                    saved_value = ""
                timeouted = False
                warned = 0
                cmd = 0
                err500 = 0
                param_name = self.HTTP.quote(params_list[i][0])

                if params_list is file_params:
                    params_list[i][1] = ["_EXEC__", params_list[i][1][1]]
                else:
                    params_list[i][1] = "__EXEC__"

                attack_pattern = HTTP.HTTPResource(form.path,
                                                   method=form.method,
                                                   get_params=get_params,
                                                   post_params=post_params,
                                                   file_params=file_params)
                if attack_pattern not in self.attackedPOST:
                    self.attackedPOST.append(attack_pattern)
                    for payload in self.payloads:
                        # no quoting: send() will do it for us
                        if params_list is file_params:
                            payload = payload.replace("[VALUE]", saved_value[0])
                            params_list[i][1][0] = payload
                        else:
                            payload = payload.replace("[VALUE]", saved_value)
                            params_list[i][1] = payload

                        evil_req = HTTP.HTTPResource(form.path,
                                                     method=form.method,
                                                     get_params=get_params,
                                                     post_params=post_params,
                                                     file_params=file_params,
                                                     referer=referer)
                        if self.verbose == 2:
                            print(u"+ {0}".format(evil_req))
                        err = ""
                        try:
                            data, code = self.HTTP.send(evil_req).getPageCode()
                        except requests.exceptions.Timeout:
                            if timeouted:
                                continue
                            code = "408"
                            self.logO(Anomaly.MSG_TIMEOUT, evil_req.url)
                            self.logO(Anomaly.MSG_EVIL_REQUEST)
                            self.logC(evil_req.http_repr)
                            print('')
                            self.logAnom(category=Anomaly.RES_CONSUMPTION,
                                         level=Anomaly.MEDIUM_LEVEL,
                                         request=evil_req,
                                         parameter=param_name,
                                         info=Anomaly.MSG_PARAM_TIMEOUT.format(param_name))
                            timeouted = True
                        else:
                            err, cmd, warned = self.__findPatternInResponse(data, warned)

                        if err != "":
                            self.logVuln(category=Vulnerability.EXEC,
                                         level=Vulnerability.HIGH_LEVEL,
                                         request=evil_req,
                                         parameter=param_name,
                                         info=("{0} via injection in the parameter {1}").format(err, param_name))
                            self.logR(Vulnerability.MSG_PARAM_INJECT, err, evil_req.url, param_name)
                            self.logR(Vulnerability.MSG_EVIL_REQUEST)
                            self.logC(evil_req.http_repr)
                            print('')

                            if cmd:
                                # Successful command execution, go to the next field
                                break

                        else:
                            if code == "500" and err500 == 0:
                                err500 = 1
                                self.logAnom(category=Anomaly.ERROR_500,
                                             level=Anomaly.HIGH_LEVEL,
                                             request=evil_req,
                                             parameter=param_name,
                                             info=Anomaly.MSG_PARAM_500.format(param_name))
                                self.logO(Anomaly.MSG_500, evil_req.url)
                                self.logO(Vulnerability.MSG_EVIL_REQUEST)
                                self.logC(evil_req.http_repr)
                                print('')
                params_list[i][1] = saved_value
Пример #16
0
    def attackGET(self, http_res):
        """This method performs the command execution with method GET"""

        page = http_res.path
        params_list = http_res.get_params
        resp_headers = http_res.headers
        referer = http_res.referer
        headers = {}
        if referer:
            headers["referer"] = referer

        if not params_list:
            # Do not attack application-type files
            if not "content-type" in resp_headers:
                # Sometimes there's no content-type... so we rely on the document extension
                if (page.split(".")[-1] not in self.allowed) and page[-1] != "/":
                    return
            elif not "text" in resp_headers["content-type"]:
                return

            timeouted = False
            warned = 0
            cmd = 0
            err500 = 0

            for payload in self.payloads:
                if "[VALUE]" in payload:
                    continue

                url = page + "?" + self.HTTP.quote(payload)

                if url not in self.attackedGET:
                    evil_req = HTTP.HTTPResource(url)
                    if self.verbose == 2:
                        print(u"+ {0}".format(url))
                    self.attackedGET.append(url)
                    try:
                        data, code = self.HTTP.send(evil_req, headers=headers).getPageCode()
                    except requests.exceptions.Timeout:
                        if timeouted:
                            continue
                        code = "408"
                        err = ""
                        self.logO(Anomaly.MSG_TIMEOUT, page)
                        self.logO(Anomaly.MSG_EVIL_URL, evil_req.url)
                        self.logAnom(category=Anomaly.RES_CONSUMPTION,
                                     level=Anomaly.MEDIUM_LEVEL,
                                     request=evil_req,
                                     info=Anomaly.MSG_QS_TIMEOUT)
                        timeouted = True
                    else:
                        err, cmd, warned = self.__findPatternInResponse(data, warned)
                    if err != "":
                        self.logVuln(category=Vulnerability.EXEC,
                                     level=Vulnerability.HIGH_LEVEL,
                                     request=evil_req,
                                     info=Vulnerability.MSG_QS_INJECT.format(err, page))
                        self.logR(Vulnerability.MSG_QS_INJECT, err, page)
                        self.logR(Vulnerability.MSG_EVIL_URL, evil_req.url)
                    else:
                        if code == "500" and err500 == 0:
                            err500 = 1
                            self.logAnom(category=Anomaly.ERROR_500,
                                         level=Anomaly.HIGH_LEVEL,
                                         request=evil_req,
                                         info=Anomaly.MSG_QS_500)
                            self.logO(Anomaly.MSG_500, page)
                            self.logO(Anomaly.MSG_EVIL_URL, evil_req.url)
                    if cmd:
                        break

        for i in range(len(params_list)):
            timeouted = False
            warned = 0
            cmd = 0
            err500 = 0

            saved_value = params_list[i][1]
            if saved_value is None:
                saved_value = ""
            params_list[i][1] = "__EXEC__"
            url = page + "?" + self.HTTP.encode(params_list)
            param_name = self.HTTP.quote(params_list[i][0])

            if url not in self.attackedGET:
                self.attackedGET.append(url)

                for payload in self.payloads:
                    payload = payload.replace("[VALUE]", saved_value)
                    params_list[i][1] = self.HTTP.quote(payload)
                    evil_req = HTTP.HTTPResource(page + "?" + self.HTTP.encode(params_list))

                    if self.verbose == 2:
                        print(u"+ {0}".format(evil_req.url))

                    try:
                        data, code = self.HTTP.send(evil_req, headers=headers).getPageCode()
                    except requests.exceptions.Timeout:
                        if timeouted:
                            continue
                        code = "408"
                        err = ""
                        self.logO(Anomaly.MSG_TIMEOUT, page)
                        self.logO(Anomaly.MSG_EVIL_URL, evil_req.url)
                        self.logAnom(category=Anomaly.RES_CONSUMPTION,
                                     level=Anomaly.MEDIUM_LEVEL,
                                     request=evil_req,
                                     parameter=param_name,
                                     info=Anomaly.MSG_PARAM_TIMEOUT.format(param_name))
                        timeouted = True
                    else:
                        err, cmd, warned = self.__findPatternInResponse(data, warned)

                    if err != "":
                        self.logVuln(category=Vulnerability.EXEC,
                                     level=Vulnerability.HIGH_LEVEL,
                                     request=evil_req,
                                     parameter=param_name,
                                     info=("{0} via injection in the parameter {1}").format(err, param_name))
                        self.logR(Vulnerability.MSG_PARAM_INJECT,
                                  err,
                                  page,
                                  param_name)
                        self.logR(Vulnerability.MSG_EVIL_URL, evil_req.url)

                        if cmd:
                            # Successful command execution, go to the next field
                            break
                    else:
                        if code == "500" and err500 == 0:
                            err500 = 1
                            self.logAnom(category=Anomaly.ERROR_500,
                                         level=Anomaly.HIGH_LEVEL,
                                         request=evil_req,
                                         parameter=param_name,
                                         info=Anomaly.MSG_PARAM_500.format(param_name))
                            self.logO(Anomaly.MSG_500, page)
                            self.logO(Anomaly.MSG_EVIL_URL, evil_req.url)
            params_list[i][1] = saved_value
Пример #17
0
                print(('error: {0} while attacking {1}').format(repr(str(e[0])), url))
                continue

            # Search for permanent XSS vulns which were injected via GET
            if self.doGET == 1:
                for code in self.GET_XSS:
                    if code in data:
                        # code found in the webpage !
                        code_url = self.GET_XSS[code][0].url
                        page = self.GET_XSS[code][0].path
                        param_name = self.GET_XSS[code][1]
                        if code in self.SUCCESSFUL_XSS:
                            # is this an already known vuln (reflected XSS)
                            if self.validXSS(data, code, self.SUCCESSFUL_XSS[code]):
                                # if we can find the payload again, this is a stored XSS
                                evil_req = HTTP.HTTPResource(code_url.replace(code, self.SUCCESSFUL_XSS[code]))

                                if param_name == "QUERY_STRING":
                                    self.logR(Vulnerability.MSG_QS_INJECT, self.MSG_VULN, page)
                                else:
                                    self.logR(Vulnerability.MSG_PARAM_INJECT, self.MSG_VULN, page, param_name)
                                self.logR(Vulnerability.MSG_EVIL_URL, code_url)

                                self.logVuln(category=Vulnerability.XSS,
                                             level=Vulnerability.HIGH_LEVEL,
                                             request=evil_req,
                                             info=("Found permanent XSS in {0}"
                                                    " with {1}").format(page, self.HTTP.escape(evil_req.url)))
                                # we reported the vuln, now search another code
                                continue
Пример #18
0
    def attack(self, urls, forms):
        junk_string = "w" + "".join([random.choice("0123456789abcdefghjijklmnopqrstuvwxyz") for __ in xrange(0, 5000)])
        for l in self.nikto_db:
            match = match_or = match_and = False
            fail = fail_or = False

            osv_id = l[1]
            path = l[3]
            method = l[4]
            vuln_desc = l[10]
            post_data = l[11]

            path = path.replace("@CGIDIRS", "/cgi-bin/")
            path = path.replace("@ADMIN", "/admin/")
            path = path.replace("@NUKE", "/modules/")
            path = path.replace("@PHPMYADMIN", "/phpMyAdmin/")
            path = path.replace("@POSTNUKE", "/postnuke/")
            path = re.sub("JUNK\((\d+)\)", lambda x: junk_string[:int(x.group(1))], path)

            if path[0] == "@":
                continue
            if path[0] != "/":
                path = "/" + path

            try:
                url = "http://" + self.HTTP.server + path
            except UnicodeDecodeError:
                continue

            if method == "GET":
                evil_req = HTTP.HTTPResource(url)
            elif method == "POST":
                evil_req = HTTP.HTTPResource(url, post_params=post_data, method=method)
            else:
                evil_req = HTTP.HTTPResource(url, post_params=post_data, method=method)

            if self.verbose == 2:
                try:
                    if method == "GET":
                        print(u"+ {0}".format(evil_req.url))
                    else:
                        print(u"+ {0}".format(evil_req.http_repr))
                except Exception:
                    continue

            try:
                resp = self.HTTP.send(evil_req)
            except Exception, e:
                # requests bug
                print(e)
                continue

            page, code = resp.getPageCode()
            encoding = BeautifulSoup(page).originalEncoding
            if encoding:
                page = unicode(page, encoding, errors='ignore')
            raw = " ".join([x + ": " + y for x, y in resp.getHeaders().items()])
            raw += page

            # First condition (match)
            if len(l[5]) == 3 and l[5].isdigit():
                if code == int(l[5]):
                    match = True
            else:
                if l[5] in raw:
                    match = True

            # Second condition (or)
            if l[6] != "":
                if len(l[6]) == 3 and l[6].isdigit():
                    if code == int(l[6]):
                        match_or = True
                else:
                    if l[6] in raw:
                        match_or = True

            # Third condition (and)
            if l[7] != "":
                if len(l[7]) == 3 and l[7].isdigit():
                    if code == int(l[7]):
                        match_and = True
                else:
                    if l[7] in raw:
                        match_and = True
            else:
                match_and = True

            # Fourth condition (fail)
            if l[8] != "":
                if len(l[8]) == 3 and l[8].isdigit():
                    if code == int(l[8]):
                        fail = True
                else:
                    if l[8] in raw:
                        fail = True

            # Fifth condition (or)
            if l[9] != "":
                if len(l[9]) == 3 and l[9].isdigit():
                    if code == int(l[9]):
                        fail_or = True
                else:
                    if l[9] in raw:
                        fail_or = True

            if ((match or match_or) and match_and) and not (fail or fail_or):
                print(url)
                print(vuln_desc)
                refs = []
                if osv_id != "0":
                    refs.append("http://osvdb.org/show/osvdb/" + osv_id)

                # CERT
                m = re.search("(CA\-[0-9]{4}-[0-9]{2})", vuln_desc)
                if m is not None:
                    refs.append("http://www.cert.org/advisories/" + m.group(0) + ".html")

                # SecurityFocus
                m = re.search("BID\-([0-9]{4})", vuln_desc)
                if m is not None:
                    refs.append("http://www.securityfocus.com/bid/" + m.group(1))

                # Mitre.org
                m = re.search("((CVE|CAN)\-[0-9]{4}-[0-9]{4,})", vuln_desc)
                if m is not None:
                    refs.append("http://cve.mitre.org/cgi-bin/cvename.cgi?name=" + m.group(0))

                # CERT Incidents
                m = re.search("(IN\-[0-9]{4}\-[0-9]{2})", vuln_desc)
                if m is not None:
                    refs.append("http://www.cert.org/incident_notes/" + m.group(0) + ".html")

                # Microsoft Technet
                m = re.search("(MS[0-9]{2}\-[0-9]{3})", vuln_desc)
                if m is not None:
                    refs.append("http://www.microsoft.com/technet/security/bulletin/" + m.group(0) + ".asp")

                info = vuln_desc
                if refs:
                    print(_("References:"))
                    print(u"  {0}".format(u"\n  ".join(refs)))
                    info += "\n" + _("References:") + "\n"
                    info += "\n".join(['<a href="' + x + '">' + x + '</a>' for x in refs])
                print('')

                self.logVuln(category=Vulnerability.NIKTO,
                             level=Vulnerability.HIGH_LEVEL,
                             request=evil_req,
                             info=info)
Пример #19
0
    def attackPOST(self, form):
        """This method performs the cross site scripting attack (XSS attack) with method POST"""
        page = form.url
        referer = form.referer
        headers = {}
        if referer:
            headers["referer"] = referer

        param_name = "PHP_SELF"

        if page not in self.PHP_SELF:
            evil_req = None
            if page.endswith("/"):
                evil_req = HTTP.HTTPResource(page + self.php_self_payload)
            elif page.endswith(".php"):
                evil_req = HTTP.HTTPResource(page + "/" +
                                             self.php_self_payload)
            if evil_req:
                if self.verbose == 2:
                    print(u"+ {0}".format(evil_req.url))
                try:
                    data, http_code = self.HTTP.send(
                        evil_req, headers=headers).getPageCode()
                except requests.exceptions.Timeout:
                    data = ""
                    self.logO(Anomaly.MSG_TIMEOUT, evil_req.url)
                    self.logO(Anomaly.MSG_EVIL_REQUEST)
                    self.logC(evil_req.http_repr)
                    print('')
                    self.logAnom(
                        category=Anomaly.RES_CONSUMPTION,
                        level=Anomaly.MEDIUM_LEVEL,
                        request=evil_req,
                        parameter=param_name,
                        info=Anomaly.MSG_PARAM_TIMEOUT.format(param_name))

                if self._validXSSContentType(
                        evil_req) and self.php_self_check in data:
                    self.logR(Vulnerability.MSG_PATH_INJECT, self.MSG_VULN,
                              page)
                    self.logR(Vulnerability.MSG_EVIL_URL, evil_req.url)

                    self.logVuln(
                        category=Vulnerability.XSS,
                        level=Vulnerability.HIGH_LEVEL,
                        request=evil_req,
                        parameter=param_name,
                        info=
                        ("XSS vulnerability found via injection in the resource path"
                         ))
                elif http_code == "500":
                    self.logAnom(category=Anomaly.ERROR_500,
                                 level=Anomaly.HIGH_LEVEL,
                                 request=evil_req,
                                 parameter=param_name,
                                 info=Anomaly.MSG_PARAM_500.format(param_name))
                    self.logO(Anomaly.MSG_500, evil_req.url)
                    self.logO(Vulnerability.MSG_EVIL_REQUEST)
                    self.logC(evil_req.http_repr)
                    print('')
            self.PHP_SELF.append(page)

        timeouted = False
        returned500 = False

        # copies
        get_params = form.get_params
        post_params = form.post_params
        file_params = form.file_params

        for params_list in [get_params, post_params, file_params]:
            for i in xrange(len(params_list)):
                param_name = self.HTTP.quote(params_list[i][0])
                saved_value = params_list[i][1]
                if saved_value is None:
                    saved_value = ""
                if params_list is file_params:
                    params_list[i][1] = ["_XSS__", params_list[i][1][1]]
                else:
                    params_list[i][1] = "__XSS__"
                # We keep an attack pattern to be sure a given form won't be attacked on the same field several times
                attack_pattern = HTTP.HTTPResource(form.path,
                                                   method=form.method,
                                                   get_params=get_params,
                                                   post_params=post_params,
                                                   file_params=file_params)
                if not attack_pattern in self.attackedPOST:
                    self.attackedPOST.append(attack_pattern)
                    code = self.random_string()
                    if params_list is file_params:
                        params_list[i][1][0] = code
                    else:
                        params_list[i][1] = code
                    # will only memorize the last used payload (working or not) but the code will always be the good
                    test_payload = HTTP.HTTPResource(form.path,
                                                     method=form.method,
                                                     get_params=get_params,
                                                     post_params=post_params,
                                                     file_params=file_params,
                                                     referer=referer)

                    self.POST_XSS[code] = (test_payload, param_name)
                    try:
                        data, http_code = self.HTTP.send(
                            test_payload).getPageCode()
                    except requests.exceptions.Timeout:
                        data = ""
                    # rapid search on the code to check injection
                    if code in data:
                        # found, now study where the payload is injected and how to exploit it
                        payloads = self.generate_payloads(data, code)
                        for payload in payloads:
                            if params_list is file_params:
                                params_list[i][1][0] = payload
                            else:
                                params_list[i][1] = payload

                            evil_req = HTTP.HTTPResource(
                                form.path,
                                method=form.method,
                                get_params=get_params,
                                post_params=post_params,
                                file_params=file_params,
                                referer=referer)

                            if self.verbose == 2:
                                print(u"+ {0}".format(evil_req))
                            try:
                                dat, http_code = self.HTTP.send(
                                    evil_req).getPageCode()
                            except requests.exceptions.Timeout:
                                dat = ""
                                if timeouted:
                                    continue
                                self.logO(Anomaly.MSG_TIMEOUT, evil_req.url)
                                self.logO(Anomaly.MSG_EVIL_REQUEST)
                                self.logC(evil_req.http_repr)
                                print('')
                                self.logAnom(
                                    category=Anomaly.RES_CONSUMPTION,
                                    level=Anomaly.MEDIUM_LEVEL,
                                    request=evil_req,
                                    parameter=param_name,
                                    info=Anomaly.MSG_PARAM_TIMEOUT.format(
                                        param_name))
                                timeouted = True

                            if self._validXSSContentType(
                                    evil_req
                            ) and dat is not None and len(dat) > 1:
                                if payload.lower() in dat.lower():
                                    self.SUCCESSFUL_XSS[code] = payload
                                    self.logVuln(
                                        category=Vulnerability.XSS,
                                        level=Vulnerability.HIGH_LEVEL,
                                        request=evil_req,
                                        parameter=param_name,
                                        info=
                                        ("XSS vulnerability found via injection"
                                         " in the parameter {0}"
                                         ).format(param_name))

                                    self.logR(Vulnerability.MSG_PARAM_INJECT,
                                              self.MSG_VULN, evil_req.url,
                                              param_name)

                                    self.logR(Vulnerability.MSG_EVIL_REQUEST)
                                    self.logC(evil_req.http_repr)
                                    print('')
                                    # Stop injecting payloads and move to the next parameter
                                    break
                            elif http_code == "500" and not returned500:
                                self.logAnom(category=Anomaly.ERROR_500,
                                             level=Anomaly.HIGH_LEVEL,
                                             request=evil_req,
                                             parameter=param_name,
                                             info=Anomaly.MSG_PARAM_500.format(
                                                 param_name))
                                self.logO(Anomaly.MSG_500, evil_req.url)
                                self.logO(Vulnerability.MSG_EVIL_REQUEST)
                                self.logC(evil_req.http_repr)
                                print('')
                                returned500 = True

                # restore the saved parameter in the list
                params_list[i][1] = saved_value