Fix for an Issue #179

This commit is contained in:
Miroslav Stampar 2012-09-10 19:23:24 +02:00
parent 9a631331a5
commit 1f49e4ae36
4 changed files with 15 additions and 134 deletions

View File

@ -16,6 +16,7 @@ from lib.core.data import queries
from lib.core.exception import sqlmapMissingMandatoryOptionException from lib.core.exception import sqlmapMissingMandatoryOptionException
from lib.core.exception import sqlmapNoneDataException from lib.core.exception import sqlmapNoneDataException
from lib.core.settings import CURRENT_DB from lib.core.settings import CURRENT_DB
from lib.utils.pivotdumptable import pivotDumpTable
from plugins.generic.enumeration import Enumeration as GenericEnumeration from plugins.generic.enumeration import Enumeration as GenericEnumeration
class Enumeration(GenericEnumeration): class Enumeration(GenericEnumeration):
@ -40,7 +41,7 @@ class Enumeration(GenericEnumeration):
rootQuery = queries[Backend.getIdentifiedDbms()].dbs rootQuery = queries[Backend.getIdentifiedDbms()].dbs
randStr = randomStr() randStr = randomStr()
query = rootQuery.inband.query query = rootQuery.inband.query
retVal = self.__pivotDumpTable("(%s) AS %s" % (query, randStr), ['%s.schemaname' % randStr], blind=True) retVal = pivotDumpTable("(%s) AS %s" % (query, randStr), ['%s.schemaname' % randStr], blind=True)
if retVal: if retVal:
kb.data.cachedDbs = retVal[0].values()[0] kb.data.cachedDbs = retVal[0].values()[0]
@ -76,7 +77,7 @@ class Enumeration(GenericEnumeration):
for db in dbs: for db in dbs:
randStr = randomStr() randStr = randomStr()
query = rootQuery.inband.query % (("'%s'" % db) if db != "USER" else 'USER') query = rootQuery.inband.query % (("'%s'" % db) if db != "USER" else 'USER')
retVal = self.__pivotDumpTable("(%s) AS %s" % (query, randStr), ['%s.tablename' % randStr], blind=True) retVal = pivotDumpTable("(%s) AS %s" % (query, randStr), ['%s.tablename' % randStr], blind=True)
if retVal: if retVal:
for table in retVal[0].values()[0]: for table in retVal[0].values()[0]:
@ -147,7 +148,7 @@ class Enumeration(GenericEnumeration):
randStr = randomStr() randStr = randomStr()
query = rootQuery.inband.query % (unsafeSQLIdentificatorNaming(tbl), ("'%s'" % unsafeSQLIdentificatorNaming(conf.db)) if unsafeSQLIdentificatorNaming(conf.db) != "USER" else 'USER') query = rootQuery.inband.query % (unsafeSQLIdentificatorNaming(tbl), ("'%s'" % unsafeSQLIdentificatorNaming(conf.db)) if unsafeSQLIdentificatorNaming(conf.db) != "USER" else 'USER')
retVal = self.__pivotDumpTable("(%s) AS %s" % (query, randStr), ['%s.columnname' % randStr,'%s.datatype' % randStr,'%s.len' % randStr], blind=True) retVal = pivotDumpTable("(%s) AS %s" % (query, randStr), ['%s.columnname' % randStr,'%s.datatype' % randStr,'%s.len' % randStr], blind=True)
if retVal: if retVal:
table = {} table = {}

View File

