From e10092efcda67304f59a13f980c5012d95e98905 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0tampar?= Date: Fri, 4 Sep 2026 09:03:25 +0200 Subject: [PATCH 1/2] Fixes #6104 --- lib/core/option.py | 7 +++++++ lib/core/settings.py | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/core/option.py b/lib/core/option.py index 5cf18f71732..7624f884a56 100644 --- a/lib/core/option.py +++ b/lib/core/option.py @@ -905,6 +905,13 @@ def _setTamperingFunctions(): priority = PRIORITY.NORMAL if not hasattr(module, "__priority__") else module.__priority__ priority = priority if priority is not None else PRIORITY.LOWEST + if not isinstance(priority, int): + warnMsg = "tamper module '%s' has an invalid value for '__priority__' " % filename[:-3] + warnMsg += "(assuming '%d')" % PRIORITY.NORMAL + logger.warning(warnMsg) + + priority = PRIORITY.NORMAL + for name, function in inspect.getmembers(module, inspect.isfunction): if name == "tamper" and (hasattr(inspect, "signature") and all(_ in inspect.signature(function).parameters for _ in ("payload", "kwargs")) or inspect.getargspec(function).args and inspect.getargspec(function).keywords == "kwargs"): found = True diff --git a/lib/core/settings.py b/lib/core/settings.py index 4dbb9e225e3..6f1586f7aa1 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -20,7 +20,7 @@ from thirdparty import six # sqlmap version (...) -VERSION = "1.10.9.2" +VERSION = "1.10.9.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) From 1ee368f78a73ccc1c193af32d4e70c1244be5865 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20=C5=A0tampar?= Date: Fri, 4 Sep 2026 09:47:33 +0200 Subject: [PATCH 2/2] Fixes #6105 --- lib/controller/checks.py | 30 +++++++++++++++++++----------- lib/core/settings.py | 15 +++++++++------ tests/test_heuristic_signatures.py | 21 +++++++++++++++++++++ 3 files changed, 49 insertions(+), 17 deletions(-) diff --git a/lib/controller/checks.py b/lib/controller/checks.py index 1ebbb81c4c0..c94c1529f66 100644 --- a/lib/controller/checks.py +++ b/lib/controller/checks.py @@ -1223,6 +1223,14 @@ def _(page): if conf.beep: beep() + def _search(regex): + # Note: on a rare (e.g. huge) response the regex engine itself can fail, and losing one + # advisory heuristic beats losing the whole run (e.g. #5994 and #6105) + try: + return re.search(regex, page or "") + except (SystemError, RuntimeError) as ex: + logger.debug("skipping heuristic check because of a regex engine failure ('%s')" % getSafeExString(ex)) + try: for match in re.finditer(FI_ERROR_REGEX, page or ""): if randStr1.lower() in match.group(0).lower(): @@ -1234,71 +1242,71 @@ def _(page): break except (SystemError, RuntimeError) as ex: - logger.debug("Skipping FI heuristic due to regex failure: %s", getSafeExString(ex)) + logger.debug("skipping heuristic check because of a regex engine failure ('%s')" % getSafeExString(ex)) - if not conf.nosql and re.search(NOSQL_ERROR_REGEX, page or ""): + if not conf.nosql and _search(NOSQL_ERROR_REGEX): infoMsg = "heuristic (NoSQL) test shows that %sparameter '%s' might be vulnerable to NoSQL injection attacks (rerun with switch '--nosql')" % ("%s " % paramType if paramType != parameter else "", parameter) logger.info(infoMsg) if conf.beep: beep() - if not conf.graphql and re.search(GRAPHQL_ERROR_REGEX, page or ""): + if not conf.graphql and _search(GRAPHQL_ERROR_REGEX): infoMsg = "heuristic (GraphQL) test shows that %sparameter '%s' appears to be a GraphQL endpoint (rerun with switch '--graphql')" % ("%s " % paramType if paramType != parameter else "", parameter) logger.info(infoMsg) if conf.beep: beep() - if not conf.ldap and re.search(LDAP_ERROR_REGEX, page or ""): + if not conf.ldap and _search(LDAP_ERROR_REGEX): infoMsg = "heuristic (LDAP) test shows that %sparameter '%s' might be vulnerable to LDAP injection (rerun with switch '--ldap')" % ("%s " % paramType if paramType != parameter else "", parameter) logger.info(infoMsg) if conf.beep: beep() - if not conf.xpath and re.search(XPATH_ERROR_REGEX, page or ""): + if not conf.xpath and _search(XPATH_ERROR_REGEX): infoMsg = "heuristic (XPath) test shows that %sparameter '%s' might be vulnerable to XPath injection (rerun with switch '--xpath')" % ("%s " % paramType if paramType != parameter else "", parameter) logger.info(infoMsg) if conf.beep: beep() - if not conf.ssti and re.search(SSTI_ERROR_REGEX, page or ""): + if not conf.ssti and _search(SSTI_ERROR_REGEX): infoMsg = "heuristic (SSTI) test shows that %sparameter '%s' might be vulnerable to server-side template injection (rerun with switch '--ssti')" % ("%s " % paramType if paramType != parameter else "", parameter) logger.info(infoMsg) if conf.beep: beep() - if not conf.hql and re.search(HQL_ERROR_REGEX, page or ""): + if not conf.hql and _search(HQL_ERROR_REGEX): infoMsg = "heuristic (HQL) test shows that %sparameter '%s' might be vulnerable to HQL/JPQL (Hibernate ORM) injection (rerun with switch '--hql')" % ("%s " % paramType if paramType != parameter else "", parameter) logger.info(infoMsg) if conf.beep: beep() - if not conf.xslt and re.search(XSLT_ERROR_REGEX, page or ""): + if not conf.xslt and _search(XSLT_ERROR_REGEX): infoMsg = "heuristic (XSLT) test shows that %sparameter '%s' might be vulnerable to XSLT injection (rerun with switch '--xslt')" % ("%s " % paramType if paramType != parameter else "", parameter) logger.info(infoMsg) if conf.beep: beep() - if not conf.sparql and re.search(SPARQL_ERROR_REGEX, page or ""): + if not conf.sparql and _search(SPARQL_ERROR_REGEX): infoMsg = "heuristic (SPARQL) test shows that %sparameter '%s' might be vulnerable to SPARQL injection (rerun with switch '--sparql')" % ("%s " % paramType if paramType != parameter else "", parameter) logger.info(infoMsg) if conf.beep: beep() - if not conf.odata and re.search(ODATA_ERROR_REGEX, page or ""): + if not conf.odata and _search(ODATA_ERROR_REGEX): infoMsg = "heuristic (OData) test shows that %sparameter '%s' might be vulnerable to OData $filter injection (rerun with switch '--odata')" % ("%s " % paramType if paramType != parameter else "", parameter) logger.info(infoMsg) if conf.beep: beep() - if not conf.xxe and kb.postHint in (POST_HINT.XML, POST_HINT.SOAP) and re.search(XXE_ERROR_REGEX, page or ""): + if not conf.xxe and kb.postHint in (POST_HINT.XML, POST_HINT.SOAP) and _search(XXE_ERROR_REGEX): infoMsg = "heuristic (XXE) test shows that the XML request body might be vulnerable to XML External Entity injection (rerun with switch '--xxe')" logger.info(infoMsg) diff --git a/lib/core/settings.py b/lib/core/settings.py index 6f1586f7aa1..c63fb98705c 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -20,7 +20,7 @@ from thirdparty import six # sqlmap version (...) -VERSION = "1.10.9.3" +VERSION = "1.10.9.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) @@ -1193,7 +1193,10 @@ ("Python ElementTree", r"xml\.etree\.ElementTree\.(?:ParseError|Element)"), # NOT XSLT: a dedicated '--xslt' engine owns those errors now, and claiming them here made every # XSLT parser error suggest '--xpath' as well - ("Generic XPath", r"XPath.*?(?:error|exception|syntax)"), + # NOTE: the gap has to stay bounded (like in 'Handlebars' below). An unbounded '.*?' turns this + # into a quadratic scan of every long line that merely carries the word 'xpath' (e.g. minified + # JS/JSON), which took ~25s on a 400KB response - and blew up the regex engine itself (#6105) + ("Generic XPath", r"XPath[^\n]{0,100}?(?:error|exception|syntax)"), ("Generic XPath", r"Invalid XPath|XPath evaluation failed"), ) @@ -1337,7 +1340,7 @@ ("Velocity", r"org\.apache\.velocity\.(?:runtime|exception)\.\w+|ParseErrorException|MethodInvocationException|ResourceNotFoundException"), ("Spring EL / Thymeleaf", r"org\.springframework\.expression\.\w+|org\.thymeleaf\.\w+|SpelEvaluationException|TemplateProcessingException|ExpressionParsingException"), ("Struts2 (OGNL)", r"ognl\.(?:OgnlException|NoSuchPropertyException|MethodFailedException|InappropriateExpressionException|ExpressionSyntaxException)|com\.opensymphony\.xwork2|org\.apache\.struts2|There is no Action mapped for|Struts (?:Problem Report|has detected an unhandled exception)"), - ("ERB", r"\(erb\):\d+|NameError.*undefined local variable"), + ("ERB", r"\(erb\):\d+|NameError[^\n]{0,100}?undefined local variable"), # NOTE: these must stay anchored to a diagnostic. The bare product names matched any page that # carries the word 'pug'/'jade'/'handlebars' (a surname, a colour, a