From f7bf1fbe9442c813a73868659d48412601e63768 Mon Sep 17 00:00:00 2001 From: Miroslav Stampar Date: Tue, 7 Feb 2012 10:46:55 +0000 Subject: [PATCH] upgrade/fixes for direct DBMS access --- lib/core/common.py | 16 ++++++++++++---- lib/core/dump.py | 3 ++- lib/core/option.py | 3 ++- lib/core/settings.py | 3 +++ lib/request/direct.py | 20 +++++++++----------- plugins/dbms/maxdb/enumeration.py | 2 -- plugins/dbms/mssqlserver/enumeration.py | 5 ----- plugins/dbms/sybase/enumeration.py | 2 -- plugins/generic/enumeration.py | 6 +++++- 9 files changed, 33 insertions(+), 27 deletions(-) diff --git a/lib/core/common.py b/lib/core/common.py index 5073f584e..a786f5b31 100644 --- a/lib/core/common.py +++ b/lib/core/common.py @@ -84,6 +84,7 @@ from lib.core.settings import UNICODE_ENCODING from lib.core.settings import DBMS_DICT from lib.core.settings import DESCRIPTION from lib.core.settings import DUMMY_SQL_INJECTION_CHARS +from lib.core.settings import NULL from lib.core.settings import IS_WIN from lib.core.settings import PLATFORM from lib.core.settings import PYVERSION @@ -1088,9 +1089,9 @@ def parsePasswordHash(password): blank = " " * 8 if not password or password == " ": - password = "NULL" + password = NULL - if Backend.isDbms(DBMS.MSSQL) and password != "NULL" and isHexEncodedString(password): + if Backend.isDbms(DBMS.MSSQL) and password != NULL and isHexEncodedString(password): hexPassword = password password = "%s\n" % hexPassword password += "%sheader: %s\n" % (blank, hexPassword[:6]) @@ -2047,7 +2048,7 @@ def getPartRun(): # Return the INI tag to consider for common outputs (e.g. 'Databases') return commonPartsDict[retVal][1] if isinstance(commonPartsDict.get(retVal), tuple) else retVal -def getUnicode(value, encoding=None, system=False): +def getUnicode(value, encoding=None, system=False, noneToNull=False): """ Return the unicode representation of the supplied value: @@ -2059,6 +2060,13 @@ def getUnicode(value, encoding=None, system=False): u'1' """ + if noneToNull and value is None: + return NULL + + if isinstance(value, (list, tuple)): + value = list(getUnicode(_, encoding, system, noneToNull) for _ in value) + return value + if not system: if isinstance(value, unicode): return value @@ -2917,7 +2925,7 @@ def isNullValue(value): Returns whether the value contains explicit 'NULL' value """ - return isinstance(value, basestring) and value.upper() == "NULL" + return isinstance(value, basestring) and value.upper() == NULL def expandMnemonics(mnemonics, parser, args): """ diff --git a/lib/core/dump.py b/lib/core/dump.py index 41a391896..9d314620a 100644 --- a/lib/core/dump.py +++ b/lib/core/dump.py @@ -29,6 +29,7 @@ from lib.core.enums import DBMS from lib.core.exception import sqlmapValueException from lib.core.replication import Replication from lib.core.settings import BUFFERED_LOG_SIZE +from lib.core.settings import NULL from lib.core.settings import TRIM_STDOUT_DUMP_SIZE from lib.core.settings import UNICODE_ENCODING @@ -455,7 +456,7 @@ class Dump: value = getUnicode(info["values"][i]) if re.search("^[\ *]*$", value): - value = "NULL" + value = NULL values.append(value) maxlength = int(info["length"]) diff --git a/lib/core/option.py b/lib/core/option.py index f6fe45121..55df79f3c 100644 --- a/lib/core/option.py +++ b/lib/core/option.py @@ -86,6 +86,7 @@ from lib.core.settings import DEFAULT_PAGE_ENCODING from lib.core.settings import DEFAULT_TOR_HTTP_PORTS from lib.core.settings import DEFAULT_TOR_SOCKS_PORT from lib.core.settings import IS_WIN +from lib.core.settings import NULL from lib.core.settings import PLATFORM from lib.core.settings import PYVERSION from lib.core.settings import SITE @@ -1474,7 +1475,7 @@ def __setKnowledgeBaseAttributes(flushAll=True): kb.testQueryCount = 0 kb.threadContinue = True kb.threadException = False - kb.uChar = "NULL" + kb.uChar = NULL kb.xpCmdshellAvailable = False kb.chars = AttribDict() diff --git a/lib/core/settings.py b/lib/core/settings.py index 0cb043785..8b09f3e32 100644 --- a/lib/core/settings.py +++ b/lib/core/settings.py @@ -239,6 +239,9 @@ SQL_STATEMENTS = { "rollback ", ), } +# string representation for NULL value +NULL = "NULL" + # Regular expressions used for parsing error messages (--parse-errors) ERROR_PARSING_REGEXES = ( r"[^<]*(fatal|error|warning|exception)[^<]*:?\s*(?P.+?)", diff --git a/lib/request/direct.py b/lib/request/direct.py index f5dd15bd3..62cc94090 100644 --- a/lib/request/direct.py +++ b/lib/request/direct.py @@ -65,19 +65,17 @@ def direct(query, content=True): if not output: return output elif content: - if conf.hostname not in kb.resumedQueries or ( conf.hostname in kb.resumedQueries and query not in kb.resumedQueries[conf.hostname] ): - dataToSessionFile("[%s][%s][%s][%s][%s]\n" % (conf.hostname, kb.injection.place, conf.parameters[kb.injection.place], query, base64pickle(output))) + #if conf.hostname not in kb.resumedQueries or ( conf.hostname in kb.resumedQueries and query not in kb.resumedQueries[conf.hostname] ): + #dataToSessionFile("[%s][%s][%s][%s][%s]\n" % (conf.hostname, kb.injection.place, conf.parameters[kb.injection.place], query, base64pickle(output))) - if len(output) == 1: + if output and isinstance(output, (list, tuple)): if len(output[0]) == 1: - out = list(output)[0][0] - if isinstance(out, str): - out = utf8decode(out) - return getUnicode(out, UNICODE_ENCODING) - else: - return list(output) - else: - return output + if len(output) > 1: + output = map(lambda _: _[0], output) + else: + output = output[0][0] + + return getUnicode(output, noneToNull=True) else: for line in output: if line[0] in (1, -1): diff --git a/plugins/dbms/maxdb/enumeration.py b/plugins/dbms/maxdb/enumeration.py index 210163a86..43d7d6fa1 100644 --- a/plugins/dbms/maxdb/enumeration.py +++ b/plugins/dbms/maxdb/enumeration.py @@ -78,8 +78,6 @@ class Enumeration(GenericEnumeration): rootQuery = queries[Backend.getIdentifiedDbms()].tables for db in dbs: - db = unArrayizeValue(db) - randStr = randomStr() query = rootQuery.inband.query % (("'%s'" % db) if db != "USER" else 'USER') retVal = self.__pivotDumpTable("(%s) AS %s" % (query, randStr), ['%s.tablename' % randStr], blind=True) diff --git a/plugins/dbms/mssqlserver/enumeration.py b/plugins/dbms/mssqlserver/enumeration.py index 7198f7d3d..1f30d4e42 100644 --- a/plugins/dbms/mssqlserver/enumeration.py +++ b/plugins/dbms/mssqlserver/enumeration.py @@ -89,8 +89,6 @@ class Enumeration(GenericEnumeration): if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR)) or conf.direct: for db in dbs: - db = unArrayizeValue(db) - if conf.excludeSysDbs and db in self.excludeDbsList: infoMsg = "skipping system database '%s'" % db logger.info(infoMsg) @@ -172,9 +170,6 @@ class Enumeration(GenericEnumeration): enumDbs = kb.data.cachedDbs for db in enumDbs: - if isinstance(db, list): - db = db[0] - db = safeSQLIdentificatorNaming(db) foundTbls[db] = [] diff --git a/plugins/dbms/sybase/enumeration.py b/plugins/dbms/sybase/enumeration.py index 05115aee1..068c6f497 100644 --- a/plugins/dbms/sybase/enumeration.py +++ b/plugins/dbms/sybase/enumeration.py @@ -139,8 +139,6 @@ class Enumeration(GenericEnumeration): rootQuery = queries[Backend.getIdentifiedDbms()].tables for db in dbs: - db = unArrayizeValue(db) - for blind in blinds: randStr = randomStr() query = rootQuery.inband.query % db diff --git a/plugins/generic/enumeration.py b/plugins/generic/enumeration.py index 8ee4a3ae2..37c7ec6c8 100644 --- a/plugins/generic/enumeration.py +++ b/plugins/generic/enumeration.py @@ -897,7 +897,7 @@ class Enumeration: value = map(lambda x: (dbs[0], x), value) for db, table in filterPairValues(value): - db = safeSQLIdentificatorNaming(unArrayizeValue(db)) + db = safeSQLIdentificatorNaming(db) table = safeSQLIdentificatorNaming(table, True) if not kb.data.cachedTables.has_key(db): @@ -1654,6 +1654,10 @@ class Enumeration: else: colEntry = entry[index] if index < len(entry) else u'' + if colEntry is None: + import pdb + pdb.set_trace() + colEntryLen = len(getUnicode(colEntry)) maxLen = max(colLen, colEntryLen)