Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions data/txt/sha256sums.txt
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ d69e84f1648cdb907f5d2dd454f03874a4613752b07867510145d51d84b3c56f lib/controller
1966ca704961fb987ab757f0a4afddbf841d1a880631b701487c75cef63d60c3 lib/controller/__init__.py
b36b085ff1b5797e375c1e2ca3b12c7ab4204f48acd1a1efb075cff8302d9750 lib/core/agent.py
ca3e5ce56cb1cae0a8e815425ab6810068004bffe8861d1037c7c87c0ae02477 lib/core/bigarray.py
1452ffc42657bea207583173de9829dddf4afd9b159c785284e43878de492afb lib/core/common.py
7fc5a845a78e6fb7b1a2fdef2fe529510ac5f2c9fac78de588844b4a8c1504e1 lib/core/common.py
8f1272487e1adfcc8c755a2f56f0c6d21eac5e685a73a9a159482f9dc9142bc5 lib/core/compat.py
742bce10b97034966021ec60c7ac294db4af4fe7893613d63172a02c29f009f8 lib/core/convert.py
c03dc585f89642cfd81b087ac2723e3e1bb3bfa8c60e6f5fe58ef3b0113ebfe6 lib/core/data.py
Expand All @@ -181,14 +181,14 @@ c03dc585f89642cfd81b087ac2723e3e1bb3bfa8c60e6f5fe58ef3b0113ebfe6 lib/core/data.
1966ca704961fb987ab757f0a4afddbf841d1a880631b701487c75cef63d60c3 lib/core/__init__.py
914a13ee21fd610a6153a37cbe50830fcbd1324c7ebc1e7fc206d5e598b0f7ad lib/core/log.py
3ec59b5eb336d9808d28496f1cbbad716b4a0e276b5399023142826e460e3fd2 lib/core/optiondict.py
3ff871fe8391952c3ec3bb528ba592a13926c80ca0b68fd322a317f69a651ef7 lib/core/option.py
b61676f0aa44798aaf9be72ff37550e2b78ed6ad3c71fbcad54f8c8bf7b34096 lib/core/option.py
ccc4a717e887652b1fcce073d9409d9c59a3b28548c703a9e453d15845f90cd7 lib/core/patch.py
49c0fa7e3814dfda610d665ee02b12df299b28bc0b6773815b4395514ddf8dec lib/core/profiling.py
03db48f02c3d07a047ddb8fe33a757b6238867352d8ddda2a83e4fec09a98d04 lib/core/readlineng.py
48797d6c34dd9bb8a53f7f3794c85f4288d82a9a1d6be7fcf317d388cb20d4b3 lib/core/replication.py
0b8c38a01bb01f843d94a6c5f2075ee47520d0c4aa799cecea9c3e2c5a4a23a6 lib/core/revision.py
888daba83fd4a34e9503fe21f01fef4cc730e5cde871b1d40e15d4cbc847d56c lib/core/session.py
ef64975437d734f34f15026d9fec87eb147999912c187985a2c83c9bb3ffb08e lib/core/settings.py
1a73ece519f93c569f9b0b9b5837213bb20aa8d1fc6be54db240c5b5d9308162 lib/core/settings.py
cd5a66deee8963ba8e7e9af3dd36eb5e8127d4d68698811c29e789655f507f82 lib/core/shell.py
bcb5d8090d5e3e0ef2a586ba09ba80eef0c6d51feb0f611ed25299fbb254f725 lib/core/subprocessng.py
70ea3768f1b3062b22d20644df41c86238157ec80dd43da40545c620714273c6 lib/core/target.py
Expand Down Expand Up @@ -230,7 +230,7 @@ f522436fbd14bdab090a1d305fcac0361800cb8e36c8cbcb47933298376a71e0 lib/takeover/r
0787f78e6bd9bb21d4267c95c4c99806711bb57c5518485c2e25f10fcf9c41fc lib/takeover/udf.py
23d73af417604dab460b74cdc230896153f018a6c00d144019491053640a172f lib/takeover/web.py
8cc1e226d4150fe8aa1a056e5d32d858ed6444d3d4e2af7fb4bc08f0bbe9d527 lib/takeover/xp_cmdshell.py
09c3759b59bc111712f75b0b1762d195c0da0e0741dd76379546c429e8ed4457 lib/techniques/blind/inference.py
42368a281d4d6f1571da95f2fb67afc43696ecdb6cad9720a178461f861b4fcd lib/techniques/blind/inference.py
1966ca704961fb987ab757f0a4afddbf841d1a880631b701487c75cef63d60c3 lib/techniques/blind/__init__.py
1966ca704961fb987ab757f0a4afddbf841d1a880631b701487c75cef63d60c3 lib/techniques/dns/__init__.py
3df9839fb92a81d46b6194d7adacb43f391efb78b071783c132e8d596ecbfaf1 lib/techniques/dns/test.py
Expand Down Expand Up @@ -589,7 +589,7 @@ caa06fed7323b2bb6d0f2443ce343de94f75bf8ad012c055d5e07741d908ebad tests/test_mis
cde0bea1263ae857561f91ed2bd515e972b716743f017d31b1718a8546c72759 tests/test_pagecontent.py
4bac34af2abddce003756d6776e89b2fda220bb7603ef3761f4f37ee29f9c369 tests/test_payload_marking.py
6bfc8201724078bd9d6d559916ef73c9ff97e19b0f2948f37e588a49b027795f tests/test_payloads_structure.py
5dc46919f971f89a3073118ec00bf420cc9cecf0b072b2f896df2f860e87adec tests/test_property.py
a6d013104601c0414628aff3d8b5b69bee3e6733781d8f8da880457d8b44bd3a tests/test_property.py
5c95e7863190e440234f231864fb1219c35207132762858cc95181c57086bafc tests/test_replication.py
67a5241aeebc20eb1c20cfc490422a59af5179040824e5731bd785db2e6bf750 tests/test_report.py
cec98d72992c0799229a780fa7f0d7f3fb01ec2d708187ce0e4a05c8612f291b tests/test_safe2bin.py
Expand Down
35 changes: 33 additions & 2 deletions lib/core/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -4507,13 +4507,15 @@ def safeCSValue(value):
'"foo, bar"'
>>> safeCSValue('foobar')
'foobar'
>>> safeCSValue('foo\\rbar')
'"foo\\rbar"'
"""

retVal = value

if retVal and isinstance(retVal, six.string_types):
if not (retVal[0] == retVal[-1] == '"'):
if any(_ in retVal for _ in (conf.get("csvDel", defaults.csvDel), '"', '\n')):
if any(_ in retVal for _ in (conf.get("csvDel", defaults.csvDel), '"', '\n', '\r')):
retVal = '"%s"' % retVal.replace('"', '""')

return retVal
Expand Down Expand Up @@ -5299,9 +5301,38 @@ def splitFields(fields, delimiter=','):

>>> splitFields('foo, bar, max(foo, bar)')
['foo', 'bar', 'max(foo,bar)']
>>> splitFields("a, 'b, c', d")
['a', "'b, c'", 'd']
"""

