Skip to content

Commit f932a3f

Browse files
committed
Minor refactoring
1 parent e0269ac commit f932a3f

6 files changed

Lines changed: 30 additions & 139 deletions

File tree

data/txt/sha256sums.txt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -181,15 +181,15 @@ f8de57606325456928e46ae2896f5f8bbec9ad18b1c644b492a566fa992216f6 lib/core/decor
181181
5387168e5dfedd94ae22af7bb255f27d6baaca50b24179c6b98f4f325f5cc7b4 lib/core/exception.py
182182
1966ca704961fb987ab757f0a4afddbf841d1a880631b701487c75cef63d60c3 lib/core/__init__.py
183183
914a13ee21fd610a6153a37cbe50830fcbd1324c7ebc1e7fc206d5e598b0f7ad lib/core/log.py
184-
33ed53b263fa766a808be6797dd812822bb115d3b9db6e3a34763f500f5359e8 lib/core/optiondict.py
184+
5a576f802f1298d0aa357e766ae6502fa53cacbbe0b1d328b7410a8b20a885b2 lib/core/optiondict.py
185185
e033b20a0f7821797a10f4bf4235723f38c7db551c611fbb713faa621b123c4a lib/core/option.py
186186
21b2b1745107c211fc7593923a3da7a808d40763c00091c28de5f7c129bcf3bc lib/core/patch.py
187187
49c0fa7e3814dfda610d665ee02b12df299b28bc0b6773815b4395514ddf8dec lib/core/profiling.py
188188
0c36a65b6237732eb001d333f80f0c58c088ff01ae80cf07e4dcc6da2a806364 lib/core/readlineng.py
189189
9bf174058f15d14e24e94f9aaf42df045119d3617c6c54bd2f3af79b462f331d lib/core/replication.py
190190
0b8c38a01bb01f843d94a6c5f2075ee47520d0c4aa799cecea9c3e2c5a4a23a6 lib/core/revision.py
191191
888daba83fd4a34e9503fe21f01fef4cc730e5cde871b1d40e15d4cbc847d56c lib/core/session.py
192-
2498555483d50cf55f24dcb82b3253816a1ad6c3325b17e502d5063f2c9cbc87 lib/core/settings.py
192+
098e5d86a0da05d4be5f5ed5371083954be2369abce57fda4bd906d12e1f8870 lib/core/settings.py
193193
c7804223319e18eb0b8e2cbf0a8b6896d1cefb7b0b1a2e9f1cf826a8a3b56750 lib/core/shell.py
194194
a2e98a94b231432736d6b304fc75525c8b5fdb4768c418387c5b4c1a610dad64 lib/core/subprocessng.py
195195
19f1e3c5e3ba703d28d510cd7a9ab8284d5fbe9df5ce7e77c86e5931571364b7 lib/core/target.py
@@ -200,7 +200,7 @@ b9aacb840310173202f79c2ba125b0243003ee6b44c92eca50424f2bdfc83c02 lib/core/unesc
200200
2400e465fa4d13e4c32795910878c71ff212e4361b46428d57ce43983f5e997c lib/core/wordlist.py
201201
1966ca704961fb987ab757f0a4afddbf841d1a880631b701487c75cef63d60c3 lib/__init__.py
202202
54bfd31ebded3ffa5848df1c644f196eb704116517c7a3d860b5d081e984d821 lib/parse/banner.py
203-
316cdcb3d8d839dab639ed7eb4935780375d49c93371edbd6224976cbb968c2e lib/parse/cmdline.py
203+
403ebb5b54531cf907a30ed439fc881cf3cbae68c3a4ec600c75312e5f6b9001 lib/parse/cmdline.py
204204
02d82e4069bd98c52755417f8b8e306d79945672656ac24f1a45e7a6eff4b158 lib/parse/configfile.py
205205
c5b258be7485089fac9d9cd179960e774fbd85e62836dc67cce76cc028bb6aeb lib/parse/handler.py
206206
5c9a9caee948843d5537745640cc7b98d70a0412cc0949f59d4ebe8b2907c06c lib/parse/headers.py
@@ -247,7 +247,7 @@ c3e5cf7e5e35ae5fd86b63a515b37e6f06e61c70d2690252f2ee8373aa16637e lib/techniques
247247
44401cad3e39ae9fb899ed5d0e2fdd0879561de05c3117f17f3b0db54f4e3724 lib/techniques/nosql/__init__.py
248248
bde75d41ac3e5747b96d2af4c33922573158cb43b48714a28490d6720dd85d89 lib/techniques/nosql/inject.py
249249
1966ca704961fb987ab757f0a4afddbf841d1a880631b701487c75cef63d60c3 lib/techniques/ssti/__init__.py
250-
8eaf90c2fa517a4577467ac0d7534a927c23931b946b27e88e63ae022f794a1c lib/techniques/ssti/inject.py
250+
14637b64878248e5965887b07aa68e62615dac88e2ffc6c3a581430bdd4e309e lib/techniques/ssti/inject.py
251251
1966ca704961fb987ab757f0a4afddbf841d1a880631b701487c75cef63d60c3 lib/techniques/union/__init__.py
252252
ceec65f8cb7c3254c4671351c837418c76ac5bc55ccbc40779f67231b54d7085 lib/techniques/union/test.py
253253
c65766f71e285fc85cdf58e7448c4c1d015af2a9dbb44fa3b665a9f13362fbcc lib/techniques/union/use.py
@@ -643,7 +643,7 @@ cec98d72992c0799229a780fa7f0d7f3fb01ec2d708187ce0e4a05c8612f291b tests/test_saf
643643
a1c6cda1e5b483f61e6a4f8ddd0b06a15ddaa3fd2119bfb9dbd9cc970d7a751d tests/test_settings_regex.py
644644
29d0278e3718b0fee422d3f6bb85ca02560138d48cd76f9fe1f35ac19d96071b tests/test_sgmllib.py
645645
d3d991331096e16e5019de3d652e9fff92c09bd9f97c50b1c2c3ceb0ed49b17e tests/test_sqlparse.py
646-
4a9409a070770cc6300ed2b0c954254273479252fa602ffd19d78917f895756c tests/test_ssti.py
646+
412a61053c2531cc0380b34dfd01d52bd118f6a6473728c069c467054c7e3c8e tests/test_ssti.py
647647
8bcbf1091134dd0a62f6201f8b3645ed87b5ff2f7ba40a87231a29dac412591f tests/test_strings.py
648648
8f1c5f0f337ecd26d35c5551060034e0aa33a62cce5385fc1227fdc485f6383e tests/test_tamper.py
649649
67472bd71c20782cc0f738e2c2e674c29d6985669e14d15b69baef7d0e33de62 tests/test_target_parsing.py

