diff --git a/extra/esperanto/extraction.py b/extra/esperanto/extraction.py index faa754f65..4338d3778 100644 --- a/extra/esperanto/extraction.py +++ b/extra/esperanto/extraction.py @@ -288,7 +288,7 @@ class _Extraction(object): if mode == "code": code = self.dialect.charcode[1].format(expr=one) - ordered = self._comparator in ("gt", "between") + ordered = self._comparator != "membership" # gt/between OR an operator-free rung (all bisect via _gtNum) if codes is not None: # restricted-alphabet (e.g. the hex-framed dump payload): a small ASCII # set. no per-char verify - ASCII codes are unambiguous across charcode diff --git a/lib/core/settings.py b/lib/core/settings.py index 8d669818a..e2753a9eb 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.171" +VERSION = "1.10.7.172" 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_esperanto.py b/tests/test_esperanto.py index fcb797ccf..965ff6269 100644 --- a/tests/test_esperanto.py +++ b/tests/test_esperanto.py @@ -539,19 +539,22 @@ class TestEsperanto(unittest.TestCase): self.assertEqual(esp.extract(_SECRET_EXPR), "admin") self.assertEqual(len((esp.dump("users") or {}).get("rows") or []), 3) # BETWEEN keyset pages all - def test_disguise_gt_and_between_blocked_use_in(self): - # '<'/'>' AND BETWEEN gone: order-free IN() subset bisection for the chars and - # NOT IN() paging for the rows - needs only '=' membership + def test_disguise_gt_and_between_blocked_use_operator_free(self): + # '<'/'>' AND BETWEEN gone: rather than drop to slow order-free membership, the ladder + # finds an ORDERED operator-free rung (SIGN((e)-(n))=1 etc.) that needs no comparison + # operator - keeping efficient log2 bisection alive. esp = Esperanto(_disguisedOracle(blocked=r">|<|BETWEEN")) esp.discover() - self.assertEqual(esp._comparator, "membership") + self.assertEqual(esp._comparator, "sign") self.assertEqual(esp.extract(_SECRET_EXPR), "admin") - self.assertEqual(len((esp.dump("users") or {}).get("rows") or []), 3) # NOT IN() pages all + self.assertEqual(len((esp.dump("users") or {}).get("rows") or []), 3) # ordered rung still pages all def test_disguise_no_ordering_no_in_still_extracts(self): - # the hard floor: no '<'/'>', no BETWEEN, no IN - only '=' equality. Values + # the hard floor: no '<'/'>', no BETWEEN, no IN, and no operator-free ordered rung + # (SIGN/ABS/LEAST/GREATEST/NULLIF/WIDTH_BUCKET/INTERVAL) - only '=' equality. Values # still extract (linear scan); multi-row dump honestly degrades (can't page) - esp = Esperanto(_disguisedOracle(blocked=r">|<|BETWEEN|\bIN\s*\(")) + esp = Esperanto(_disguisedOracle( + blocked=r">|<|BETWEEN|\bIN\s*\(|SIGN\(|ABS\(|LEAST\(|GREATEST\(|NULLIF\(|WIDTH_BUCKET\(|INTERVAL\(")) esp.discover() self.assertEqual(esp.extract(_SECRET_EXPR), "admin") rows = (esp.dump("users") or {}).get("rows")