Projects STRLCPY ghauri Commits cf1eabae
🤬
  • fixed #50, fixed #51, fixed #49. updated code quality for avoid possible false positive detection case of content length boolean based type, added a proper retry mechanism before quitting, bumped version 1.1.9..

  • Loading...
  • r0oth3x49 committed 1 year ago
    cf1eabae
    1 parent 77c85f89
  • ■ ■ ■ ■
    README.md
    1  -[![GitHub release](https://img.shields.io/badge/release-v1.1.8-brightgreen?style=flat-square)](https://github.com/r0oth3x49/ghauri/releases/tag/1.1.8)
     1 +[![GitHub release](https://img.shields.io/badge/release-v1.1.9-brightgreen?style=flat-square)](https://github.com/r0oth3x49/ghauri/releases/tag/1.1.9)
    2 2  [![GitHub stars](https://img.shields.io/github/stars/r0oth3x49/ghauri?style=flat-square)](https://github.com/r0oth3x49/ghauri/stargazers)
    3 3  [![GitHub forks](https://img.shields.io/github/forks/r0oth3x49/ghauri?style=flat-square)](https://github.com/r0oth3x49/ghauri/network)
    4 4  [![GitHub issues](https://img.shields.io/github/issues/r0oth3x49/ghauri?style=flat-square)](https://github.com/r0oth3x49/ghauri/issues)
    skipped 160 lines
  • ■ ■ ■ ■
    ghauri/__init__.py
    skipped 23 lines
    24 24   
    25 25  """
    26 26   
    27  -__version__ = "1.1.8"
     27 +__version__ = "1.1.9"
    28 28  __author__ = "Nasir Khan (r0ot h3x49)"
    29 29  __license__ = "MIT"
    30 30  __copyright__ = "Copyright (c) 2016-2025 Nasir Khan (r0ot h3x49)"
    skipped 2 lines
  • ■ ■ ■ ■ ■ ■
    ghauri/common/config.py
    skipped 100 lines
    101 101   self.test_filter = None
    102 102   self.prioritize = False
    103 103   self._is_asked_for_priority = False
     104 + self._bool_check_on_ct = True
     105 + self._bool_ctb = None
     106 + self._bool_ctt = None
     107 + self._bool_ctf = None
    104 108   
    105 109   @property
    106 110   def session_filepath(self):
    skipped 7 lines
  • ■ ■ ■ ■ ■ ■
    ghauri/common/utils.py
    skipped 573 lines
    574 574   w2 = attack_false.filtered_text
    575 575   ratio_true = get_boolean_ratio(w0, w1)
    576 576   ratio_false = get_boolean_ratio(w0, w2)
    577  - logger.debug(f"ratio false payload attack: {ratio_false}")
    578  - logger.debug(f"ratio true payload attack: {ratio_true}")
     577 + # logger.debug(f"ratios: (True => {ratio_true} / False => {ratio_false})")
    579 578   if not conf.match_ratio:
    580 579   if ratio_false >= 0.02 and ratio_false <= 0.98:
    581 580   conf.match_ratio = ratio_false
    skipped 40 lines
    622 621   not_string = difference
    623 622   _cases.append("Page Content")
    624 623   else:
    625  - if ctt != ctf and ctb == ctt:
    626  - is_vulner = True
    627  - content_length = ctt
    628  - _cases.append("Content Length")
    629  - elif ctt != ctf and ctb == ctf:
    630  - is_vulner = True
    631  - content_length = ctf
    632  - _cases.append("Content Length")
     624 + # do check if initial requests performed returrned exact same content length
     625 + if conf._bool_check_on_ct:
     626 + if ctt != ctf and ctb == ctt:
     627 + is_vulner = True
     628 + content_length = ctt
     629 + _cases.append("Content Length")
     630 + elif ctt != ctf and ctb == ctf:
     631 + is_vulner = True
     632 + content_length = ctf
     633 + _cases.append("Content Length")
    633 634   if ratio_true != ratio_false:
    634 635   _cases.append("Page Ratio")
    635 636   is_vulner = True
    skipped 10 lines
    646 647   is_vulner = False
    647 648   else:
    648 649   logger.debug(f"possible injectable cases detected: '{case}'")
     650 + if case == "Content Length":
     651 + if not conf._bool_ctt and not conf._bool_ctf:
     652 + logger.debug(
     653 + "setting config content length for comparision to avoid false positive.."
     654 + )
     655 + conf._bool_ctt = ctt
     656 + conf._bool_ctf = ctf
    649 657   if case == "Page Ratio":
    650 658   w0set = set(get_filtered_page_content(base.text, True, "\n").split("\n"))
    651 659   w1set = set(get_filtered_page_content(attack_true.text, True, "\n").split("\n"))
    skipped 1418 lines
  • ■ ■ ■ ■ ■ ■
    ghauri/core/inject.py
    skipped 44 lines
    45 45   expression=None,
    46 46   is_multipart=False,
    47 47   injection_type=None,
     48 + connection_test=False,
    48 49  ):
    49 50   attack = None
    50 51   attack_url = url
    skipped 6 lines
    57 58   # )
    58 59   if conf.timeout and conf.timeout > 30:
    59 60   timeout = conf.timeout
    60  - if injection_type in ["HEADER", "COOKIE"]:
    61  - attack_headers = prepare_attack_request(
    62  - headers,
    63  - expression,
    64  - param=parameter,
    65  - injection_type=injection_type,
    66  - )
    67  - if injection_type == "GET":
    68  - attack_url = prepare_attack_request(
    69  - url,
    70  - expression,
    71  - param=parameter,
    72  - encode=True,
    73  - injection_type=injection_type,
    74  - )
     61 + if not connection_test:
     62 + if injection_type in ["HEADER", "COOKIE"]:
     63 + attack_headers = prepare_attack_request(
     64 + headers,
     65 + expression,
     66 + param=parameter,
     67 + injection_type=injection_type,
     68 + )
     69 + if injection_type == "GET":
     70 + attack_url = prepare_attack_request(
     71 + url,
     72 + expression,
     73 + param=parameter,
     74 + encode=True,
     75 + injection_type=injection_type,
     76 + )
    75 77   
    76  - if injection_type == "POST":
    77  - attack_data = prepare_attack_request(
    78  - data,
    79  - expression,
    80  - param=parameter,
    81  - encode=True,
    82  - injection_type=injection_type,
    83  - )
     78 + if injection_type == "POST":
     79 + attack_data = prepare_attack_request(
     80 + data,
     81 + expression,
     82 + param=parameter,
     83 + encode=True,
     84 + injection_type=injection_type,
     85 + )
    84 86   try:
    85 87   attack = request.perform(
    86 88   url=attack_url,
    87 89   data=attack_data,
    88 90   proxy=conf.proxy,
    89 91   headers=attack_headers,
     92 + connection_test=connection_test,
    90 93   is_multipart=conf.is_multipart,
    91 94   timeout=timeout,
    92 95   )
    skipped 70 lines
  • ■ ■ ■ ■ ■
    ghauri/core/tests.py
    skipped 100 lines
    101 101   _possible_dbms = None
    102 102   try:
    103 103   logger.notice("testing connection to the target URL")
    104  - base = request.perform(
     104 + base = inject_expression(
    105 105   url=url,
    106 106   data=data,
    107 107   proxy=proxy,
    108 108   headers=headers,
     109 + parameter=parameter,
    109 110   connection_test=True,
    110  - is_multipart=is_multipart,
    111  - timeout=timeout,
    112 111   )
    113 112   retval = session.fetchall(
    114 113   session_filepath=conf.session_filepath,
    skipped 18 lines
    133 132   time.sleep(0.5)
    134 133   except:
    135 134   pass
    136  - resp = request.perform(
     135 + resp = inject_expression(
    137 136   url=url,
    138 137   data=data,
    139 138   proxy=proxy,
    140 139   headers=headers,
     140 + parameter=parameter,
    141 141   connection_test=True,
    142  - is_multipart=is_multipart,
    143  - timeout=timeout,
    144 142   )
    145 143   logger.debug(f"r1: {base.content_length}, r2: {resp.content_length}")
     144 + # check when content length for two similar request differs it mean there could be a false positive boolean based injection detection
     145 + # based on content length of a page so to avoid that content these two initial request should match the content length
     146 + # for Ghauri to consider content length based boolean injection types, default check is true
     147 + if base.content_length != resp.content_length:
     148 + conf._bool_check_on_ct = False
     149 + conf._bool_ctb = base.content_length
    146 150   baseSet = set(base.filtered_text.split("\n"))
    147 151   respSet = set(resp.filtered_text.split("\n"))
    148 152   is_stable = bool(baseSet == respSet)
    skipped 246 lines
    395 399   confirm_response_type = boolean_confirm_retval.vulnerable
    396 400   case = boolean_confirm_retval.case
    397 401   diff = boolean_confirm_retval.difference
     402 + if case == "Content Length" and conf._bool_ctf and conf._bool_ctt:
     403 + is_bool_ct_ok = bool(
     404 + conf._bool_ctt == attack.content_length
     405 + and conf._bool_ctf == attack01.content_length
     406 + )
     407 + if not is_bool_ct_ok:
     408 + # logger.debug(f"false positive payload detected for case '{case}'")
     409 + conf._bool_ctt = None
     410 + conf._bool_ctf = None
     411 + break
    398 412   if confirm_response_type:
    399 413   logger.debug(
    400 414   " Test: {}, Response Type {}".format(
    skipped 2136 lines
  • ■ ■ ■ ■ ■ ■
    ghauri/extractor/common.py
    skipped 123 lines
    124 124   logger.success(f"banner: '{retval.result}'")
    125 125   else:
    126 126   error = retval.error
    127  - message = f"Ghauri detected an error during banner extraction ({error})"
    128  - logger.warning(f"{message}")
     127 + if error:
     128 + message = (
     129 + f"Ghauri detected an error during banner extraction ({error})"
     130 + )
     131 + logger.warning(f"{message}")
    129 132   logger.end("ending")
    130 133   exit(0)
    131 134   else:
    skipped 80 lines
    212 215   logger.success(f"current user: '{retval.result}'")
    213 216   else:
    214 217   error = retval.error
    215  - message = (
    216  - f"Ghauri detected an error during current user extraction ({error})"
    217  - )
    218  - logger.warning(f"{message}")
     218 + if error:
     219 + message = f"Ghauri detected an error during current user extraction ({error})"
     220 + logger.warning(f"{message}")
    219 221   logger.end("ending")
    220 222   exit(0)
    221 223   else:
    skipped 80 lines
    302 304   logger.success(f"current database: '{retval.result}'")
    303 305   else:
    304 306   error = retval.error
    305  - message = f"Ghauri detected an error during current database extraction ({error})"
    306  - logger.warning(f"{message}")
     307 + if error:
     308 + message = f"Ghauri detected an error during current database extraction ({error})"
     309 + logger.warning(f"{message}")
    307 310   logger.end("ending")
    308 311   exit(0)
    309 312   else:
    skipped 6 lines
  • ■ ■ ■ ■
    setup.py
    skipped 4 lines
    5 5   
    6 6  setup(
    7 7   name="ghauri",
    8  - version="1.1.8",
     8 + version="1.1.9",
    9 9   description="An advanced SQL injection detection & exploitation tool.",
    10 10   classifiers=["Programming Language :: Python3"],
    11 11   author="Nasir Khan",
    skipped 28 lines
Please wait...
Page is in error, reload to recover