Example #1
0
    async def attack(self, request: Request):
        try:
            with open(os.path.join(self.user_config_dir, self.NIKTO_DB),
                      encoding='utf-8') as nikto_db_file:
                reader = csv.reader(nikto_db_file)
                next(reader)
                self.nikto_db = [
                    line for line in reader
                    if line != [] and line[0].isdigit()
                ]

        except IOError:
            logging.warning(_("Problem with local nikto database."))
            logging.info(_("Downloading from the web..."))
            await self.update()

        self.finished = True
        root_url = request.url
        self.parts = urlparse(root_url)

        tasks = set()
        pending_count = 0

        with open(os.path.join(self.user_config_dir, self.NIKTO_DB),
                  encoding='utf-8') as nikto_db_file:
            reader = csv.reader(nikto_db_file)
            while True:
                if pending_count < self.options[
                        "tasks"] and not self._stop_event.is_set():
                    try:
                        line = next(reader)
                    except StopIteration:
                        pass
                    else:
                        if line == [] or not line[0].isdigit():
                            continue

                        task = asyncio.create_task(self.process_line(line))
                        tasks.add(task)

                if not tasks:
                    break

                done_tasks, pending_tasks = await asyncio.wait(
                    tasks, timeout=0.01, return_when=asyncio.FIRST_COMPLETED)
                pending_count = len(pending_tasks)
                for task in done_tasks:
                    await task
                    tasks.remove(task)

                if self._stop_event.is_set():
                    for task in pending_tasks:
                        task.cancel()
                        tasks.remove(task)
Example #2
0
 async def _verify_wapp_database(self, categories_file_path: str,
                                 technologies_base_path: str,
                                 groups_file_path: str):
     try:
         with open(categories_file_path, encoding='utf-8') as categories_file, \
                 open(technologies_base_path, encoding='utf-8') as technologies_file, \
                 open(groups_file_path, encoding='utf-8') as groups_file:
             json.load(categories_file)
             json.load(technologies_file)
             json.load(groups_file)
     except IOError:
         logging.warning(_("Problem with local wapp database."))
         logging.info(_("Downloading from the web..."))
         await self.update()
Example #3
0
    async def finish(self):
        endpoint_url = f"{self.internal_endpoint}get_ssrf.php?session_id={self._session_id}"
        logging.info(_("[*] Asking endpoint URL {} for results, please wait...").format(endpoint_url))
        await sleep(2)
        # A la fin des attaques on questionne le endpoint pour savoir s'il a été contacté
        endpoint_request = Request(endpoint_url)
        try:
            response = await self.crawler.async_send(endpoint_request)
        except RequestError:
            self.network_errors += 1
            logging.error(_("[!] Unable to request endpoint URL '{}'").format(self.internal_endpoint))
        else:
            data = response.json
            if isinstance(data, dict):
                for request_id in data:
                    original_request = await self.persister.get_path_by_id(request_id)
                    if original_request is None:
                        raise ValueError("Could not find the original request with that ID")

                    page = original_request.path
                    for hex_param in data[request_id]:
                        parameter = unhexlify(hex_param).decode("utf-8")

                        for infos in data[request_id][hex_param]:
                            request_url = infos["url"]
                            # Date in ISO format
                            request_date = infos["date"]
                            request_ip = infos["ip"]
                            request_method = infos["method"]
                            # request_size = infos["size"]

                            if parameter == "QUERY_STRING":
                                vuln_message = Messages.MSG_QS_INJECT.format(self.MSG_VULN, page)
                            else:
                                vuln_message = _(
                                    "{0} via injection in the parameter {1}.\n"
                                    "The target performed an outgoing HTTP {2} request at {3} with IP {4}.\n"
                                    "Full request can be seen at {5}"
                                ).format(
                                    self.MSG_VULN,
                                    parameter,
                                    request_method,
                                    request_date,
                                    request_ip,
                                    request_url
                                )

                            mutator = Mutator(
                                methods="G" if original_request.method == "GET" else "PF",
                                payloads=[("http://external.url/page", Flags())],
                                qs_inject=self.must_attack_query_string,
                                parameters=[parameter],
                                skip=self.options.get("skipped_parameters")
                            )

                            mutated_request, __, __, __ = next(mutator.mutate(original_request))

                            await self.add_vuln_critical(
                                request_id=original_request.path_id,
                                category=NAME,
                                request=mutated_request,
                                info=vuln_message,
                                parameter=parameter,
                                wstg=WSTG_CODE
                            )

                            log_red("---")
                            log_red(
                                Messages.MSG_QS_INJECT if parameter == "QUERY_STRING"
                                else Messages.MSG_PARAM_INJECT,
                                self.MSG_VULN,
                                page,
                                parameter
                            )
                            log_red(Messages.MSG_EVIL_REQUEST)
                            log_red(mutated_request.http_repr())
                            log_red("---")