lib/core/optiondict.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,6 @@
173173
"lastChar": "integer",
174174
"sqlQuery": "string",
175175
"sqlShell": "boolean",
176-
"sstiQuery": "string",
177-
"sstiShell": "boolean",
178176
"sqlFile": "string",
179177
},
180178

lib/core/settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from thirdparty import six
2121

2222
# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
23-
VERSION = "1.10.6.197"
23+
VERSION = "1.10.6.198"
2424
TYPE = "dev" if VERSION.count('.') > 2 and VERSION.split('.')[-1] != '0' else "stable"
2525
TYPE_COLORS = {"dev": 33, "stable": 90, "pip": 34}
2626
VERSION_STRING = "sqlmap/%s#%s" % ('.'.join(VERSION.split('.')[:-1]) if VERSION.count('.') > 2 and VERSION.split('.')[-1] == '0' else VERSION, TYPE)

lib/parse/cmdline.py

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ def cmdLineParser(argv=None):
133133
help="Parse target(s) from Burp or WebScarab proxy log file")
134134

135135
target.add_argument("-m", dest="bulkFile",
136-
help="Scan multiple targets given in a textual file ")
136+
help="Scan multiple targets given in a textual file")
137137

138138
target.add_argument("-r", dest="requestFile",
139139
help="Load HTTP request from a file")
@@ -335,7 +335,7 @@ def cmdLineParser(argv=None):
335335
help="Skip testing for given parameter(s)")
336336

337337
injection.add_argument("--skip-static", dest="skipStatic", action="store_true",
338-
help="Skip testing parameters that not appear to be dynamic")
338+
help="Skip testing parameters that do not appear to be dynamic")
339339

340340
injection.add_argument("--param-exclude", dest="paramExclude",
341341
help="Regexp to exclude parameters from testing (e.g. \"ses\")")
@@ -442,21 +442,6 @@ def cmdLineParser(argv=None):
442442
techniques.add_argument("--second-req", dest="secondReq",
443443
help="Load second-order HTTP request from file")
444444

445-
techniques.add_argument("--graphql", dest="graphql", action="store_true",
446-
help="Test for GraphQL injection")
447-
448-
techniques.add_argument("--ldap", dest="ldap", action="store_true",
449-
help="Test for LDAP injection")
450-
451-
techniques.add_argument("--nosql", dest="nosql", action="store_true",
452-
help="Test for NoSQL injection")
453-
454-
techniques.add_argument("--xpath", dest="xpath", action="store_true",
455-
help="Test for XPath injection")
456-
457-
techniques.add_argument("--ssti", dest="ssti", action="store_true",
458-
help="Test for server-side template injection")
459-
460445
# Fingerprint options
461446
fingerprint = parser.add_argument_group("Fingerprint", "These options can be used to perform a back-end database management system version fingerprint")
462447

