From 43c657405634454fa72f24638b10032f55e90377 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0tampar?= Date: Thu, 16 Jul 2026 18:33:39 +0200 Subject: [PATCH] Fixing CI/CD errors --- .github/workflows/tests.yml | 6 ++++++ extra/esperanto/__init__.py | 2 ++ extra/esperanto/atlas.py | 8 +++++++- extra/esperanto/discovery.py | 21 +++++++++++++++++++-- extra/esperanto/engine.py | 7 +++++-- extra/esperanto/enumeration.py | 14 ++++++++++++-- extra/esperanto/extraction.py | 19 +++++++++++++++++-- extra/esperanto/oracle.py | 4 ++-- extra/esperanto/records.py | 3 --- lib/core/settings.py | 2 +- lib/core/testing.py | 1 + 11 files changed, 72 insertions(+), 15 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 85ae78c0e..98dedd5cd 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -111,6 +111,12 @@ jobs: # 'binary' instead of 'text'. Keeping this step byte-compile-free leaves --smoke clean. run: python -B -m unittest discover -s tests -p "test_*.py" + - name: Esperanto self-test + # offline, deterministic engine check against an in-memory SQLite boolean oracle: all + # compare modes + identify + bytes/text + noisy-oracle quorum + integrity + strategy + # handoff (a failed assertion exits non-zero) + run: python extra/esperanto/run.py --self-test + - name: Coverage if: matrix.python-version != 'pypy-2.7' run: | diff --git a/extra/esperanto/__init__.py b/extra/esperanto/__init__.py index 815002404..cc2cb9e39 100644 --- a/extra/esperanto/__init__.py +++ b/extra/esperanto/__init__.py @@ -24,3 +24,5 @@ from .engine import hostExtract from .handler import buildHandler from .records import Cap, ExtractResult, BulkResult, Dialect, InferenceStrategy from .records import OracleUndecided, QueryBudgetExceeded + +__all__ = ["Esperanto", "hostExtract", "buildHandler", "Cap", "ExtractResult", "BulkResult", "Dialect", "InferenceStrategy", "OracleUndecided", "QueryBudgetExceeded"] diff --git a/extra/esperanto/atlas.py b/extra/esperanto/atlas.py index 07ae9981b..40e516916 100644 --- a/extra/esperanto/atlas.py +++ b/extra/esperanto/atlas.py @@ -418,12 +418,18 @@ try: except NameError: _unichr = chr # py3 +# py2/py3 shim: the py2 unicode text type (str on py3) +try: + _unicode = unicode # py2 +except NameError: + _unicode = str # py3 + def _native(s): # embed a literal as the native str type: on py2 a unicode value is encoded to # utf-8 bytes so the byte-string SQL templates ('{expr}'.format(...)) don't force # an ascii encode of non-ASCII data; on py3 str is already unicode-clean. - if str is bytes and isinstance(s, unicode): # py2 only (unicode unresolved on py3) + if str is bytes and isinstance(s, _unicode): # py2 only return s.encode("utf-8") return s diff --git a/extra/esperanto/discovery.py b/extra/esperanto/discovery.py index 7463526af..9b5a24b9e 100644 --- a/extra/esperanto/discovery.py +++ b/extra/esperanto/discovery.py @@ -5,8 +5,25 @@ Copyright (c) 2006-2026 sqlmap developers (https://sqlmap.org) See the file 'LICENSE' for copying permission """ -from .atlas import * -from .records import * +from .atlas import _BANNER_KEYWORDS +from .atlas import _BANNERS +from .atlas import _BINWRAP +from .atlas import _BYTELEN +from .atlas import _CATALOGS +from .atlas import _CHARCODE +from .atlas import _CHARFROM +from .atlas import _COALESCE +from .atlas import _CONCAT +from .atlas import _DUAL +from .atlas import _DUAL_IMPLIES +from .atlas import _HEXFN +from .atlas import _IDENTITY +from .atlas import _LENGTH +from .atlas import _PREFIX +from .atlas import _SUBSTRING +from .atlas import _TEXTCAST +from .records import Cap +from .records import OracleUndecided class _Discovery(object): diff --git a/extra/esperanto/engine.py b/extra/esperanto/engine.py index 7179529dc..d5ea7be15 100644 --- a/extra/esperanto/engine.py +++ b/extra/esperanto/engine.py @@ -5,8 +5,11 @@ Copyright (c) 2006-2026 sqlmap developers (https://sqlmap.org) See the file 'LICENSE' for copying permission """ -from .atlas import * -from .records import * +from .atlas import _FREQ_ORDER +from .atlas import _PRINTABLE_SORTED +from .atlas import _REPL +from .atlas import _unichr +from .records import Dialect from .oracle import _OracleCore from .discovery import _Discovery from .extraction import _Extraction diff --git a/extra/esperanto/enumeration.py b/extra/esperanto/enumeration.py index 2a0e9274f..28709458b 100644 --- a/extra/esperanto/enumeration.py +++ b/extra/esperanto/enumeration.py @@ -5,8 +5,18 @@ Copyright (c) 2006-2026 sqlmap developers (https://sqlmap.org) See the file 'LICENSE' for copying permission """ -from .atlas import * -from .records import * +from .atlas import _BULK_AGG +from .atlas import _COLUMN_SPECS +from .atlas import _HEX_PAYLOAD_CODES +from .atlas import _IDENT_QUOTE +from .atlas import _KEY_SPECS +from .atlas import _REPL +from .atlas import _ROWID +from .atlas import _ROWID_LITBOUND +from .records import BulkResult +from .records import Cap +from .records import InferenceStrategy +from .records import OracleUndecided from .wordlist import commonColumns from .wordlist import commonTables diff --git a/extra/esperanto/extraction.py b/extra/esperanto/extraction.py index db5ea6dfe..e3b01656b 100644 --- a/extra/esperanto/extraction.py +++ b/extra/esperanto/extraction.py @@ -5,8 +5,23 @@ Copyright (c) 2006-2026 sqlmap developers (https://sqlmap.org) See the file 'LICENSE' for copying permission """ -from .atlas import * -from .records import * +import binascii + +from .atlas import _FREQ_ORDER +from .atlas import _HEX_Q_ENCODINGS +from .atlas import _HEXDIGITS +from .atlas import _HEXFN +from .atlas import _isSingleUnicodeScalar +from .atlas import _MAX_HEX_CHAR_NIBBLES +from .atlas import _native +from .atlas import _PRINTABLE_SORTED +from .atlas import _REPL +from .atlas import _SIMILAR_META +from .atlas import _UNICODE_MAX +from .atlas import _unhexlify +from .atlas import _unichr +from .records import Cap +from .records import ExtractResult class _Extraction(object): diff --git a/extra/esperanto/oracle.py b/extra/esperanto/oracle.py index 5cbe526a1..e31da724d 100644 --- a/extra/esperanto/oracle.py +++ b/extra/esperanto/oracle.py @@ -7,8 +7,8 @@ See the file 'LICENSE' for copying permission from contextlib import contextmanager -from .atlas import * -from .records import * +from .records import OracleUndecided +from .records import QueryBudgetExceeded class _OracleCore(object): diff --git a/extra/esperanto/records.py b/extra/esperanto/records.py index fa9d7a792..67733e70f 100644 --- a/extra/esperanto/records.py +++ b/extra/esperanto/records.py @@ -5,9 +5,6 @@ Copyright (c) 2006-2026 sqlmap developers (https://sqlmap.org) See the file 'LICENSE' for copying permission """ -from .atlas import * - - class OracleUndecided(RuntimeError): """The oracle gave no reliable True/False after retries/voting - a transport or observation failure, NOT a definitive answer. Raised so blind extraction fails diff --git a/lib/core/settings.py b/lib/core/settings.py index b9f61edd2..ebf0cb0bb 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -20,7 +20,7 @@ from lib.core.enums import OS from thirdparty import six # sqlmap version (...) -VERSION = "1.10.7.107" +VERSION = "1.10.7.108" TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable" TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34} VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE) diff --git a/lib/core/testing.py b/lib/core/testing.py index c983ebdc6..37f20aef0 100644 --- a/lib/core/testing.py +++ b/lib/core/testing.py @@ -97,6 +97,7 @@ def vulnTest(tests=None, label="vuln"): ("-u \"xpath/search?q=x\" --xpath --flush-session --disable-hashing", ("is vulnerable to XPath injection", "Title: XPath boolean-based blind", "XPath: GET parameter 'q' XML tree", "extracted", "XPath scan complete")), # XPath: error-based detection + boolean oracle + blind XML tree-walking via starts-with character extraction ("-u \"ssti/search?q=x\" --ssti --flush-session --disable-hashing", ("is vulnerable to SSTI", "Title: SSTI Jinja2 injection", "back-end template engine: 'Jinja2'", "in-band arithmetic proof confirmed", "SSTI scan complete")), # SSTI: Jinja2 detection via arithmetic control-pair + boolean oracle + distinguishing probe ("-u \"hql/search?name=admin\" -p name --hql --flush-session --disable-hashing", ("is vulnerable to HQL injection", "back-end: 'Hibernate'", "entity 'Users'", "s3cr3t", "HQL scan complete")), # HQL: error-based Hibernate fingerprint + boolean oracle + error-leaked entity + blind attribute enumeration and substring value extraction + ("-u --flush-session --esperanto --technique=B --banner", ("using the DBMS-agnostic 'Esperanto' engine", "Esperanto dialect verdict: SQLite", "banner: '3.")), # Esperanto: DBMS-agnostic boolean-oracle engine drives --banner end-to-end through the real sqlmap handler (fingerprinting skipped, dialect discovered from scratch, banner blind-extracted) ("-u \"xxe\" --data=\"x\" --xxe --file-read=\"%s\" --flush-session" % vulnserver.XXE_READ_FILE, ("the XML body processes DTD/internal entities", "in-band XXE file-read impact confirmed", "Type: XXE injection", "XXE scan complete")), # XXE: in-band internal-entity reflection (real libxml2/lxml parser) + external file:// entity file read ("-u \"&query=*\" --flush-session --technique=Q --banner", ("Title: SQLite inline queries", "banner: '3.")), ("-d \"\" --flush-session --dump -T creds --dump-format=SQLITE --binary-fields=password_hash --where \"user_id=5\"", ("3137396164343563366365326362393763663130323965323132303436653831", "dumped to SQLITE database")),