Example #4
0
 async def _verify_htp_database(self, htp_database_path: str):
     if os.path.exists(htp_database_path) is False:
         logging.warning(_("Problem with local htp database."))
         logging.info(_("Downloading from the web..."))
         await self.update()
Example #5
0
    async def finish(self):
        endpoint_url = f"{self.internal_endpoint}get_xxe.php?session_id={self._session_id}"
        logging.info(
            _("[*] Asking endpoint URL {} for results, please wait...").format(
                endpoint_url))
        await sleep(2)
        # A la fin des attaques on questionne le endpoint pour savoir s'il a été contacté
        endpoint_request = Request(endpoint_url)
        try:
            response = await self.crawler.async_send(endpoint_request)
        except RequestError:
            self.network_errors += 1
            logging.error(
                _("[!] Unable to request endpoint URL '{}'").format(
                    self.internal_endpoint))
            return

        data = response.json
        if not isinstance(data, dict):
            return

        for request_id in data:
            original_request = await self.persister.get_path_by_id(request_id)
            if original_request is None:
                continue
                # raise ValueError("Could not find the original request with ID {}".format(request_id))

            page = original_request.path
            for hex_param in data[request_id]:
                parameter = unhexlify(hex_param).decode("utf-8")

                for infos in data[request_id][hex_param]:
                    request_url = infos["url"]
                    # Date in ISO format
                    request_date = infos["date"]
                    request_ip = infos["ip"]
                    request_size = infos["size"]
                    payload_name = infos["payload"]

                    if parameter == "QUERY_STRING":
                        vuln_message = Messages.MSG_QS_INJECT.format(
                            self.MSG_VULN, page)
                    elif parameter == "raw body":
                        vuln_message = _(
                            "Out-Of-Band {0} by sending raw XML in request body"
                        ).format(self.MSG_VULN)
                    else:
                        vuln_message = _(
                            "Out-Of-Band {0} via injection in the parameter {1}"
                        ).format(self.MSG_VULN, parameter)

                    more_infos = _(
                        "The target sent {0} bytes of data to the endpoint at {1} with IP {2}.\n"
                        "Received data can be seen at {3}.").format(
                            request_size, request_date, request_ip,
                            request_url)

                    vuln_message += "\n" + more_infos

                    # placeholder if shit happens
                    payload = (
                        "<xml>"
                        "See https://phonexicum.github.io/infosec/xxe.html#attack-vectors"
                        "</xml>")

                    for payload, _flags in self.payloads:
                        if f"{payload_name}.dtd" in payload:
                            payload = payload.replace(
                                "[PATH_ID]", str(original_request.path_id))
                            payload = payload.replace("[PARAM_AS_HEX]",
                                                      "72617720626f6479")
                            break

                    if parameter == "raw body":
                        mutated_request = Request(original_request.path,
                                                  method="POST",
                                                  enctype="text/xml",
                                                  post_params=payload)
                    elif parameter == "QUERY_STRING":
                        mutated_request = Request(
                            f"{original_request.path}?{quote(payload)}",
                            method="GET")
                    elif parameter in original_request.get_keys or parameter in original_request.post_keys:
                        mutator = Mutator(
                            methods="G"
                            if original_request.method == "GET" else "P",
                            payloads=[(payload, Flags())],
                            qs_inject=self.must_attack_query_string,
                            parameters=[parameter],
                            skip=self.options.get("skipped_parameters"))

                        mutated_request, __, __, __ = next(
                            mutator.mutate(original_request))
                    else:
                        mutator = FileMutator(
                            payloads=[(payload, Flags())],
                            parameters=[parameter],
                            skip=self.options.get("skipped_parameters"))
                        mutated_request, __, __, __ = next(
                            mutator.mutate(original_request))

                    await self.add_vuln_high(
                        request_id=original_request.path_id,
                        category=NAME,
                        request=mutated_request,
                        info=vuln_message,
                        parameter=parameter,
                        wstg=WSTG_CODE)

                    log_red("---")
                    log_red(vuln_message)
                    log_red(Messages.MSG_EVIL_REQUEST)
                    log_red(mutated_request.http_repr())
                    log_red("---")