@@ -515,7 +500,7 @@ def cmdLineParser(argv=None):
515500
help="Dump DBMS database table entries")
516501

517502
enumeration.add_argument("--dump-all", dest="dumpAll", action="store_true",
518-
help="Dump all DBMS databases tables entries")
503+
help="Dump entries of all DBMS database tables")
519504

520505
enumeration.add_argument("--search", dest="search", action="store_true",
521506
help="Search column(s), table(s) and/or database name(s)")
@@ -571,12 +556,6 @@ def cmdLineParser(argv=None):
571556
enumeration.add_argument("--sql-shell", dest="sqlShell", action="store_true",
572557
help="Prompt for an interactive SQL shell")
573558

574-
enumeration.add_argument("--ssti-query", dest="sstiQuery",
575-
help="SSTI expression to evaluate in-band on the vulnerable parameter")
576-
577-
enumeration.add_argument("--ssti-shell", dest="sstiShell", action="store_true",
578-
help="Prompt for an interactive SSTI expression shell")
579-
580559
enumeration.add_argument("--sql-file", dest="sqlFile",
581560
help="Execute SQL statements from given file(s)")
582561

@@ -626,11 +605,10 @@ def cmdLineParser(argv=None):
626605
help="Prompt for an OOB shell, Meterpreter or VNC")
627606

628607
takeover.add_argument("--os-smbrelay", dest="osSmb", action="store_true",
629-
help="One click prompt for an OOB shell, Meterpreter or VNC")
608+
help="One-click prompt for an OOB shell, Meterpreter or VNC")
630609

631610
takeover.add_argument("--os-bof", dest="osBof", action="store_true",
632-
help="Stored procedure buffer overflow "
633-
"exploitation")
611+
help="Stored procedure buffer overflow exploitation")
634612

635613
takeover.add_argument("--priv-esc", dest="privEsc", action="store_true",
636614
help="Database process user privilege escalation")
@@ -788,6 +766,24 @@ def cmdLineParser(argv=None):
788766
general.add_argument("--web-root", dest="webRoot",
789767
help="Web server document root directory (e.g. \"/var/www\")")
790768

769+
# Non-SQL injection options
770+
nonsql = parser.add_argument_group("Non-SQL injection", "These options can be used to test for non-SQL injection types")
771+
772+
nonsql.add_argument("--graphql", dest="graphql", action="store_true",
773+
help="Test for GraphQL injection")
774+
775+
nonsql.add_argument("--ldap", dest="ldap", action="store_true",
776+
help="Test for LDAP injection")
777+
778+
nonsql.add_argument("--nosql", dest="nosql", action="store_true",
779+
help="Test for NoSQL injection")
780+
781+
nonsql.add_argument("--xpath", dest="xpath", action="store_true",
782+
help="Test for XPath injection")
783+
784+
nonsql.add_argument("--ssti", dest="ssti", action="store_true",
785+
help="Test for server-side template injection")
786+
791787
# Miscellaneous options
792788
miscellaneous = parser.add_argument_group("Miscellaneous", "These options do not fit into any other category")
793789

lib/techniques/ssti/inject.py

Lines changed: 1 addition & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,6 @@ def _arithmeticPayload(fmt, a, b):
5959
return fmt.replace("%d", str(a), 1).replace("%d", str(b), 1)
6060

6161

62-
def _expressionPayload(fmt, value):
63-
# Same rationale as _arithmeticPayload(): literal %s substitution so '%'-delimited engines
64-
# (notably ERB) can wrap expressions instead of crashing on fmt % value.
65-
return fmt.replace("%s", value, 1)
66-
67-
6862
def _degroup(text):
6963
# Strip digit-group (thousands) separators so an arithmetic result still matches when the
7064
# engine formats large numbers with grouping (e.g. FreeMarker renders 234*567 as "132,678").
@@ -642,7 +636,7 @@ def sstiScan():
642636
place, parameter, engine, evidence = slot
643637
from lib.core.common import readInput
644638

645-
wantsTakeover = any(conf.get(_) for _ in ("osCmd", "osShell", "sstiQuery", "sstiShell"))
639+
wantsTakeover = any(conf.get(_) for _ in ("osCmd", "osShell"))
646640

647641
# If the user did not ask for exploitation, confirm (benignly) whether OS command
648642
# execution is reachable and, if so, advise the relevant switches.
@@ -651,20 +645,6 @@ def sstiScan():
651645
"you are advised to try '--os-shell' (interactive) or "
652646
"'--os-cmd=<command>' (single command)" % engine.name)
653647

