diff --git a/lib/core/optiondict.py b/lib/core/optiondict.py index 01615f322..c1db5307a 100644 --- a/lib/core/optiondict.py +++ b/lib/core/optiondict.py @@ -114,6 +114,7 @@ optDict = { "getCount": "boolean", "dumpTable": "boolean", "dumpAll": "boolean", + "pivotColumn": "string", "search": "boolean", "db": "string", "tbl": "string", diff --git a/lib/parse/cmdline.py b/lib/parse/cmdline.py index b809bb90d..b7028ff10 100644 --- a/lib/parse/cmdline.py +++ b/lib/parse/cmdline.py @@ -365,6 +365,9 @@ def cmdLineParser(): enumeration.add_option("--dump-all", dest="dumpAll", action="store_true", help="Dump all DBMS databases tables entries") + enumeration.add_option("--pivot-column", dest="pivotColumn", + help="Pivot column name") + enumeration.add_option("--search", dest="search", action="store_true", help="Search column(s), table(s) and/or database name(s)") diff --git a/lib/utils/pivotdumptable.py b/lib/utils/pivotdumptable.py index fd055430b..fe1bf2b4d 100644 --- a/lib/utils/pivotdumptable.py +++ b/lib/utils/pivotdumptable.py @@ -5,6 +5,8 @@ Copyright (c) 2006-2013 sqlmap developers (http://sqlmap.org/) See the file 'doc/COPYING' for copying permission """ +import re + from extra.safe2bin.safe2bin import safechardecode from lib.core.agent import agent from lib.core.bigarray import BigArray @@ -60,36 +62,50 @@ def pivotDumpTable(table, colList, count=None, blind=True): 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) + if conf.pivotColumn: + if any(re.search(r"(.+\.)?%s" % conf.pivotColumn, _, re.I) for _ in colList): + infoMsg = "using column '%s' as a pivot " % conf.pivotColumn + infoMsg += "for retrieving row data" + logger.info(infoMsg) - query = dumpNode.count2 % (column, table) - value = inject.getValue(query, blind=blind, union=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) + validPivotValue = True + colList.remove(conf.pivotColumn) + colList.insert(0, conf.pivotColumn) + else: + warnMsg = "column '%s' not " % conf.pivotColumn + warnMsg += "found in table '%s'" % table + logger.warn(warnMsg) 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) + 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, union=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 diff --git a/sqlmap.conf b/sqlmap.conf index 8297e3916..86f65303e 100644 --- a/sqlmap.conf +++ b/sqlmap.conf @@ -398,6 +398,9 @@ dumpTable = False # Valid: True or False dumpAll = False +# Pivot column name. +pivotColumn = + # Search column(s), table(s) and/or database name(s). # Requires: db, tbl or col # Valid: True or False