diff --git a/lib/controller/action.py b/lib/controller/action.py
index d1f7e737f..f858edec6 100644
--- a/lib/controller/action.py
+++ b/lib/controller/action.py
@@ -120,6 +120,9 @@ def action():
if conf.dumpAll:
conf.dbmsHandler.dumpAll()
+ if conf.search:
+ conf.dbmsHandler.search()
+
if conf.query:
dumper.string(conf.query, conf.dbmsHandler.sqlQuery(conf.query))
diff --git a/lib/core/common.py b/lib/core/common.py
index e8b03a23b..94ba94276 100644
--- a/lib/core/common.py
+++ b/lib/core/common.py
@@ -1006,7 +1006,7 @@ def normalizePath(path):
return retVal
def safeStringFormat(formatStr, params):
- retVal = formatStr.replace('%d', '%s')
+ retVal = formatStr.replace("%d", "%s")
if isinstance(params, str):
retVal = retVal.replace("%s", params)
@@ -1015,7 +1015,7 @@ def safeStringFormat(formatStr, params):
index = 0
while index != -1:
- index = retVal.find('%s')
+ index = retVal.find("%s")
if index != -1:
if count < len(params):
diff --git a/lib/core/optiondict.py b/lib/core/optiondict.py
index 1adc221a0..c5a444023 100644
--- a/lib/core/optiondict.py
+++ b/lib/core/optiondict.py
@@ -96,6 +96,7 @@ optDict = {
"getColumns": "boolean",
"dumpTable": "boolean",
"dumpAll": "boolean",
+ "search": "boolean",
"user": "string",
"db": "string",
"tbl": "string",
diff --git a/lib/parse/cmdline.py b/lib/parse/cmdline.py
index 7c3eb15b0..7db4834a3 100644
--- a/lib/parse/cmdline.py
+++ b/lib/parse/cmdline.py
@@ -275,6 +275,9 @@ def cmdLineParser():
enumeration.add_option("--dump-all", dest="dumpAll", action="store_true",
help="Dump all DBMS databases tables entries")
+ enumeration.add_option("--search", dest="search", action="store_true",
+ help="Search column(s), table(s) and/or database name(s)")
+
enumeration.add_option("-D", dest="db",
help="DBMS database to enumerate")
diff --git a/lib/parse/queriesfile.py b/lib/parse/queriesfile.py
index c1b2906b0..0f8cdc6fd 100644
--- a/lib/parse/queriesfile.py
+++ b/lib/parse/queriesfile.py
@@ -207,13 +207,6 @@ class queriesHandler(ContentHandler):
self.__queries.columns = self.__columns
- elif name == "dump_column":
- self.__dumpColumn = {}
- self.__dumpColumn["inband"] = { "query": self.__inband, "query2": self.__inband2, "condition": self.__conditionInband, "condition2": self.__conditionInband2 }
- self.__dumpColumn["blind"] = { "query": self.__blind, "query2": self.__blind2, "count": self.__count, "count2": self.__count2, "condition": self.__conditionBlind, "condition2": self.__conditionBlind2 }
-
- self.__queries.dumpColumn = self.__dumpColumn
-
elif name == "dump_table":
self.__dumpTable = {}
self.__dumpTable["inband"] = { "query": self.__inband }
@@ -221,6 +214,27 @@ class queriesHandler(ContentHandler):
self.__queries.dumpTable = self.__dumpTable
+ elif name == "search_db":
+ self.__searchDb = {}
+ self.__searchDb["inband"] = { "query": self.__inband, "query2": self.__inband2, "condition": self.__conditionInband, "condition2": self.__conditionInband2 }
+ self.__searchDb["blind"] = { "query": self.__blind, "query2": self.__blind2, "count": self.__count, "count2": self.__count2, "condition": self.__conditionBlind, "condition2": self.__conditionBlind2 }
+
+ self.__queries.searchDb = self.__searchDb
+
+ elif name == "search_table":
+ self.__searchTable = {}
+ self.__searchTable["inband"] = { "query": self.__inband, "query2": self.__inband2, "condition": self.__conditionInband, "condition2": self.__conditionInband2 }
+ self.__searchTable["blind"] = { "query": self.__blind, "query2": self.__blind2, "count": self.__count, "count2": self.__count2, "condition": self.__conditionBlind, "condition2": self.__conditionBlind2 }
+
+ self.__queries.searchTable = self.__searchTable
+
+ elif name == "search_column":
+ self.__searchColumn = {}
+ self.__searchColumn["inband"] = { "query": self.__inband, "query2": self.__inband2, "condition": self.__conditionInband, "condition2": self.__conditionInband2 }
+ self.__searchColumn["blind"] = { "query": self.__blind, "query2": self.__blind2, "count": self.__count, "count2": self.__count2, "condition": self.__conditionBlind, "condition2": self.__conditionBlind2 }
+
+ self.__queries.searchColumn = self.__searchColumn
+
def queriesParser():
"""
This function calls a class to parse the default DBMS queries
diff --git a/plugins/dbms/access/enumeration.py b/plugins/dbms/access/enumeration.py
index c4670dded..1fa10e4f0 100644
--- a/plugins/dbms/access/enumeration.py
+++ b/plugins/dbms/access/enumeration.py
@@ -29,7 +29,7 @@ from plugins.generic.enumeration import Enumeration as GenericEnumeration
class Enumeration(GenericEnumeration):
def __init__(self):
GenericEnumeration.__init__(self, "Microsoft Access")
-
+
def getDbs(self):
warnMsg = "on Microsoft Access it is not possible to enumerate databases"
logger.warn(warnMsg)
@@ -47,3 +47,9 @@ class Enumeration(GenericEnumeration):
logger.warn(warnMsg)
return {}
+
+ def searchDb(self):
+ warnMsg = "on Microsoft Access it is not possible to search databases"
+ logger.warn(warnMsg)
+
+ return []
diff --git a/plugins/dbms/firebird/enumeration.py b/plugins/dbms/firebird/enumeration.py
index 4462f44cb..76254bb6c 100644
--- a/plugins/dbms/firebird/enumeration.py
+++ b/plugins/dbms/firebird/enumeration.py
@@ -41,3 +41,9 @@ class Enumeration(GenericEnumeration):
logger.warn(warnMsg)
return {}
+
+ def searchDb(self):
+ warnMsg = "on Firebird it is not possible to search databases"
+ logger.warn(warnMsg)
+
+ return []
diff --git a/plugins/dbms/oracle/enumeration.py b/plugins/dbms/oracle/enumeration.py
index f6ee4ff26..2edd43578 100644
--- a/plugins/dbms/oracle/enumeration.py
+++ b/plugins/dbms/oracle/enumeration.py
@@ -180,3 +180,9 @@ class Enumeration(GenericEnumeration):
logger.warn(warnMsg)
return []
+
+ def searchDb(self):
+ warnMsg = "on Oracle it is not possible to search databases"
+ logger.warn(warnMsg)
+
+ return []
diff --git a/plugins/dbms/sqlite/enumeration.py b/plugins/dbms/sqlite/enumeration.py
index e9af5cbb3..0daf4c6a1 100644
--- a/plugins/dbms/sqlite/enumeration.py
+++ b/plugins/dbms/sqlite/enumeration.py
@@ -78,10 +78,16 @@ class Enumeration(GenericEnumeration):
logger.warn(errMsg)
- def dumpColumn(self):
- errMsg = "on SQLite you must specify the table and columns to dump"
- raise sqlmapUnsupportedFeatureException, errMsg
-
def dumpAll(self):
errMsg = "on SQLite you must specify the table and columns to dump"
raise sqlmapUnsupportedFeatureException, errMsg
+
+ def searchDb(self):
+ warnMsg = "on SQLite it is not possible to search databases"
+ logger.warn(warnMsg)
+
+ return []
+
+ def searchColumn(self):
+ errMsg = "on SQLite you must specify the table and columns to dump"
+ raise sqlmapUnsupportedFeatureException, errMsg
diff --git a/plugins/generic/enumeration.py b/plugins/generic/enumeration.py
index 68caff95a..cca9123b2 100644
--- a/plugins/generic/enumeration.py
+++ b/plugins/generic/enumeration.py
@@ -28,6 +28,7 @@ from lib.core.agent import agent
from lib.core.common import getRange
from lib.core.common import parsePasswordHash
from lib.core.common import readInput
+from lib.core.common import safeStringFormat
from lib.core.convert import urlencode
from lib.core.data import conf
from lib.core.data import kb
@@ -971,313 +972,18 @@ class Enumeration:
return kb.data.cachedColumns
- def dumpColumn(self):
- if kb.dbms == "MySQL" and not kb.data.has_information_schema:
- errMsg = "information_schema not available, "
- errMsg += "back-end DBMS is MySQL < 5.0"
- raise sqlmapUnsupportedFeatureException, errMsg
-
- if not conf.col:
- errMsg = "missing column parameter"
- raise sqlmapMissingMandatoryOptionException, errMsg
-
- rootQuery = queries[kb.dbms].dumpColumn
- foundCols = {}
- dbs = {}
- colList = conf.col.split(",")
- colCond = rootQuery["inband"]["condition"]
- dbCond = rootQuery["inband"]["condition2"]
-
- message = "do you want sqlmap to consider provided column(s):\n"
- message += "[1] as LIKE column names (default)\n"
- message += "[2] as exact column names"
- colConsider = readInput(message, default="1")
-
- if not colConsider or colConsider.isdigit() and colConsider == "1":
- colConsider = "1"
- colCondParam = " LIKE '%%%s%%'"
- elif colConsider.isdigit() and colConsider == "2":
- colCondParam = "='%s'"
- else:
- errMsg = "invalid value"
- raise sqlmapNoneDataException, errMsg
-
- for column in colList:
- if kb.dbms == "Oracle":
- column = column.upper()
- conf.db = "USERS"
- elif kb.dbms == "Microsoft SQL Server":
- if not conf.db:
- if not len(kb.data.cachedDbs):
- enumDbs = self.getDbs()
- else:
- enumDbs = kb.data.cachedDbs
-
- conf.db = ",".join(db for db in enumDbs)
-
- foundCols[column] = {}
-
- if conf.db:
- for db in conf.db.split(","):
- dbs[db] = {}
- foundCols[column][db] = []
-
- continue
-
- infoMsg = "fetching databases with tables containing column"
- if colConsider == "1":
- infoMsg += "s like"
- infoMsg += " '%s'" % column
- logger.info(infoMsg)
-
- if conf.excludeSysDbs and kb.dbms != "Oracle":
- dbsQuery = "".join(" AND '%s' != %s" % (db, dbCond) for db in self.excludeDbsList)
- infoMsg = "skipping system databases '%s'" % ", ".join(db for db in self.excludeDbsList)
- logger.info(infoMsg)
- else:
- dbsQuery = ""
-
- colQuery = "%s%s" % (colCond, colCondParam)
- colQuery = colQuery % column
-
- if kb.unionPosition or conf.direct:
- query = rootQuery["inband"]["query"]
- query += colQuery
- query += dbsQuery
- values = inject.getValue(query, blind=False)
-
- if values:
- if isinstance(values, str):
- values = [ values ]
-
- for value in values:
- dbs[value] = {}
- foundCols[column][value] = []
- else:
- infoMsg = "fetching number of databases with tables containing column"
- if colConsider == "1":
- infoMsg += "s like"
- infoMsg += " '%s'" % column
- logger.info(infoMsg)
-
- query = rootQuery["blind"]["count"]
- query += colQuery
- query += dbsQuery
- count = inject.getValue(query, inband=False, expected="int", charsetType=2)
-
- if not count.isdigit() or not len(count) or count == "0":
- warnMsg = "no databases have tables containing column"
- if colConsider == "1":
- warnMsg += "s like"
- warnMsg += " '%s'" % column
- logger.warn(warnMsg)
-
- continue
-
- indexRange = getRange(count)
-
- for index in indexRange:
- query = rootQuery["blind"]["query"]
- query += colQuery
- query += dbsQuery
- query = agent.limitQuery(index, query)
- db = inject.getValue(query, inband=False)
- dbs[db] = {}
- foundCols[column][db] = []
-
- for column, dbData in foundCols.items():
- colQuery = "%s%s" % (colCond, colCondParam)
- colQuery = colQuery % column
-
- for db in dbData:
- infoMsg = "fetching tables containing column"
- if colConsider == "1":
- infoMsg += "s like"
- infoMsg += " '%s' in database '%s'" % (column, db)
- logger.info(infoMsg)
-
- if kb.unionPosition or conf.direct:
- query = rootQuery["inband"]["query2"]
-
- if kb.dbms in ( "MySQL", "PostgreSQL" ):
- query = query % db
- query += " AND %s" % colQuery
- elif kb.dbms == "Oracle":
- query += " WHERE %s" % colQuery
- elif kb.dbms == "Microsoft SQL Server":
- query = query % (db, db, db, db, db)
- query += " AND %s" % colQuery.replace("[DB]", db)
-
- values = inject.getValue(query, blind=False)
-
- if values:
- if isinstance(values, str):
- values = [ values ]
-
- for value in values:
- if value not in dbs[db]:
- dbs[db][value] = {}
-
- dbs[db][value][column] = None
- foundCols[column][db].append(value)
- else:
- infoMsg = "fetching number of tables containing column"
- if colConsider == "1":
- infoMsg += "s like"
- infoMsg += " '%s' in database '%s'" % (column, db)
- logger.info(infoMsg)
-
- query = rootQuery["blind"]["count2"]
-
- if kb.dbms in ( "MySQL", "PostgreSQL" ):
- query = query % db
- query += " AND %s" % colQuery
- elif kb.dbms == "Oracle":
- query += " WHERE %s" % colQuery
- elif kb.dbms == "Microsoft SQL Server":
- query = query % (db, db, db, db, db)
- query += " AND %s" % colQuery.replace("[DB]", db)
-
- count = inject.getValue(query, inband=False, expected="int", charsetType=2)
-
- if not count.isdigit() or not len(count) or count == "0":
- warnMsg = "no tables contain column"
- if colConsider == "1":
- warnMsg += "s like"
- warnMsg += " '%s' " % column
- warnMsg += "in database '%s'" % db
- logger.warn(warnMsg)
-
- continue
-
- indexRange = getRange(count)
-
- for index in indexRange:
- query = rootQuery["blind"]["query2"]
-
- if kb.dbms in ( "MySQL", "PostgreSQL" ):
- query = query % db
- query += " AND %s" % colQuery
- field = None
- elif kb.dbms == "Oracle":
- query += " WHERE %s" % colQuery
- field = None
- elif kb.dbms == "Microsoft SQL Server":
- query = query % (db, db, db, db, db)
- query += " AND %s" % colQuery.replace("[DB]", db)
- field = colCond.replace("[DB]", db)
-
- query = agent.limitQuery(index, query, field)
- tbl = inject.getValue(query, inband=False)
-
- if tbl not in dbs[db]:
- dbs[db][tbl] = {}
-
- dbs[db][tbl][column] = None
- foundCols[column][db].append(tbl)
-
- if colConsider == "1":
- okDbs = {}
-
- for db, tableData in dbs.items():
- conf.db = db
- okDbs[db] = {}
-
- for tbl, columns in tableData.items():
- conf.tbl = tbl
-
- for column in columns:
- conf.col = column
-
- self.getColumns(onlyColNames=True)
-
- if tbl in okDbs[db]:
- okDbs[db][tbl].update(kb.data.cachedColumns[db][tbl])
- else:
- okDbs[db][tbl] = kb.data.cachedColumns[db][tbl]
-
- kb.data.cachedColumns = {}
-
- dbs = okDbs
-
- if not dbs:
- warnMsg = "no databases have tables containing any of the "
- warnMsg += "provided columns"
- logger.warn(warnMsg)
- return
-
- dumper.dbColumns(foundCols, colConsider, dbs)
-
- message = "do you want to dump entries? [Y/n] "
- output = readInput(message, default="Y")
-
- if output and output[0] not in ("y", "Y"):
- return
-
- dumpFromDbs = []
- message = "which database(s)?\n[a]ll (default)\n"
-
- for db, tblData in dbs.items():
- if tblData:
- message += "[%s]\n" % db
-
- message += "[q]uit"
- test = readInput(message, default="a")
-
- if not test or test in ("a", "A"):
- dumpFromDbs = dbs.keys()
- elif test in ("q", "Q"):
- return
- else:
- dumpFromDbs = test.replace(" ", "").split(",")
-
- for db, tblData in dbs.items():
- if db not in dumpFromDbs or not tblData:
- continue
-
- conf.db = db
- dumpFromTbls = []
- message = "which table(s) of database '%s'?\n" % db
- message += "[a]ll (default)\n"
-
- for tbl in tblData:
- message += "[%s]\n" % tbl
-
- message += "[s]kip\n"
- message += "[q]uit"
- test = readInput(message, default="a")
-
- if not test or test in ("a", "A"):
- dumpFromTbls = tblData
- elif test in ("s", "S"):
- continue
- elif test in ("q", "Q"):
- return
- else:
- dumpFromTbls = test.replace(" ", "").split(",")
-
- for table, columns in tblData.items():
- if table not in dumpFromTbls:
- continue
-
- conf.tbl = table
- conf.col = ",".join(column for column in columns)
- kb.data.cachedColumns = {}
- kb.data.dumpedTable = {}
-
- data = self.dumpTable()
-
- if data:
- dumper.dbTableValues(data)
-
def dumpTable(self):
if not conf.tbl and not conf.col:
- errMsg = "missing both table and column parameters, please "
- errMsg += "provide at least one of them"
+ errMsg = "missing table parameter"
raise sqlmapMissingMandatoryOptionException, errMsg
if conf.col and not conf.tbl:
- self.dumpColumn()
+ warnMsg = "missing table parameter. You only provided "
+ warnMsg += "column(s). sqlmap will search for all databases' "
+ warnMsg += "tables containing the provided column(s)"
+ logger.warn(warnMsg)
+
+ self.searchColumn()
return
if "." in conf.tbl:
@@ -1479,6 +1185,391 @@ class Enumeration:
if data:
dumper.dbTableValues(data)
+ def searchDb(self):
+ foundDbs = []
+ rootQuery = queries[kb.dbms].searchDb
+ dbList = conf.db.split(",")
+
+ if kb.dbms == "MySQL" and not kb.data.has_information_schema:
+ dbCond = rootQuery["inband"]["condition2"]
+ else:
+ dbCond = rootQuery["inband"]["condition"]
+
+ dbConsider, dbCondParam = self.likeOrExact("database")
+
+ for db in dbList:
+ infoMsg = "searching database"
+ if dbConsider == "1":
+ infoMsg += "s like"
+ infoMsg += " '%s'" % db
+ logger.info(infoMsg)
+
+ if conf.excludeSysDbs:
+ exclDbsQuery = "".join(" AND '%s' != %s" % (db, dbCond) for db in self.excludeDbsList)
+ infoMsg = "skipping system databases '%s'" % ", ".join(db for db in self.excludeDbsList)
+ logger.info(infoMsg)
+ else:
+ exclDbsQuery = ""
+
+ dbQuery = "%s%s" % (dbCond, dbCondParam)
+ dbQuery = dbQuery % db
+
+ if kb.unionPosition or conf.direct:
+ if kb.dbms == "MySQL" and not kb.data.has_information_schema:
+ query = rootQuery["inband"]["query2"]
+ else:
+ query = rootQuery["inband"]["query"]
+ query += dbQuery
+ query += exclDbsQuery
+ values = inject.getValue(query, blind=False)
+
+ if values:
+ if isinstance(values, str):
+ values = [ values ]
+
+ for value in values:
+ foundDbs.append(value)
+ else:
+ infoMsg = "fetching number of databases"
+ if dbConsider == "1":
+ infoMsg += "s like"
+ infoMsg += " '%s'" % db
+ logger.info(infoMsg)
+
+ if kb.dbms == "MySQL" and not kb.data.has_information_schema:
+ query = rootQuery["blind"]["count2"]
+ else:
+ query = rootQuery["blind"]["count"]
+ query += dbQuery
+ query += exclDbsQuery
+ count = inject.getValue(query, inband=False, expected="int", charsetType=2)
+
+ if not count.isdigit() or not len(count) or count == "0":
+ warnMsg = "no database"
+ if dbConsider == "1":
+ warnMsg += "s like"
+ warnMsg += " '%s' found" % db
+ logger.warn(warnMsg)
+
+ continue
+
+ indexRange = getRange(count)
+
+ for index in indexRange:
+ if kb.dbms == "MySQL" and not kb.data.has_information_schema:
+ query = rootQuery["blind"]["query2"]
+ else:
+ query = rootQuery["blind"]["query"]
+ query += dbQuery
+ query += exclDbsQuery
+ query = agent.limitQuery(index, query, dbCond)
+
+ foundDbs.append(inject.getValue(query, inband=False))
+
+ return foundDbs
+
+ def searchTable(self):
+ errMsg = "search for table names is not supported yet"
+ raise sqlmapUnsupportedFeatureException, errMsg
+
+ def searchColumn(self):
+ if kb.dbms == "MySQL" and not kb.data.has_information_schema:
+ errMsg = "information_schema not available, "
+ errMsg += "back-end DBMS is MySQL < 5.0"
+ raise sqlmapUnsupportedFeatureException, errMsg
+
+ rootQuery = queries[kb.dbms].searchColumn
+ foundCols = {}
+ dbs = {}
+ colList = conf.col.split(",")
+ colCond = rootQuery["inband"]["condition"]
+ dbCond = rootQuery["inband"]["condition2"]
+
+ colConsider, colCondParam = self.likeOrExact("column")
+
+ for column in colList:
+ if kb.dbms == "Oracle":
+ column = column.upper()
+ conf.db = "USERS"
+ elif kb.dbms == "Microsoft SQL Server":
+ if not conf.db:
+ if not len(kb.data.cachedDbs):
+ enumDbs = self.getDbs()
+ else:
+ enumDbs = kb.data.cachedDbs
+
+ conf.db = ",".join(db for db in enumDbs)
+
+ foundCols[column] = {}
+
+ if conf.db:
+ for db in conf.db.split(","):
+ dbs[db] = {}
+ foundCols[column][db] = []
+
+ continue
+
+ infoMsg = "fetching databases with tables containing column"
+ if colConsider == "1":
+ infoMsg += "s like"
+ infoMsg += " '%s'" % column
+ logger.info(infoMsg)
+
+ if conf.excludeSysDbs and kb.dbms != "Oracle":
+ exclDbsQuery = "".join(" AND '%s' != %s" % (db, dbCond) for db in self.excludeDbsList)
+ infoMsg = "skipping system databases '%s'" % ", ".join(db for db in self.excludeDbsList)
+ logger.info(infoMsg)
+ else:
+ exclDbsQuery = ""
+
+ colQuery = "%s%s" % (colCond, colCondParam)
+ colQuery = colQuery % column
+
+ if kb.unionPosition or conf.direct:
+ query = rootQuery["inband"]["query"]
+ query += colQuery
+ query += exclDbsQuery
+ values = inject.getValue(query, blind=False)
+
+ if values:
+ if isinstance(values, str):
+ values = [ values ]
+
+ for value in values:
+ dbs[value] = {}
+ foundCols[column][value] = []
+ else:
+ infoMsg = "fetching number of databases with tables containing column"
+ if colConsider == "1":
+ infoMsg += "s like"
+ infoMsg += " '%s'" % column
+ logger.info(infoMsg)
+
+ query = rootQuery["blind"]["count"]
+ query += colQuery
+ query += exclDbsQuery
+ count = inject.getValue(query, inband=False, expected="int", charsetType=2)
+
+ if not count.isdigit() or not len(count) or count == "0":
+ warnMsg = "no databases have tables containing column"
+ if colConsider == "1":
+ warnMsg += "s like"
+ warnMsg += " '%s'" % column
+ logger.warn(warnMsg)
+
+ continue
+
+ indexRange = getRange(count)
+
+ for index in indexRange:
+ query = rootQuery["blind"]["query"]
+ query += colQuery
+ query += exclDbsQuery
+ query = agent.limitQuery(index, query)
+ db = inject.getValue(query, inband=False)
+ dbs[db] = {}
+ foundCols[column][db] = []
+
+ for column, dbData in foundCols.items():
+ colQuery = "%s%s" % (colCond, colCondParam)
+ colQuery = colQuery % column
+
+ for db in dbData:
+ infoMsg = "fetching tables containing column"
+ if colConsider == "1":
+ infoMsg += "s like"
+ infoMsg += " '%s' in database '%s'" % (column, db)
+ logger.info(infoMsg)
+
+ if kb.unionPosition or conf.direct:
+ query = rootQuery["inband"]["query2"]
+
+ if kb.dbms in ( "MySQL", "PostgreSQL" ):
+ query = query % db
+ query += " AND %s" % colQuery
+ elif kb.dbms == "Oracle":
+ query += " WHERE %s" % colQuery
+ elif kb.dbms == "Microsoft SQL Server":
+ query = query % (db, db, db, db, db)
+ query += " AND %s" % colQuery.replace("[DB]", db)
+
+ values = inject.getValue(query, blind=False)
+
+ if values:
+ if isinstance(values, str):
+ values = [ values ]
+
+ for value in values:
+ if value not in dbs[db]:
+ dbs[db][value] = {}
+
+ dbs[db][value][column] = None
+ foundCols[column][db].append(value)
+ else:
+ infoMsg = "fetching number of tables containing column"
+ if colConsider == "1":
+ infoMsg += "s like"
+ infoMsg += " '%s' in database '%s'" % (column, db)
+ logger.info(infoMsg)
+
+ query = rootQuery["blind"]["count2"]
+
+ if kb.dbms in ( "MySQL", "PostgreSQL" ):
+ query = query % db
+ query += " AND %s" % colQuery
+ elif kb.dbms == "Oracle":
+ query += " WHERE %s" % colQuery
+ elif kb.dbms == "Microsoft SQL Server":
+ query = query % (db, db, db, db, db)
+ query += " AND %s" % colQuery.replace("[DB]", db)
+
+ count = inject.getValue(query, inband=False, expected="int", charsetType=2)
+
+ if not count.isdigit() or not len(count) or count == "0":
+ warnMsg = "no tables contain column"
+ if colConsider == "1":
+ warnMsg += "s like"
+ warnMsg += " '%s' " % column
+ warnMsg += "in database '%s'" % db
+ logger.warn(warnMsg)
+
+ continue
+
+ indexRange = getRange(count)
+
+ for index in indexRange:
+ query = rootQuery["blind"]["query2"]
+
+ if kb.dbms in ( "MySQL", "PostgreSQL" ):
+ query = query % db
+ query += " AND %s" % colQuery
+ field = None
+ elif kb.dbms == "Oracle":
+ query += " WHERE %s" % colQuery
+ field = None
+ elif kb.dbms == "Microsoft SQL Server":
+ query = query % (db, db, db, db, db)
+ query += " AND %s" % colQuery.replace("[DB]", db)
+ field = colCond.replace("[DB]", db)
+
+ query = agent.limitQuery(index, query, field)
+ tbl = inject.getValue(query, inband=False)
+
+ if tbl not in dbs[db]:
+ dbs[db][tbl] = {}
+
+ dbs[db][tbl][column] = None
+ foundCols[column][db].append(tbl)
+
+ if colConsider == "1":
+ okDbs = {}
+
+ for db, tableData in dbs.items():
+ conf.db = db
+ okDbs[db] = {}
+
+ for tbl, columns in tableData.items():
+ conf.tbl = tbl
+
+ for column in columns:
+ conf.col = column
+
+ self.getColumns(onlyColNames=True)
+
+ if tbl in okDbs[db]:
+ okDbs[db][tbl].update(kb.data.cachedColumns[db][tbl])
+ else:
+ okDbs[db][tbl] = kb.data.cachedColumns[db][tbl]
+
+ kb.data.cachedColumns = {}
+
+ dbs = okDbs
+
+ if not dbs:
+ warnMsg = "no databases have tables containing any of the "
+ warnMsg += "provided columns"
+ logger.warn(warnMsg)
+ return
+
+ dumper.dbColumns(foundCols, colConsider, dbs)
+
+ message = "do you want to dump entries? [Y/n] "
+ output = readInput(message, default="Y")
+
+ if output and output[0] not in ("y", "Y"):
+ return
+
+ dumpFromDbs = []
+ message = "which database(s)?\n[a]ll (default)\n"
+
+ for db, tblData in dbs.items():
+ if tblData:
+ message += "[%s]\n" % db
+
+ message += "[q]uit"
+ test = readInput(message, default="a")
+
+ if not test or test in ("a", "A"):
+ dumpFromDbs = dbs.keys()
+ elif test in ("q", "Q"):
+ return
+ else:
+ dumpFromDbs = test.replace(" ", "").split(",")
+
+ for db, tblData in dbs.items():
+ if db not in dumpFromDbs or not tblData:
+ continue
+
+ conf.db = db
+ dumpFromTbls = []
+ message = "which table(s) of database '%s'?\n" % db
+ message += "[a]ll (default)\n"
+
+ for tbl in tblData:
+ message += "[%s]\n" % tbl
+
+ message += "[s]kip\n"
+ message += "[q]uit"
+ test = readInput(message, default="a")
+
+ if not test or test in ("a", "A"):
+ dumpFromTbls = tblData
+ elif test in ("s", "S"):
+ continue
+ elif test in ("q", "Q"):
+ return
+ else:
+ dumpFromTbls = test.replace(" ", "").split(",")
+
+ for table, columns in tblData.items():
+ if table not in dumpFromTbls:
+ continue
+
+ conf.tbl = table
+ conf.col = ",".join(column for column in columns)
+ kb.data.cachedColumns = {}
+ kb.data.dumpedTable = {}
+
+ data = self.dumpTable()
+
+ if data:
+ dumper.dbTableValues(data)
+
+ def search(self):
+ if conf.db:
+ dumper.lister("found databases", self.searchDb())
+
+ if conf.tbl:
+ dumper.dbTables(self.searchTable())
+
+ if conf.col:
+ self.searchColumn()
+
+ if not conf.db and not conf.tbl and not conf.col:
+ errMsg = "missing parameter, provide -D, -T or -C together "
+ errMsg += "with --search"
+ raise sqlmapMissingMandatoryOptionException, errMsg
+
def sqlQuery(self, query):
output = None
sqlType = None
diff --git a/plugins/generic/misc.py b/plugins/generic/misc.py
index 5dd95ad84..4972ab43e 100644
--- a/plugins/generic/misc.py
+++ b/plugins/generic/misc.py
@@ -184,3 +184,21 @@ class Miscellaneous:
warnMsg += "saved on the file system can only be deleted "
warnMsg += "manually"
logger.warn(warnMsg)
+
+ def likeOrExact(self, what):
+ message = "do you want sqlmap to consider provided %s(s):\n" % what
+ message += "[1] as LIKE column names (default)\n"
+ message += "[2] as exact column names"
+
+ choice = readInput(message, default="1")
+
+ if not choice or choice == "1":
+ choice = "1"
+ condParam = " LIKE '%%%s%%'"
+ elif choice.isdigit() and choice == "2":
+ condParam = "='%s'"
+ else:
+ errMsg = "invalid value"
+ raise sqlmapNoneDataException, errMsg
+
+ return choice, condParam
diff --git a/sqlmap.conf b/sqlmap.conf
index 7ee15e2ba..2dfc98272 100644
--- a/sqlmap.conf
+++ b/sqlmap.conf
@@ -290,6 +290,11 @@ dumpTable = False
# Valid: True or False
dumpAll = False
+# Search column(s), table(s) and/or database name(s).
+# Requires: db, tbl or col
+# Valid: True or False
+search = False
+
# Back-end database management system database to enumerate.
db =
diff --git a/xml/queries.xml b/xml/queries.xml
index 0be5618fc..496401f17 100644
--- a/xml/queries.xml
+++ b/xml/queries.xml
@@ -55,14 +55,19 @@
-
-
-
-
+
+
+
+
+
+
+
+
+
@@ -126,14 +131,16 @@
-
-
-
-
+
+
+
+
+
+
@@ -190,14 +197,19 @@
-
-
-
-
+
+
+
+
+
+
+
+
+
@@ -245,14 +257,19 @@
-
-
-
-
+
+
+
+
+
+
+
+
+
@@ -291,11 +308,13 @@
-
+
+
+
@@ -355,10 +374,6 @@
-
-
-
-
@@ -369,7 +384,11 @@
-
+
+
+
+
+