fields = fields.replace("%s " % delimiter, delimiter)
# collapse "<delimiter> " -> "<delimiter>" but only OUTSIDE quoted string literals, so a
# space inside e.g. 'b, c' survives (the quote handling mirrors zeroDepthSearch)
normalized = []
quote = None
index = 0
while index < len(fields):
char = fields[index]
if quote:
normalized.append(char)
if char == quote:
if index + 1 < len(fields) and fields[index + 1] == quote: # escaped quote (e.g. '')
normalized.append(fields[index + 1])
index += 2
continue
else:
quote = None
elif char in ('"', "'"):
quote = char
normalized.append(char)
elif char == delimiter and index + 1 < len(fields) and fields[index + 1] == ' ':
normalized.append(char) # keep the delimiter, drop the single trailing space
index += 2
continue
else:
normalized.append(char)
index += 1

fields = "".join(normalized)
commas = [-1, len(fields)]
commas.extend(zeroDepthSearch(fields, ','))
commas = sorted(commas)
Expand Down
1 change: 1 addition & 0 deletions lib/core/option.py
Original file line number Diff line number Diff line change
Expand Up @@ -2074,6 +2074,7 @@ def _setKnowledgeBaseAttributes(flushAll=True):
kb.cache.comparison = LRUDict(capacity=256)
kb.cache.encoding = LRUDict(capacity=256)
kb.cache.alphaBoundaries = None
kb.cache.charsetAsciiTbl = None
kb.cache.hashRegex = None
kb.cache.intBoundaries = None
kb.cache.parsedDbms = {}
Expand Down
2 changes: 1 addition & 1 deletion lib/core/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from thirdparty import six

# sqlmap version (<major>.<minor>.<month>.<monthly commit>)
VERSION = "1.10.6.115"
VERSION = "1.10.6.116"
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)
Expand Down
5 changes: 4 additions & 1 deletion lib/techniques/blind/inference.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,10 @@ def bisection(payload, expression, length=None, charsetType=None, firstChar=None
return 0, None

if charsetType is None and conf.charset:
asciiTbl = sorted(set(ord(_) for _ in conf.charset))
# conf.charset is fixed for the whole run; compute the table once, not per bisection() call
if kb.cache.charsetAsciiTbl is None:
kb.cache.charsetAsciiTbl = sorted(set(ord(_) for _ in conf.charset))
asciiTbl = kb.cache.charsetAsciiTbl
else:
asciiTbl = getCharset(charsetType)

Expand Down
16 changes: 13 additions & 3 deletions tests/test_property.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,19 @@ def prop(_):

class TestSplitterInvariants(unittest.TestCase):
def test_reconstruction(self):
# pure partition identity: rejoining the 0-depth split must reproduce the (space-normalized) input
for_all(self, gen_text, lambda s: u",".join(splitFields(s)) == s.replace(", ", ","), label="split-reconstruct-text")
for_all(self, gen_sql_fields, lambda s: u",".join(splitFields(s)) == s.replace(", ", ","), label="split-reconstruct-sql")
# Faithful partition: rejoining the 0-depth split reconstructs the input modulo the only
# transform splitFields applies - dropping a single space after an unquoted delimiter. So
# nothing other than spaces may be lost/added/reordered. (Space-insensitive so it survives
# the quote-aware normalization: spaces inside 'literals' are kept, comma-trailing ones are
# not; either way no non-space content changes.)
for_all(self, gen_text, lambda s: u",".join(splitFields(s)).replace(u" ", u"") == s.replace(u" ", u""), label="split-reconstruct-text")
for_all(self, gen_sql_fields, lambda s: u",".join(splitFields(s)).replace(u" ", u"") == s.replace(u" ", u""), label="split-reconstruct-sql")

def test_quoted_literal_spaces_preserved(self):
# the I3 contract: a ", " inside a quoted literal must NOT be collapsed (the whole literal
# survives intact as a single field)
for_all(self, lambda r: u"%s, '%s, %s', %s" % (r.choice([u"a", u"id"]), r.choice([u"x", u"p q"]), r.choice([u"y", u"z"]), r.choice([u"b", u"c"])),
lambda s: u"'%s'" % s.split(u"'")[1] in splitFields(s), label="split-quote-preserve")

def test_never_cuts_inside_parens(self):
# on well-formed input no field may carry unbalanced parens (i.e. a split never lands inside a group)
Expand Down