Example #1
0
 def perform_request(url,
                     data,
                     headers,
                     payload,
                     param,
                     injection_type,
                     uec=0):
     resp = ""
     if url and not data and "GET" in injection_type or "URI" in injection_type:
         url = prepare_injection_payload(url,
                                         payload,
                                         param=param,
                                         unknown_error_counter=uec)
     if data and url and "POST" in injection_type:
         data = prepare_injection_payload(data,
                                          payload,
                                          param=param,
                                          unknown_error_counter=uec)
     if (headers and url and "HEADER" in injection_type
             or "COOKIE" in injection_type):
         headers = prepare_injection_payload(headers,
                                             payload,
                                             param=param,
                                             unknown_error_counter=uec)
     try:
         resp = request.perform(url,
                                data=data,
                                headers=headers,
                                proxy=self._proxy)
     except Exception as error:
         logger.error(error)
         raise error
     return resp
Example #2
0
    def _fallback_check(self, payload, count, unknown_error_counter=0):
        PayloadResponse = collections.namedtuple(
            "PayloadResponse",
            [
                "is_injected",
                "status_code",
                "result",
                "payload",
                "payloads_count",
                "error",
            ],
        )
        status_code = None
        error = None
        logger.payload(f"{payload}")
        payload_request = prepare_payload_request(
            self, payload, unknown_error_counter=unknown_error_counter)
        url = payload_request.url
        data = payload_request.data
        regex = payload_request.regex
        headers = payload_request.headers
        try:
            response = request.inject_payload(url=url,
                                              regex=regex,
                                              data=data,
                                              headers=headers,
                                              proxy=self._proxy)
            if response.ok:
                result = response.result
                status_code = response.status_code
                error = response.error
                return PayloadResponse(
                    is_injected=True,
                    status_code=status_code,
                    result=result,
                    payload=payload,
                    payloads_count=count,
                    error=error,
                )
            else:
                status_code = response.status_code
                error = response.error
        except KeyboardInterrupt:
            logger.error("user interrupted")
            logger.end("ending")
            exit(0)

        return PayloadResponse(
            is_injected=False,
            status_code=status_code,
            result="",
            payload="",
            payloads_count=count,
            error=error,
        )
Example #3
0
 def _parse_target(self):
     ParamResponse = collections.namedtuple(
         "ParamResponse",
         ["params", "injection_type", "is_custom_injection"])
     params = []
     injection_type = self._injection_type
     is_custom_injection = False
     _temp = ParamResponse(
         params=params,
         injection_type=injection_type,
         is_custom_injection=is_custom_injection,
     )
     if (self.headers and self.url and "COOKIE" in injection_type.upper()
             or "HEADER" in injection_type.upper()):
         params = extract_params(value=self.headers,
                                 injection_type=injection_type)
         if "*" in self.headers:
             question = logger.read_input(
                 "custom injection marker ('*') found in option '--headers/--user-agent/--referer/--cookie'. Do you want to process it? [Y/n/q] ",
                 batch=self._batch,
                 user_input="Y",
             )
             if question and question == "q":
                 logger.error("user quit.")
                 logger.end("ending")
                 sys.exit(0)
             if question and question == "n":
                 params = params
             if question == "" or question == "y":
                 is_custom_injection = True
                 injection_type = f"(custom) {injection_type}"
     if self.data and self.url and "POST" in injection_type.upper():
         params = extract_params(value=self.data,
                                 injection_type=injection_type)
         if "*" in self.data:
             question = logger.read_input(
                 "custom injection marker ('*') found in POST body. Do you want to process it? [Y/n/q] ",
                 batch=self._batch,
                 user_input="Y",
             )
             if question and question == "q":
                 logger.error("user quit.")
                 logger.end("ending")
                 sys.exit(0)
             if question and question == "n":
                 params = params
             if question == "" or question == "y":
                 is_custom_injection = True
                 injection_type = "(custom) POST"
     if self.url and not self.data and "GET" in injection_type.upper():
         params = extract_params(value=self.url,
                                 injection_type=injection_type)
         if "*" in self.url:
             question = logger.read_input(
                 "custom injection marker ('*') found in option '-u'. Do you want to process it? [Y/n/q] ",
                 batch=self._batch,
                 user_input="Y",
             )
             if question and question == "q":
                 logger.error("user quit.")
                 logger.end("ending")
                 sys.exit(0)
             if question and question == "n":
                 params = params
             if question == "" or question == "y":
                 is_custom_injection = True
                 injection_type = "URI"
     if params:
         _temp = ParamResponse(
             params=params,
             injection_type=injection_type,
             is_custom_injection=is_custom_injection,
         )
     return _temp
