From 1ae413a2062fce0e935f6152cb2162ec1b602071 Mon Sep 17 00:00:00 2001 From: Miroslav Stampar Date: Thu, 22 Dec 2011 10:32:21 +0000 Subject: [PATCH] some refactoring/speedup around UNION technique --- lib/core/common.py | 32 +++++++++----------------- lib/request/inject.py | 10 ++++---- lib/takeover/xp_cmdshell.py | 2 +- plugins/dbms/mssqlserver/filesystem.py | 4 ++-- plugins/dbms/mysql/filesystem.py | 6 ++--- 5 files changed, 22 insertions(+), 32 deletions(-) diff --git a/lib/core/common.py b/lib/core/common.py index 9c68aee9e..8010ccbef 100644 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -1328,7 +1328,7 @@ def getRange(count, dump=False, plusOne=False): return indexRange -def parseUnionPage(output, expression, partial=False, sort=True): +def parseUnionPage(output, expression, partial=False, unique=True): if output is None: return None @@ -1336,31 +1336,21 @@ def parseUnionPage(output, expression, partial=False, sort=True): if output.startswith(kb.chars.start) and output.endswith(kb.chars.stop): regExpr = '%s(.*?)%s' % (kb.chars.start, kb.chars.stop) - output = re.findall(regExpr, output, re.DOTALL | re.IGNORECASE) - - if sort: - _ = [] - unique = set() - for entry in output: - key = entry.lower() - if key not in unique: - unique.add(key) - _.append(entry) - output = _ + _ = set() for entry in output: + if unique: + key = entry.lower() + if key not in _: + _.add(key) + else: + continue + entry = safecharencode(entry) if kb.safeCharEncode else entry + entry = entry.split(DUMP_DEL_MARKER if DUMP_DEL_MARKER in entry else kb.chars.delimiter) - if DUMP_DEL_MARKER in entry: - entry = entry.split(DUMP_DEL_MARKER) - else: - entry = entry.split(kb.chars.delimiter) - - if len(entry) == 1: - data.append(entry[0]) - else: - data.append(entry) + data.append(entry[0] if len(entry) == 1 else entry) else: data = output diff --git a/lib/request/inject.py b/lib/request/inject.py index dd3a99135..d8f231da4 100644 --- a/lib/request/inject.py +++ b/lib/request/inject.py @@ -368,7 +368,7 @@ def __goError(expression, expected=None, resumeValue=True, dump=False): return output -def __goInband(expression, expected=None, sort=True, resumeValue=True, unpack=True, dump=False): +def __goInband(expression, expected=None, unique=True, resumeValue=True, unpack=True, dump=False): """ Retrieve the output of a SQL query taking advantage of an inband SQL injection vulnerability on the affected parameter. @@ -384,11 +384,11 @@ def __goInband(expression, expected=None, sort=True, resumeValue=True, unpack=Tr if isinstance(output, list): data = output else: - data = parseUnionPage(output, expression, partial, sort) + data = parseUnionPage(output, expression, partial, unique) return data -def getValue(expression, blind=True, inband=True, error=True, time=True, fromUser=False, expected=None, batch=False, unpack=True, sort=True, resumeValue=True, charsetType=None, firstChar=None, lastChar=None, dump=False, suppressOutput=None, expectingNone=False, safeCharEncode=True): +def getValue(expression, blind=True, inband=True, error=True, time=True, fromUser=False, expected=None, batch=False, unpack=True, unique=True, resumeValue=True, charsetType=None, firstChar=None, lastChar=None, dump=False, suppressOutput=None, expectingNone=False, safeCharEncode=True): """ Called each time sqlmap inject a SQL query on the SQL injection affected parameter. It can call a function to retrieve the output @@ -429,9 +429,9 @@ def getValue(expression, blind=True, inband=True, error=True, time=True, fromUse kb.technique = PAYLOAD.TECHNIQUE.UNION if expected == EXPECTED.BOOL: - value = __goInband(forgeCaseExpression, expected, sort, resumeValue, unpack, dump) + value = __goInband(forgeCaseExpression, expected, unique, resumeValue, unpack, dump) else: - value = __goInband(query, expected, sort, resumeValue, unpack, dump) + value = __goInband(query, expected, unique, resumeValue, unpack, dump) count += 1 found = (value is not None) or (value is None and expectingNone) or count >= MAX_TECHNIQUES_PER_VALUE diff --git a/lib/takeover/xp_cmdshell.py b/lib/takeover/xp_cmdshell.py index cb125f66c..6ee9a38a5 100644 --- a/lib/takeover/xp_cmdshell.py +++ b/lib/takeover/xp_cmdshell.py @@ -121,7 +121,7 @@ class xp_cmdshell: self.delRemoteFile(tmpFile) - output = inject.getValue("SELECT %s FROM %s" % (self.tblField, self.cmdTblName), resumeValue=False, sort=False, firstChar=first, lastChar=last, safeCharEncode=False) + output = inject.getValue("SELECT %s FROM %s" % (self.tblField, self.cmdTblName), resumeValue=False, unique=False, firstChar=first, lastChar=last, safeCharEncode=False) inject.goStacked("DELETE FROM %s" % self.cmdTblName) if output and isinstance(output, (list, tuple)): diff --git a/plugins/dbms/mssqlserver/filesystem.py b/plugins/dbms/mssqlserver/filesystem.py index 8d8bd3f54..8288552fe 100644 --- a/plugins/dbms/mssqlserver/filesystem.py +++ b/plugins/dbms/mssqlserver/filesystem.py @@ -94,7 +94,7 @@ class Filesystem(GenericFilesystem): inject.goStacked(binToHexQuery) if isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION): - result = inject.getValue("SELECT %s FROM %s ORDER BY id ASC" % (self.tblField, hexTbl), sort=False, resumeValue=False, blind=False, error=False) + result = inject.getValue("SELECT %s FROM %s ORDER BY id ASC" % (self.tblField, hexTbl), unique=False, resumeValue=False, blind=False, error=False) if not result: result = [] @@ -108,7 +108,7 @@ class Filesystem(GenericFilesystem): indexRange = getRange(count) for index in indexRange: - chunk = inject.getValue("SELECT TOP 1 %s FROM %s WHERE %s NOT IN (SELECT TOP %d %s FROM %s ORDER BY id ASC) ORDER BY id ASC" % (self.tblField, hexTbl, self.tblField, index, self.tblField, hexTbl), unpack=False, resumeValue=False, sort=False, charsetType=3) + chunk = inject.getValue("SELECT TOP 1 %s FROM %s WHERE %s NOT IN (SELECT TOP %d %s FROM %s ORDER BY id ASC) ORDER BY id ASC" % (self.tblField, hexTbl, self.tblField, index, self.tblField, hexTbl), unpack=False, resumeValue=False, unique=False, charsetType=3) result.append(chunk) inject.goStacked("DROP TABLE %s" % hexTbl) diff --git a/plugins/dbms/mysql/filesystem.py b/plugins/dbms/mysql/filesystem.py index 930c10f68..e8eb2d5f2 100644 --- a/plugins/dbms/mysql/filesystem.py +++ b/plugins/dbms/mysql/filesystem.py @@ -52,7 +52,7 @@ class Filesystem(GenericFilesystem): logger.debug(debugMsg) inject.goStacked("LOAD DATA INFILE '%s' INTO TABLE %s FIELDS TERMINATED BY '%s' (%s)" % (tmpFile, self.fileTblName, randomStr(10), self.tblField)) - length = unArrayizeValue(inject.getValue("SELECT LENGTH(%s) FROM %s" % (self.tblField, self.fileTblName), sort=False, resumeValue=False, charsetType=2)) + length = unArrayizeValue(inject.getValue("SELECT LENGTH(%s) FROM %s" % (self.tblField, self.fileTblName), unique=False, resumeValue=False, charsetType=2)) if not isNumPosStrValue(length): errMsg = "unable to retrieve the content of the " @@ -66,11 +66,11 @@ class Filesystem(GenericFilesystem): result = [] for i in xrange(1, length, sustrLen): - chunk = inject.getValue("SELECT MID(%s, %d, %d) FROM %s" % (self.tblField, i, sustrLen, self.fileTblName), unpack=False, sort=False, resumeValue=False, charsetType=3) + chunk = inject.getValue("SELECT MID(%s, %d, %d) FROM %s" % (self.tblField, i, sustrLen, self.fileTblName), unpack=False, unique=False, resumeValue=False, charsetType=3) result.append(chunk) else: - result = inject.getValue("SELECT %s FROM %s" % (self.tblField, self.fileTblName), sort=False, resumeValue=False, charsetType=3) + result = inject.getValue("SELECT %s FROM %s" % (self.tblField, self.fileTblName), unique=False, resumeValue=False, charsetType=3) return result