2012-09-11 00:39:56 +04:00
|
|
|
#!/usr/bin/env python
|
|
|
|
|
|
|
|
"""
|
2013-01-18 18:07:51 +04:00
|
|
|
Copyright (c) 2006-2013 sqlmap developers (http://sqlmap.org/)
|
2012-09-11 00:39:56 +04:00
|
|
|
See the file 'doc/COPYING' for copying permission
|
|
|
|
"""
|
|
|
|
|
|
|
|
from extra.safe2bin.safe2bin import safechardecode
|
2013-01-15 19:05:33 +04:00
|
|
|
from lib.core.agent import agent
|
2012-09-11 00:39:56 +04:00
|
|
|
from lib.core.bigarray import BigArray
|
|
|
|
from lib.core.common import Backend
|
|
|
|
from lib.core.common import isNoneValue
|
|
|
|
from lib.core.common import isNumPosStrValue
|
|
|
|
from lib.core.common import singleTimeWarnMessage
|
|
|
|
from lib.core.common import unArrayizeValue
|
|
|
|
from lib.core.common import unsafeSQLIdentificatorNaming
|
|
|
|
from lib.core.data import conf
|
|
|
|
from lib.core.data import logger
|
|
|
|
from lib.core.data import queries
|
|
|
|
from lib.core.enums import CHARSET_TYPE
|
|
|
|
from lib.core.enums import EXPECTED
|
2012-12-06 17:14:19 +04:00
|
|
|
from lib.core.exception import SqlmapConnectionException
|
|
|
|
from lib.core.exception import SqlmapNoneDataException
|
2012-09-11 00:39:56 +04:00
|
|
|
from lib.core.settings import MAX_INT
|
2012-10-29 02:09:35 +04:00
|
|
|
from lib.core.unescaper import unescaper
|
2012-09-11 00:39:56 +04:00
|
|
|
from lib.request import inject
|
|
|
|
|
|
|
|
def pivotDumpTable(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
|
2012-10-28 02:36:09 +04:00
|
|
|
count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) if blind else inject.getValue(query, blind=False, time=False, expected=EXPECTED.INT)
|
2012-09-11 00:39:56 +04:00
|
|
|
|
|
|
|
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)
|
2012-10-28 02:36:09 +04:00
|
|
|
value = inject.getValue(query, blind=blind, union=not blind, error=not blind, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
|
2012-09-11 00:39:56 +04:00
|
|
|
|
|
|
|
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"
|
2013-01-04 02:20:55 +04:00
|
|
|
raise SqlmapNoneDataException(errMsg)
|
2012-09-11 00:39:56 +04:00
|
|
|
|
|
|
|
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:
|
2012-10-29 01:18:22 +04:00
|
|
|
def _(pivotValue):
|
|
|
|
if column == colList[0]:
|
2013-01-18 18:40:37 +04:00
|
|
|
query = dumpNode.query.replace("'%s'", "%s") % (agent.preprocessField(table, column), table, agent.preprocessField(table, column), unescaper.escape(pivotValue, False))
|
2012-10-29 01:18:22 +04:00
|
|
|
else:
|
2013-01-18 18:40:37 +04:00
|
|
|
query = dumpNode.query2.replace("'%s'", "%s") % (agent.preprocessField(table, column), table, agent.preprocessField(table, colList[0]), unescaper.escape(pivotValue, False))
|
2012-09-11 00:39:56 +04:00
|
|
|
|
2012-10-29 01:18:22 +04:00
|
|
|
return unArrayizeValue(inject.getValue(query, blind=blind, time=blind, union=not blind, error=not blind))
|
2012-09-11 00:39:56 +04:00
|
|
|
|
2012-10-29 01:18:22 +04:00
|
|
|
value = _(pivotValue)
|
2012-09-11 00:39:56 +04:00
|
|
|
if column == colList[0]:
|
2012-10-29 01:18:22 +04:00
|
|
|
if isNoneValue(value):
|
2012-10-29 02:09:35 +04:00
|
|
|
for pivotValue in filter(None, (" " if pivotValue == " " else None, "%s%s" % (pivotValue[0], unichr(ord(pivotValue[1]) + 1)) if len(pivotValue) > 1 else None, unichr(ord(pivotValue[0]) + 1))):
|
2012-10-29 01:18:22 +04:00
|
|
|
value = _(pivotValue)
|
|
|
|
if not isNoneValue(value):
|
|
|
|
break
|
2012-09-11 00:39:56 +04:00
|
|
|
if isNoneValue(value):
|
|
|
|
breakRetrieval = True
|
|
|
|
break
|
2012-10-29 01:18:22 +04:00
|
|
|
pivotValue = safechardecode(value)
|
2012-09-11 00:39:56 +04:00
|
|
|
|
|
|
|
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)
|
|
|
|
|
2012-12-06 17:14:19 +04:00
|
|
|
except SqlmapConnectionException, e:
|
2012-09-11 00:39:56 +04:00
|
|
|
errMsg = "connection exception detected. sqlmap "
|
|
|
|
errMsg += "will display partial output"
|
|
|
|
errMsg += "'%s'" % e
|
|
|
|
logger.critical(errMsg)
|
|
|
|
|
|
|
|
return entries, lengths
|