Example #4
0
    def perform(self):
        vulns = []
        Response = collections.namedtuple(
            "Response",
            [
                "is_vulnerable",
                "dbms",
                "payloads",
                "filepath",
                "cookies",
                "headers",
                "injection_type",
                "injected_param",
                "session_filepath",
                "recommended_payload",
                "recommended_payload_type",
            ],
        )
        attemps_counter = 0
        session_data = []
        tested_payloads = []
        successful_payloads = []
        is_resumed = False
        filepath = None
        target_info = self._parse_target()
        set_cookie = ""
        set_headers = ""
        try:
            logger.notice("testing connection to the target URL.")
            resp = request.perform(
                self.url,
                data=self.data,
                headers=self.headers,
                use_requests=False,
                connection_test=True,
                proxy=self._proxy,
            )
            if "Set-Cookie" in list(resp.headers.keys()):
                set_cookie = (", ".join(resp.headers.get_all("Set-Cookie"))
                              if hasattr(resp.headers, "get_all") else
                              resp.headers.get("Set-Cookie"))
                set_cookie = re.sub(r"(?is)path=/", "", set_cookie)
                _show_slice = set_cookie.rstrip()
                if len(set_cookie) > 20:
                    _show_slice = f"{set_cookie[0:14]}....{set_cookie[-10:-2]}"
                question = logger.read_input(
                    f"you have not declared cookie(s), while server wants to set its own ('{_show_slice}'). Do you want to use those [Y/n] ",
                    batch=self._batch,
                    user_input="Y",
                )
                if question in ["", "y"]:
                    if "," in set_cookie:
                        set_cookie = "".join([
                            i.strip().replace("path=/", "").strip()
                            for i in set_cookie.split(",")
                        ])
                        set_cookie = ";".join(set_cookie.split(";"))
                    set_cookie = f"Cookie: {set_cookie}"
                    if (not self.headers or self.headers
                            and "cookie" not in self.headers.lower()):
                        self.headers += set_cookie
        except Exception as error:
            logger.critical(
                "Xpath was not able to establish connection. try checking with -v set to 5."
            )
            logger.error(error)
            sys.exit(0)
        payloads_list = prepare_payloads(
            prefixes=PREFIX,
            suffixes=SUFFIX,
            payloads=PAYLOADS,
            techniques=self._techniques,
        )
        try:
            table_name = "tbl_payload"
            session_data = session.fetch_from_table(
                session_filepath=self._session_filepath,
                table_name=table_name,
                cursor=False,
            )
            if session_data:
                is_resumed = True
            is_questioned = False
            for pay in session_data:
                vulns.append({
                    "injection_type":
                    f"({pay.get('parameter')})",
                    "attempts":
                    pay.get("payload_attemps"),
                    "payload":
                    pay.get("payload"),
                    "title":
                    pay.get("payload_type"),
                    "order":
                    pay.get("payload_order"),
                    "regex":
                    pay.get("regex"),
                    "injected_param":
                    pay.get("param").replace("*", ""),
                    "dbms":
                    pay.get("dbms"),
                })
        except Exception as error:
            pass
        if not target_info.params:
            logger.critical(
                "no parameter(s) found for testing in the provided data (e.g. GET parameter 'id' in 'www.site.com/index.php?id=1')."
            )
            logger.end("ending")
            sys.exit(0)
        if not vulns:
            params = target_info.params
            injection_type = target_info.injection_type
            is_custom_injection = target_info.is_custom_injection
            end_detection_phase = False
            is_injected = False
            successful_payload_prefix = ""
            vulnerable_param = ""
            unknown_error_counter = 0
            dbms = ""
            for entry in params:
                param = entry.get("key")
                param_value = entry.get("value")
                if is_custom_injection and not param_value.endswith("*"):
                    continue
                sep = ": " if "header" in injection_type.lower() else "="
                injectable_param = (f"{param}{sep}{param_value}"
                                    if param_value else f"{param}{sep}")
                resp = self.is_injectable(
                    self.url,
                    self.data,
                    self.headers,
                    param=param,
                    injectable_param=injectable_param,
                    injection_type=injection_type,
                )
                if not dbms:
                    dbms = resp.dbms
                is_injectable = resp.injectable
                logger.info(
                    f"testing for SQL injection on {injection_type} parameter '{param if not is_custom_injection else '#1*'}'"
                )
                next_param_test = False
                for entry in payloads_list:
                    backend = entry.get("back_end")
                    title = entry.get("title")
                    if dbms and dbms.lower() != backend.lower():
                        logger.debug(f"Skipped '{title}'")
                        continue
                    regex = entry.get("regex")
                    order = entry.get("order")
                    payloads = entry.get("payloads")
                    logger.info(f"testing '{title}'")
                    index = 0
                    if successful_payload_prefix:
                        payloads = [
                            pl for pl in payloads
                            if pl.prefix == successful_payload_prefix
                        ]
                    while index < len(payloads):
                        url = self.url
                        data = self.data
                        headers = self.headers
                        obj = payloads[index]
                        payload = obj.string
                        prefix = obj.prefix
                        suffix = obj.suffix
                        logger.payload(payload)
                        it = self._injection_type.upper()
                        if "HEADER" in it or "COOKIE" in it:
                            headers = prepare_injection_payload(
                                text=self.headers,
                                payload=payload,
                                param=injectable_param,
                                unknown_error_counter=unknown_error_counter,
                            )
                        if "GET" in it:
                            url = prepare_injection_payload(
                                text=self.url,
                                payload=payload,
                                param=injectable_param,
                                unknown_error_counter=unknown_error_counter,
                            )
                        if "POST" in it:
                            data = prepare_injection_payload(
                                text=self.data,
                                payload=payload,
                                param=injectable_param,
                                unknown_error_counter=unknown_error_counter,
                            )
                        try:
                            if not is_injected:
                                attemps_counter += 1
                            response = request.inject_payload(
                                url=url,
                                regex=REGEX_TESTS,
                                data=data,
                                headers=headers,
                                use_requests=self._use_requests,
                                proxy=self._proxy,
                            )
                        except KeyboardInterrupt as e:
                            question = logger.read_input(
                                "how do you want to proceed? [(S)kip current test/(e)nd detection phase/(n)ext parameter/(q)uit] "
                            )
                            if question and question == "e":
                                end_detection_phase = True
                                break
                            if question and question == "s":
                                break
                            if question and question == "n":
                                next_param_test = True
                                break
                            if question and question.lower() == "q":
                                logger.error("user quit")
                                logger.end("ending")
                                sys.exit(0)
                        except Exception as e:
                            unknown_error_counter += 1
                        else:
                            if response.ok:
                                is_injected = True
                                successful_payload_prefix = prefix
                                _ = session.generate(
                                    session_filepath=self._session_filepath)
                                with open(self._target_file, "w") as fd:
                                    fd.write(
                                        f"{self.url} ({'GET' if 'cookie' in injection_type.lower() else injection_type}) # {' '.join(sys.argv)}"
                                    )
                                if param:
                                    message = f"{injection_type} parameter '{DIM}{white}{param}{BRIGHT}{black}' is '{DIM}{white}{title}{BRIGHT}{black}' injectable"
                                else:
                                    message = f"{injection_type} parameter is '{DIM}{white}{title}{BRIGHT}{black}' injectable"
                                logger.notice(message)
                                vulns.append({
                                    "injection_type":
                                    f"({injection_type})",
                                    "attempts":
                                    attemps_counter,
                                    "payload":
                                    payload,
                                    "title":
                                    title,
                                    "order":
                                    order,
                                    "regex":
                                    regex,
                                    "injected_param":
                                    injectable_param.replace("*", ""),
                                    "dbms":
                                    dbms,
                                })
                                _ = session.dump(
                                    session_filepath=self._session_filepath,
                                    query=PAYLOAD_STATEMENT,
                                    values=(
                                        str(title),
                                        order,
                                        attemps_counter,
                                        payload,
                                        injection_type,
                                        regex,
                                        "test",
                                        injectable_param,
                                        dbms,
                                    ),
                                )
                                vulnerable_param = param
                                break
                            index += 1
                    if end_detection_phase or next_param_test:
                        break
                if not is_injected:
                    _param = f"{DIM}{white}'{param}'{BRIGHT}{black}"
                    logger.notice(
                        f"{injection_type} parameter {_param} does not seem to be injectable"
                    )
                if end_detection_phase:
                    if not is_injected:
                        logger.critical(
                            "all tested parameters do not appear to be injectable"
                        )
                    break
                if is_injected and not next_param_test:
                    if vulnerable_param:
                        message = f"{injection_type} parameter '{vulnerable_param}' is vulnerable. Do you want to keep testing the others (if any)? [y/N] "
                    else:
                        message = f"{injection_type} parameter is vulnerable. Do you want to keep testing the others (if any)? [y/N] "
                    question = logger.read_input(message,
                                                 batch=self._batch,
                                                 user_input="N")
                    if question and question == "n":
                        break
        else:
            logger.debug(
                "skipping tests as we already have injected the target..")

        if vulns and isinstance(vulns, list):
            vulns = sorted(
                vulns,
                key=lambda k: k.get("order")
                if k.get("order") else k.get("payload_order"),
                reverse=True,
            )
            dbms = vulns[0].get("dbms")
            injection_type = vulns[0].get("injection_type")
            injected_param = vulns[0].get("injected_param")
            recommended_payload = vulns[0].get("payload")
            recommended_payload = clean_up_payload(
                payload=recommended_payload,
                replaceable_string="0x72306f746833783439")
            recommended_payload_type = vulns[0].get("regex")
            param = injected_param
            if not param and self.headers:
                params = extract_params(self.headers,
                                        injection_type=injection_type)
                payload = prepare_injection_payload(self.headers,
                                                    recommended_payload,
                                                    param="").replace(
                                                        "%20", " ")
                param = ""
                for p in params:
                    sep = ": " if "header" in injection_type.lower() else "="
                    _param = f"{p.get('key')}{sep}{p.get('value').replace('*', '')}"
                    _ = f"{_param}{recommended_payload}"
                    if _ in payload.strip():
                        param = _param
                        break
            if not is_resumed:
                message = f"xpath identified the following injection point(s) with a total of {attemps_counter} HTTP(s) requests:"
            if is_resumed:
                message = "xpath resumed the following injection point(s) from stored session:"
            logger.success(message)
            if param:
                sep = ":" if "header" in injection_type.lower() else "="
                _param = param.split(sep)[0] if sep in param else param
                injection_type = f"{_param} {injection_type}"
            logger.success(f"---\nParameter: {injection_type}")
            text = "    Type: error-based\n    Title: {title}\n    Payload: {_payload}"
            ok = []
            for v in vulns:
                title = v.get("title").strip()
                pl = v.get("payload").strip()
                if pl[0].lower() in ["a", "o"]:
                    pl = f" {pl}"
                if param and "HEADER" not in injection_type.upper():
                    pl = f"{param}{pl}"
                ok.append(text.format(title=title, _payload=pl))
            logger.success("\n\n".join(ok))
            logger.success("---")
            resp = Response(
                is_vulnerable=True,
                payloads=vulns,
                dbms=dbms,
                filepath=self._filepath,
                cookies=set_cookie,
                headers=set_headers,
                injected_param=injected_param,
                injection_type=self._injection_type,
                session_filepath=self._session_filepath,
                recommended_payload=recommended_payload,
                recommended_payload_type=recommended_payload_type,
            )
        else:
            resp = Response(
                is_vulnerable=False,
                dbms=dbms,
                payloads=vulns,
                filepath=None,
                cookies=set_cookie,
                headers=set_headers,
                injected_param=None,
                session_filepath=None,
                injection_type=None,
                recommended_payload=None,
                recommended_payload_type=None,
            )
        return resp