654-
# --ssti-query: user-provided expression evaluated in-band
655-
if conf.get("sstiQuery"):
656-
_evalExpression(place, parameter, engine, conf.sstiQuery)
657-
658-
# --ssti-shell: interactive expression evaluation loop (interactive even under --batch,
659-
# like sqlmap's SQL --sql-shell/--os-shell, which read straight from the terminal)
660-
if conf.get("sstiShell"):
661-
logger.info("calling SSTI shell. Enter expressions (e.g. 7*7) or 'exit'/'quit' to leave")
662-
while True:
663-
expr = readInput("ssti-shell> ", checkBatch=False)
664-
if not expr or expr.strip().lower() in ("exit", "quit"):
665-
break
666-
_evalExpression(place, parameter, engine, expr.strip())
667-
668648
# --os-cmd / --os-shell: RCE via SSTI (reuses existing SQL takeover flags)
669649
if conf.get("osCmd") or conf.get("osShell"):
670650
if not _canTakeover(engine, evidence):
@@ -692,56 +672,6 @@ def _escapeSingleQuoted(value):
692672
return value.replace("\\", "\\\\").replace("'", "\\'")
693673

694674

695-
def _evalExpression(place, parameter, engine, expr):
696-
"""Wrap expr in the engine's expression format, extract result between
697-
random markers for deterministic output, fall back to baseline diff."""
698-
699-
if not engine.expressionFmt:
700-
logger.error("expression evaluation not supported for engine '%s'" % engine.name)
701-
return
702-
703-
original = _originalValue(place, parameter) or ""
704-
startMarker = randomStr(length=8, lowercase=True)
705-
endMarker = randomStr(length=8, lowercase=True)
706-
707-
# Three-part payload: marker, expression, marker -- each in its own template tag
708-
# so the expression is evaluated independently of the markers
709-
payload = original + _expressionPayload(engine.expressionFmt, "'%s'" % startMarker)
710-
payload += " " + _expressionPayload(engine.expressionFmt, expr)
711-
payload += " " + _expressionPayload(engine.expressionFmt, "'%s'" % endMarker)
712-
page = _send(place, parameter, payload)
713-
714-
if not page:
715-
logger.warning("no response for SSTI expression '%s'" % expr)
716-
return
717-
718-
text = getUnicode(page)
719-
result = None
720-
721-
# Extract content between the random markers
722-
if startMarker in text and endMarker in text:
723-
start = text.index(startMarker) + len(startMarker)
724-
end = text.index(endMarker, start)
725-
result = text[start:end].strip()
726-
727-
# Fallback: diff against baseline
728-
if not result:
729-
baseline = _send(place, parameter, original)
730-
if baseline:
731-
sm = difflib.SequenceMatcher(None, getUnicode(baseline), text)
732-
parts = []
733-
for tag, i1, i2, j1, j2 in sm.get_opcodes():
734-
if tag in ("insert", "replace"):
735-
parts.append(text[j1:j2])
736-
if parts:
737-
result = "".join(parts).strip()
738-
739-
if result:
740-
conf.dumper.singleString("SSTI expression result: %s" % result)
741-
else:
742-
logger.warning("could not extract expression result from response")
743-
744-
745675
def _canTakeover(engine, evidence):
746676
"""Require exact engine fingerprint (not a family guess) and confirmed
747677
proof before attempting OS command execution."""

tests/test_ssti.py

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -275,39 +275,6 @@ def mock(place, parameter, value):
275275
self.assertIn("Twig", engine.name)
276276

277277

278-
class TestExpressionEvaluation(unittest.TestCase):
279-
def setUp(self):
280-
self.original_send = ssti._send
281-
282-
def tearDown(self):
283-
ssti._send = self.original_send
284-
285-
def test_eval_uses_expressionFmt(self):
286-
engine = ssti._ENGINE_TABLE[0] # Jinja2: expressionFmt = "{{ %s }}"
287-
results = []
288-
289-
def mock(place, parameter, value):
290-
results.append(value)
291-
return "Hello __marker__ 49 __marker2__"
292-
293-
ssti._send = mock
294-
ssti._evalExpression("GET", "q", engine, "7*7")
295-
# Payload must use expressionFmt, not raw delimiter concatenation
296-
self.assertIn("{{ ", results[0])
297-
self.assertIn(" }}", results[0])
298-
299-
def test_eval_falls_back_when_no_expressionFmt(self):
300-
engine = [e for e in ssti._ENGINE_TABLE if e.name == "Handlebars"][0]
301-
self.assertEqual(engine.expressionFmt, "")
302-
303-
def mock(place, parameter, value):
304-
return "irrelevant"
305-
306-
ssti._send = mock
307-
# Should not raise; just logs error
308-
ssti._evalExpression("GET", "q", engine, "7*7")
309-
310-
311278
class TestBooleanUniqueness(unittest.TestCase):
312279
def test_jinja2_boolean_unique_among_curlies(self):
313280
jinja2 = ssti._ENGINE_TABLE[0]

0 commit comments

Comments
 (0)