From 96fec6864e7c8508330f3d0900819540773d141f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0tampar?= Date: Tue, 4 Aug 2026 22:46:04 +0200 Subject: [PATCH 1/5] Minor patch --- lib/core/settings.py | 2 +- lib/utils/jwt.py | 3 ++- tests/test_jwt.py | 7 +++++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/lib/core/settings.py b/lib/core/settings.py index ee2ac49de4a..1330f7c2231 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -20,7 +20,7 @@ from thirdparty import six # sqlmap version (...) -VERSION = "1.10.8.1" +VERSION = "1.10.8.2" 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/utils/jwt.py b/lib/utils/jwt.py index 358e62b6cf9..88b5490c92c 100644 --- a/lib/utils/jwt.py +++ b/lib/utils/jwt.py @@ -14,6 +14,7 @@ from lib.core.convert import encodeBase64 from lib.core.convert import getBytes from lib.core.convert import getText +from thirdparty import six # a compact JSON Web Token: base64url(header).base64url(payload).base64url(signature); a header always starts # with '{"' which base64url-encodes to the literal prefix 'eyJ', so this matches JWTs embedded in a larger value @@ -46,7 +47,7 @@ def parseJWT(token): except Exception: return None - if not isinstance(header, dict) or "alg" not in header: + if not isinstance(header, dict) or not isinstance(header.get("alg"), six.string_types): return None return {"header": header, "payload": payload, "signature": signature, "signingInput": token.rsplit('.', 1)[0], "raw": token} diff --git a/tests/test_jwt.py b/tests/test_jwt.py index 31d0cf66859..b1ff857d045 100644 --- a/tests/test_jwt.py +++ b/tests/test_jwt.py @@ -24,6 +24,7 @@ from lib.core.enums import PLACE from lib.utils.jwt import auditJWT from lib.utils.jwt import crackHMAC +from lib.utils.jwt import encodeSegment from lib.utils.jwt import findJWTs from lib.utils.jwt import forgeJWT from lib.utils.jwt import parseJWT @@ -41,6 +42,12 @@ def test_parse_rejects_non_jwt(self): for value in ("", "a.b", "a.b.c.d", "not.a.jwt", "eyJx.eyJx"): self.assertIsNone(parseJWT(value)) + def test_parse_rejects_non_string_alg(self): + # RFC 7515: "alg" MUST be a string; a crafted token with e.g. an integer "alg" must not parse + # (a permissive gate here would let a non-string "alg" reach auditJWT's alg.strip() and crash) + token = "%s.%s." % (encodeSegment({"alg": 123}), encodeSegment({})) + self.assertIsNone(parseJWT(token)) + def test_forge_none_is_unsigned(self): token = forgeJWT({"alg": "none"}, {"user": "admin"}) self.assertTrue(token.endswith(".")) From a9f5d30b4acbc330b4c162e18a6003daa4f9720f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0tampar?= Date: Tue, 4 Aug 2026 22:58:19 +0200 Subject: [PATCH 2/5] Minor patch --- lib/core/settings.py | 2 +- plugins/generic/filesystem.py | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/core/settings.py b/lib/core/settings.py index 1330f7c2231..e2d23d97142 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -20,7 +20,7 @@ from thirdparty import six # sqlmap version (...) -VERSION = "1.10.8.2" +VERSION = "1.10.8.3" 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/plugins/generic/filesystem.py b/plugins/generic/filesystem.py index 69ceebb9f55..be6fbd30d12 100644 --- a/plugins/generic/filesystem.py +++ b/plugins/generic/filesystem.py @@ -48,6 +48,8 @@ def __init__(self): self.tblField = "data" def _checkFileLength(self, localFile, remoteFile, fileRead=False): + lengthQuery = None + if Backend.isDbms(DBMS.MYSQL): lengthQuery = "LENGTH(LOAD_FILE('%s'))" % remoteFile @@ -70,6 +72,9 @@ def _checkFileLength(self, localFile, remoteFile, fileRead=False): if fileRead and Backend.isDbms(DBMS.PGSQL): logger.info("length of read file '%s' cannot be checked on PostgreSQL" % remoteFile) sameFile = True + elif lengthQuery is None: + logger.info("length of the %s file '%s' cannot be checked on %s" % ("read" if fileRead else "written", remoteFile, Backend.getDbms())) + sameFile = True else: logger.debug("checking the length of the remote file '%s'" % remoteFile) remoteFileSize = inject.getValue(lengthQuery, resumeValue=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) From dbe2734b71503e55ba5db9caaa7d0f44111c1172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0tampar?= Date: Tue, 4 Aug 2026 23:02:00 +0200 Subject: [PATCH 3/5] Minor update --- lib/core/settings.py | 2 +- tests/test_hql.py | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/core/settings.py b/lib/core/settings.py index e2d23d97142..861e5673f52 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -20,7 +20,7 @@ from thirdparty import six # sqlmap version (...) -VERSION = "1.10.8.3" +VERSION = "1.10.8.4" 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/tests/test_hql.py b/tests/test_hql.py index 0712b5ce04e..113c7ac3858 100644 --- a/tests/test_hql.py +++ b/tests/test_hql.py @@ -48,6 +48,30 @@ def test_short_entity(self): self.assertEqual(hql._shortEntity("User"), "User") +class TestOriginalValue(unittest.TestCase): + def setUp(self): + self.originalParameters = hql.conf.parameters + self.originalParamDict = hql.conf.paramDict + + def tearDown(self): + hql.conf.parameters = self.originalParameters + hql.conf.paramDict = self.originalParamDict + + def test_original_value_parsed_from_raw_query_string(self): + hql.conf.parameters = {"GET": "id=1&name=alice"} + self.assertEqual(hql._originalValue("GET", "name"), "alice") + + def test_original_value_falls_back_to_param_dict(self): + hql.conf.parameters = {} + hql.conf.paramDict = {"GET": {"name": "bob"}} + self.assertEqual(hql._originalValue("GET", "name"), "bob") + + def test_original_value_missing_returns_empty(self): + hql.conf.parameters = {} + hql.conf.paramDict = {} + self.assertEqual(hql._originalValue("GET", "nope"), "") + + class TestBoundary(unittest.TestCase): def test_wrap_string(self): b = hql.Boundary("' OR ", " OR '1'='2", True) From ede662eca6b95b7b1e70dbb2ea71fca1d6d6e6b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0tampar?= Date: Tue, 4 Aug 2026 23:12:27 +0200 Subject: [PATCH 4/5] Minor patch --- lib/core/settings.py | 2 +- plugins/dbms/mssqlserver/syntax.py | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/core/settings.py b/lib/core/settings.py index 861e5673f52..8653a9dd262 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -20,7 +20,7 @@ from thirdparty import six # sqlmap version (...) -VERSION = "1.10.8.4" +VERSION = "1.10.8.5" 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/plugins/dbms/mssqlserver/syntax.py b/plugins/dbms/mssqlserver/syntax.py index 183ce9462c9..c60441855dd 100644 --- a/plugins/dbms/mssqlserver/syntax.py +++ b/plugins/dbms/mssqlserver/syntax.py @@ -16,9 +16,22 @@ def escape(expression, quote=True): True >>> Syntax.escape(u"SELECT 'abcd\xebfgh' FROM foobar") == "SELECT CHAR(97)+CHAR(98)+CHAR(99)+CHAR(100)+NCHAR(235)+CHAR(102)+CHAR(103)+CHAR(104) FROM foobar" True + >>> Syntax.escape(u"SELECT '\U0001f600' FROM foobar") == "SELECT NCHAR(55357)+NCHAR(56832) FROM foobar" + True """ def escaper(value): - return "+".join("%s(%d)" % ("CHAR" if _ < 128 else "NCHAR", _) for _ in getOrds(value)) + chars = [] + + for _ in getOrds(value): + if _ < 128: + chars.append("CHAR(%d)" % _) + elif _ < 0x10000: + chars.append("NCHAR(%d)" % _) + else: + _ -= 0x10000 + chars.append("NCHAR(%d)+NCHAR(%d)" % (0xd800 + (_ >> 10), 0xdc00 + (_ & 0x3ff))) # SQL Server's NCHAR() only accepts BMP values without SC collation, so split into a surrogate pair + + return "+".join(chars) return Syntax._escape(expression, quote, escaper) From fc503ee8d5f77b582fd9500b2d2f372b64db3d77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0tampar?= Date: Tue, 4 Aug 2026 23:38:10 +0200 Subject: [PATCH 5/5] Minor update of doctest --- extra/dbwire/firebird.py | 13 ++++++++++++- lib/core/settings.py | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/extra/dbwire/firebird.py b/extra/dbwire/firebird.py index 0e1c8ec5afb..647070723d0 100644 --- a/extra/dbwire/firebird.py +++ b/extra/dbwire/firebird.py @@ -341,7 +341,18 @@ def _b2i_signed(b): return n def _scaled(n, scale): - # integer n represents n * 10**scale (scale <= 0); render as an exact decimal string + """ + integer n represents n * 10**scale (scale <= 0); render as an exact decimal string + + >>> _scaled(1234, -2) + '12.34' + >>> _scaled(-5, -2) + '-0.05' + >>> _scaled(5, -4) + '0.0005' + >>> _scaled(7, 0) + '7' + """ if scale >= 0: return str(n * (10 ** scale)) digits = "%0*d" % (-scale + 1, abs(n)) diff --git a/lib/core/settings.py b/lib/core/settings.py index 8653a9dd262..70cf154e89a 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -20,7 +20,7 @@ from thirdparty import six # sqlmap version (...) -VERSION = "1.10.8.5" +VERSION = "1.10.8.6" 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)