Example #5
0
    def _extact(self, payloads):

        PayloadResponse = collections.namedtuple(
            "PayloadResponse",
            [
                "is_injected",
                "status_code",
                "result",
                "payload",
                "payloads_count",
                "error",
            ],
        )
        payloads_count = len(payloads)
        status_code = None
        error = None
        unknown_error_counter = 0
        for payload in payloads:
            logger.payload(f"{payload}")
            payload_request = prepare_payload_request(self, payload)
            url = payload_request.url
            data = payload_request.data
            regex = payload_request.regex
            headers = payload_request.headers
            try:
                response = request.inject_payload(url=url,
                                                  regex=regex,
                                                  data=data,
                                                  headers=headers,
                                                  proxy=self._proxy)
            except KeyboardInterrupt:
                logger.error("user interrupted")
                logger.end("ending")
                exit(0)
            except:
                unknown_error_counter += 1
                logger.debug(
                    "trying again the same payload with url encoding..")
                resp = self._fallback_check(
                    payload,
                    payloads_count,
                    unknown_error_counter=unknown_error_counter)
                if resp.is_injected:
                    return resp
            else:
                if response.ok:
                    result = response.result
                    status_code = response.status_code
                    error = response.error
                    return PayloadResponse(
                        is_injected=True,
                        status_code=status_code,
                        result=result,
                        payload=payload,
                        payloads_count=payloads_count,
                        error=error,
                    )
                else:
                    status_code = response.status_code
                    error = response.error
        return PayloadResponse(
            is_injected=False,
            status_code=status_code,
            result="",
            payload="",
            payloads_count=payloads_count,
            error=error,
        )