@ -20,6 +20,7 @@ from lib.core.enums import PAYLOAD
from lib.core.exception import sqlmapMissingMandatoryOptionException from lib.core.exception import sqlmapMissingMandatoryOptionException
from lib.core.exception import sqlmapNoneDataException from lib.core.exception import sqlmapNoneDataException
from lib.core.settings import CURRENT_DB from lib.core.settings import CURRENT_DB
from lib.utils.pivotdumptable import pivotDumpTable
from plugins.generic.enumeration import Enumeration as GenericEnumeration from plugins.generic.enumeration import Enumeration as GenericEnumeration
class Enumeration(GenericEnumeration): class Enumeration(GenericEnumeration):
@ -41,7 +42,7 @@ class Enumeration(GenericEnumeration):
blinds = (True,) blinds = (True,)
for blind in blinds: for blind in blinds:
retVal = self.__pivotDumpTable("(%s) AS %s" % (query, randStr), ['%s.name' % randStr], blind=blind) retVal = pivotDumpTable("(%s) AS %s" % (query, randStr), ['%s.name' % randStr], blind=blind)
if retVal: if retVal:
kb.data.cachedUsers = retVal[0].values()[0] kb.data.cachedUsers = retVal[0].values()[0]
@ -95,7 +96,7 @@ class Enumeration(GenericEnumeration):
blinds = [True] blinds = [True]
for blind in blinds: for blind in blinds:
retVal = self.__pivotDumpTable("(%s) AS %s" % (query, randStr), ['%s.name' % randStr], blind=blind) retVal = pivotDumpTable("(%s) AS %s" % (query, randStr), ['%s.name' % randStr], blind=blind)
if retVal: if retVal:
kb.data.cachedDbs = retVal[0].values()[0] kb.data.cachedDbs = retVal[0].values()[0]
@ -140,7 +141,7 @@ class Enumeration(GenericEnumeration):
for blind in blinds: for blind in blinds:
randStr = randomStr() randStr = randomStr()
query = rootQuery.inband.query % db query = rootQuery.inband.query % db
retVal = self.__pivotDumpTable("(%s) AS %s" % (query, randStr), ['%s.name' % randStr], blind=blind) retVal = pivotDumpTable("(%s) AS %s" % (query, randStr), ['%s.name' % randStr], blind=blind)
if retVal: if retVal:
for table in retVal[0].values()[0]: for table in retVal[0].values()[0]:
@ -232,7 +233,7 @@ class Enumeration(GenericEnumeration):
for blind in blinds: for blind in blinds:
randStr = randomStr() randStr = randomStr()
query = rootQuery.inband.query % (conf.db, conf.db, conf.db, conf.db, conf.db, conf.db, conf.db, unsafeSQLIdentificatorNaming(tbl)) query = rootQuery.inband.query % (conf.db, conf.db, conf.db, conf.db, conf.db, conf.db, conf.db, unsafeSQLIdentificatorNaming(tbl))
retVal = self.__pivotDumpTable("(%s) AS %s" % (query, randStr), ['%s.name' % randStr,'%s.usertype' % randStr], blind=blind) retVal = pivotDumpTable("(%s) AS %s" % (query, randStr), ['%s.name' % randStr,'%s.usertype' % randStr], blind=blind)
if retVal: if retVal:
table = {} table = {}

View File

