Added support to search for tables (--search with -T). See #190.

This commit is contained in:
Bernardo Damele
2010-05-16 20:46:17 +00:00
parent e938331d8e
commit c9ee11e0e4
4 changed files with 235 additions and 9 deletions

View File

@@ -22,6 +22,8 @@ with sqlmap; if not, write to the Free Software Foundation, Inc., 51
Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""
from lib.core.agent import agent
from lib.core.common import getRange
from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
@@ -116,3 +118,89 @@ class Enumeration(GenericEnumeration):
raise sqlmapNoneDataException(errMsg)
return kb.data.cachedTables
def searchTable(self):
rootQuery = queries[kb.dbms].searchTable
foundTbls = {}
tblList = conf.tbl.split(",")
tblCond = rootQuery["inband"]["condition"]
dbCond = rootQuery["inband"]["condition2"]
tblConsider, tblCondParam = self.likeOrExact("table")
if not len(kb.data.cachedDbs):
enumDbs = self.getDbs()
else:
enumDbs = kb.data.cachedDbs
for db in enumDbs:
foundTbls[db] = []
for tbl in tblList:
infoMsg = "searching table"
if tblConsider == "1":
infoMsg += "s like"
infoMsg += " '%s'" % tbl
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 = ""
tblQuery = "%s%s" % (tblCond, tblCondParam)
tblQuery = tblQuery % tbl
for db in foundTbls.keys():
if kb.unionPosition or conf.direct:
query = rootQuery["inband"]["query"] % db
query += tblQuery
query += exclDbsQuery
values = inject.getValue(query, blind=False)
if values:
if isinstance(values, str):
values = [ values ]
for foundTbl in values:
foundTbls[db].append(foundTbl)
else:
infoMsg = "fetching number of table"
if tblConsider == "1":
infoMsg += "s like"
infoMsg += " '%s' in database '%s'" % (tbl, db)
logger.info(infoMsg)
query = rootQuery["blind"]["count2"]
query = query % db
query += " AND %s" % tblQuery
count = inject.getValue(query, inband=False, expected="int", charsetType=2)
if not count.isdigit() or not len(count) or count == "0":
warnMsg = "no table"
if tblConsider == "1":
warnMsg += "s like"
warnMsg += " '%s' " % tbl
warnMsg += "in database '%s'" % db
logger.warn(warnMsg)
continue
indexRange = getRange(count)
for index in indexRange:
query = rootQuery["blind"]["query2"]
query = query % db
query += " AND %s" % tblQuery
query = agent.limitQuery(index, query, tblCond)
tbl = inject.getValue(query, inband=False)
kb.hintValue = tbl
foundTbls[db].append(tbl)
for db, tbls in foundTbls.items():
if len(tbls) == 0:
foundTbls.pop(db)
return foundTbls

View File

@@ -1269,8 +1269,125 @@ class Enumeration:
return foundDbs
def searchTable(self):
errMsg = "search for table names is not supported yet"
raise sqlmapUnsupportedFeatureException, errMsg
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].searchTable
foundTbls = {}
tblList = conf.tbl.split(",")
tblCond = rootQuery["inband"]["condition"]
dbCond = rootQuery["inband"]["condition2"]
tblConsider, tblCondParam = self.likeOrExact("table")
for tbl in tblList:
if kb.dbms == "Oracle":
tbl = tbl.upper()
infoMsg = "searching table"
if tblConsider == "1":
infoMsg += "s like"
infoMsg += " '%s'" % tbl
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 = ""
tblQuery = "%s%s" % (tblCond, tblCondParam)
tblQuery = tblQuery % tbl
if kb.unionPosition or conf.direct:
query = rootQuery["inband"]["query"]
query += tblQuery
query += exclDbsQuery
values = inject.getValue(query, blind=False)
if values:
if isinstance(values, str):
values = [ values ]
for foundDb, foundTbl in values:
if foundDb in foundTbls:
foundTbls[foundDb].append(foundTbl)
else:
foundTbls[foundDb] = [ foundTbl ]
else:
infoMsg = "fetching number of databases with table"
if tblConsider == "1":
infoMsg += "s like"
infoMsg += " '%s'" % tbl
logger.info(infoMsg)
query = rootQuery["blind"]["count"]
query += tblQuery
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 table"
if tblConsider == "1":
warnMsg += "s like"
warnMsg += " '%s'" % tbl
logger.warn(warnMsg)
continue
indexRange = getRange(count)
for index in indexRange:
query = rootQuery["blind"]["query"]
query += tblQuery
query += exclDbsQuery
query = agent.limitQuery(index, query)
foundDb = inject.getValue(query, inband=False)
foundTbls[foundDb] = []
if tblConsider == "2":
foundTbls[foundDb].append(tbl)
if tblConsider == "2":
continue
for db in foundTbls.keys():
infoMsg = "fetching number of table"
if tblConsider == "1":
infoMsg += "s like"
infoMsg += " '%s' in database '%s'" % (tbl, db)
logger.info(infoMsg)
query = rootQuery["blind"]["count2"]
query = query % db
query += " AND %s" % tblQuery
count = inject.getValue(query, inband=False, expected="int", charsetType=2)
if not count.isdigit() or not len(count) or count == "0":
warnMsg = "no table"
if tblConsider == "1":
warnMsg += "s like"
warnMsg += " '%s' " % tbl
warnMsg += "in database '%s'" % db
logger.warn(warnMsg)
continue
indexRange = getRange(count)
for index in indexRange:
query = rootQuery["blind"]["query2"]
query = query % db
query += " AND %s" % tblQuery
query = agent.limitQuery(index, query)
foundTbl = inject.getValue(query, inband=False)
kb.hintValue = foundTbl
foundTbls[db].append(foundTbl)
return foundTbls
def searchColumn(self):
if kb.dbms == "MySQL" and not kb.data.has_information_schema:
@@ -1291,7 +1408,16 @@ class Enumeration:
if kb.dbms == "Oracle":
column = column.upper()
conf.db = "USERS"
elif kb.dbms == "Microsoft SQL Server":
infoMsg = "searching column"
if colConsider == "1":
infoMsg += "s like"
infoMsg += " '%s'" % column
logger.info(infoMsg)
foundCols[column] = {}
if kb.dbms == "Microsoft SQL Server":
if not conf.db:
if not len(kb.data.cachedDbs):
enumDbs = self.getDbs()
@@ -1300,8 +1426,6 @@ class Enumeration:
conf.db = ",".join(db for db in enumDbs)
foundCols[column] = {}
if conf.db:
for db in conf.db.split(","):
dbs[db] = {}

View File

@@ -32,6 +32,7 @@ from lib.core.data import conf
from lib.core.data import kb
from lib.core.data import logger
from lib.core.data import queries
from lib.core.exception import sqlmapNoneDataException
from lib.core.exception import sqlmapUnsupportedFeatureException
from lib.core.session import setRemoteTempPath
from lib.request import inject