Example #6
0
 def inject_payload(
     self,
     url,
     regex,
     data="",
     headers="",
     proxy=None,
     use_requests=False,
     timeout=30,
 ):
     req = prepare_request(url=url,
                           data=data,
                           custom_headers=headers,
                           use_requests=use_requests)
     raw = req.raw
     custom_headers = req.headers
     logger.traffic_out(f"HTTP request:\n{raw}")
     ok = False
     text = ""
     result = ""
     error = ""
     status_code = 0
     response_url = ""
     reason = ""
     headers = {}
     Response = collections.namedtuple(
         "Response",
         [
             "ok", "url", "status_code", "text", "result", "headers",
             "reason", "error"
         ],
     )
     _temp = Response(
         ok=ok,
         url=response_url,
         status_code=status_code,
         text=text,
         result=result,
         headers=headers,
         reason=reason,
         error=error,
     )
     if proxy and proxy.for_urllib and not use_requests:
         proxy = proxy.for_urllib
     elif proxy and proxy.for_requests and use_requests:
         proxy = proxy.for_requests
     else:
         proxy = None
     if not data:
         try:
             if not use_requests:
                 opener = compat_opener()
                 if proxy:
                     opener = compat_opener(proxy)
                 opener.addheaders = custom_headers
                 resp = opener.open(url, timeout=timeout)
             else:
                 resp = requests.get(url,
                                     headers=custom_headers,
                                     proxies=proxy,
                                     timeout=timeout)
                 resp.raise_for_status()
         except (compat_httperr, requests.exceptions.HTTPError) as e:
             error_resp = parse_http_error(e)
             text = error_resp.text
             headers = error_resp.headers
             status_code = error_resp.status_code
             error = error_resp.error
             reason = error_resp.reason
             response_url = error_resp.url
         except compat_urlerr as e:
             logger.error(e)
         except KeyboardInterrupt as e:
             raise e
         except Exception as e:
             raise e
         else:
             http_response = parse_http_response(resp)
             headers = http_response.headers
             text = http_response.text
             status_code = http_response.status_code
             reason = http_response.reason
             response_url = http_response.url
     if data:
         try:
             if not use_requests:
                 data = data.encode("utf-8")
                 opener = compat_opener()
                 if proxy:
                     opener = compat_opener(proxy)
                 opener.addheaders = custom_headers
                 resp = opener.open(url, data, timeout=timeout)
             else:
                 resp = requests.get(
                     url,
                     data=data,
                     headers=custom_headers,
                     proxies=proxy,
                     timeout=timeout,
                 )
                 resp.raise_for_status()
         except (compat_httperr, requests.exceptions.HTTPError) as e:
             error_resp = parse_http_error(e)
             text = error_resp.text
             headers = error_resp.headers
             status_code = error_resp.status_code
             error = error_resp.error
             reason = error_resp.reason
             response_url = error_resp.url
         except compat_urlerr as e:
             logger.error(e)
         except KeyboardInterrupt as e:
             raise e
         except Exception as e:
             raise e
         else:
             http_response = parse_http_response(resp)
             headers = http_response.headers
             text = http_response.text
             status_code = http_response.status_code
             reason = http_response.reason
             response_url = http_response.url
     is_protected = detect_cloudflare_protection(text)
     if is_protected:
         result = cloudflare_decode(extract_encoded_data(text))
         try:
             result = result.encode("utf-8")
             encoding = chardet.detect(result).get("encoding", "utf-8")
             result = result.decode(encoding)
         except:
             pass
         _temp = Response(
             ok=True if result else False,
             url=response_url,
             status_code=status_code,
             text="",  # text, we can add response html here
             result=result,
             error=error,
             reason=reason,
             headers=headers,
         )
     if not is_protected:
         result = search_regex(
             pattern=regex,
             string=text,
             default="",
             group="xpath_data",
         )
         try:
             result = result.encode("utf-8")
             encoding = chardet.detect(result).get("encoding", "utf-8")
             result = result.decode(encoding)
         except:
             pass
         _temp = Response(
             ok=True if result else False,
             url=response_url,
             status_code=status_code,
             text="",  # text, we can add response html here
             result=result,
             error=error,
             reason=reason,
             headers=headers,
         )
     raw_response = prepare_response(_temp)
     logger.traffic_in(f"HTTP Response {raw_response}")
     return _temp