@ -42,6 +42,7 @@ from lib.core.settings import MAX_INT
from lib.core.settings import NULL from lib.core.settings import NULL
from lib.request import inject from lib.request import inject
from lib.utils.hash import attackDumpedTable from lib.utils.hash import attackDumpedTable
from lib.utils.pivotdumptable import pivotDumpTable
class Entries: class Entries:
""" """
@ -51,129 +52,6 @@ class Entries:
def __init__(self): def __init__(self):
pass pass
def __pivotDumpTable(self, table, colList, count=None, blind=True):
lengths = {}
entries = {}
dumpNode = queries[Backend.getIdentifiedDbms()].dump_table.blind
validColumnList = False
validPivotValue = False
if count is None:
query = dumpNode.count % table
count = inject.getValue(query, inband=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) if blind else inject.getValue(query, blind=False, expected=EXPECTED.INT)
if isinstance(count, basestring) and count.isdigit():
count = int(count)
if count == 0:
infoMsg = "table '%s' appears to be empty" % unsafeSQLIdentificatorNaming(table)
logger.info(infoMsg)
for column in colList:
lengths[column] = len(column)
entries[column] = []
return entries, lengths
elif not isNumPosStrValue(count):
return None
for column in colList:
lengths[column] = 0
entries[column] = BigArray()
colList = filter(None, sorted(colList, key=lambda x: len(x) if x else MAX_INT))
for column in colList:
infoMsg = "fetching number of distinct "
infoMsg += "values for column '%s'" % column
logger.info(infoMsg)
query = dumpNode.count2 % (column, table)
value = inject.getValue(query, blind=blind, inband=not blind, error=not blind, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
if isNumPosStrValue(value):
validColumnList = True
if value == count:
infoMsg = "using column '%s' as a pivot " % column
infoMsg += "for retrieving row data"
logger.info(infoMsg)
validPivotValue = True
colList.remove(column)
colList.insert(0, column)
break
if not validColumnList:
errMsg = "all column name(s) provided are non-existent"
raise sqlmapNoneDataException, errMsg
if not validPivotValue:
warnMsg = "no proper pivot column provided (with unique values)."
warnMsg += " It won't be possible to retrieve all rows"
logger.warn(warnMsg)
pivotValue = " "
breakRetrieval = False
try:
for i in xrange(count):
if breakRetrieval:
break
for column in colList:
# Correction for pivotValues with unrecognized/problematic chars
for char in ('\'', '?'):
if pivotValue and char in pivotValue and pivotValue[0] != char:
pivotValue = pivotValue.split(char)[0]
pivotValue = pivotValue[:-1] + decodeIntToUnicode(ord(pivotValue[-1]) + 1)
break
if column == colList[0]:
query = dumpNode.query % (column, table, column, pivotValue)
else:
query = dumpNode.query2 % (column, table, colList[0], pivotValue)
value = inject.getValue(query, blind=blind, inband=not blind, error=not blind)
if column == colList[0]:
if isNoneValue(value):
breakRetrieval = True
break
else:
pivotValue = safechardecode(value)
if conf.limitStart or conf.limitStop:
if conf.limitStart and (i + 1) < conf.limitStart:
warnMsg = "skipping first %d pivot " % conf.limitStart
warnMsg += "point values"
singleTimeWarnMessage(warnMsg)
break
elif conf.limitStop and (i + 1) > conf.limitStop:
breakRetrieval = True
break
value = "" if isNoneValue(value) else unArrayizeValue(value)
lengths[column] = max(lengths[column], len(value) if value else 0)
entries[column].append(value)
except KeyboardInterrupt:
warnMsg = "user aborted during enumeration. sqlmap "
warnMsg += "will display partial output"
logger.warn(warnMsg)
except sqlmapConnectionException, e:
errMsg = "connection exception detected. sqlmap "
errMsg += "will display partial output"
errMsg += "'%s'" % e
logger.critical(errMsg)
return entries, lengths
def dumpTable(self, foundData=None): def dumpTable(self, foundData=None):
self.forceDbmsEnum() self.forceDbmsEnum()
@ -269,7 +147,7 @@ class Entries:
if not (isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) and kb.injection.data[PAYLOAD.TECHNIQUE.UNION].where == PAYLOAD.WHERE.ORIGINAL): if not (isTechniqueAvailable(PAYLOAD.TECHNIQUE.UNION) and kb.injection.data[PAYLOAD.TECHNIQUE.UNION].where == PAYLOAD.WHERE.ORIGINAL):
table = "%s.%s" % (conf.db, tbl) table = "%s.%s" % (conf.db, tbl)
retVal = self.__pivotDumpTable(table, colList, blind=False) retVal = pivotDumpTable(table, colList, blind=False)
if retVal: if retVal:
entries, _ = retVal entries, _ = retVal
@ -365,7 +243,7 @@ class Entries:
elif Backend.isDbms(DBMS.MAXDB): elif Backend.isDbms(DBMS.MAXDB):
table = "%s.%s" % (conf.db, tbl) table = "%s.%s" % (conf.db, tbl)
retVal = self.__pivotDumpTable(table, colList, count, blind=True) retVal = pivotDumpTable(table, colList, count, blind=True)
if retVal: if retVal:
entries, lengths = retVal entries, lengths = retVal

View File

@ -39,6 +39,7 @@ from lib.core.exception import sqlmapUserQuitException
from lib.core.threads import getCurrentThreadData from lib.core.threads import getCurrentThreadData
from lib.request import inject from lib.request import inject
from lib.utils.hash import attackCachedUsersPasswords from lib.utils.hash import attackCachedUsersPasswords
from lib.utils.pivotdumptable import pivotDumpTable
class Users: class Users:
""" """
@ -179,7 +180,7 @@ class Users:
randStr = randomStr() randStr = randomStr()
getCurrentThreadData().disableStdOut = True getCurrentThreadData().disableStdOut = True
retVal = self.__pivotDumpTable("(%s) AS %s" % (query, randStr), ['%s.name' % randStr, '%s.password' % randStr], blind=False) retVal = pivotDumpTable("(%s) AS %s" % (query, randStr), ['%s.name' % randStr, '%s.password' % randStr], blind=False)
if retVal: if retVal:
for user, password in filterPairValues(zip(retVal[0]["%s.name" % randStr], retVal[0]["%s.password" % randStr])): for user, password in filterPairValues(zip(retVal[0]["%s.name" % randStr], retVal[0]["%s.password" % randStr])):
@ -221,7 +222,7 @@ class Users:
randStr = randomStr() randStr = randomStr()
query = rootQuery.inband.query query = rootQuery.inband.query
retVal = self.__pivotDumpTable("(%s) AS %s" % (query, randStr), ['%s.name' % randStr, '%s.password' % randStr], blind=True) retVal = pivotDumpTable("(%s) AS %s" % (query, randStr), ['%s.name' % randStr, '%s.password' % randStr], blind=True)
if retVal: if retVal:
for user, password in filterPairValues(zip(retVal[0]["%s.name" % randStr], retVal[0]["%s.password" % randStr])): for user, password in filterPairValues(zip(retVal[0]["%s.name" % randStr], retVal[0]["%s.password" % randStr])):