2019-05-08 13:47:52 +03:00
|
|
|
#!/usr/bin/env python
|
2010-03-23 01:57:57 +03:00
|
|
|
|
|
|
|
"""
|
2019-01-05 23:38:52 +03:00
|
|
|
Copyright (c) 2006-2019 sqlmap developers (http://sqlmap.org/)
|
2017-10-11 15:50:46 +03:00
|
|
|
See the file 'LICENSE' for copying permission
|
2010-03-23 01:57:57 +03:00
|
|
|
"""
|
|
|
|
|
2010-05-17 00:46:17 +04:00
|
|
|
from lib.core.agent import agent
|
2010-12-22 21:55:50 +03:00
|
|
|
from lib.core.common import arrayizeValue
|
2012-02-16 18:42:28 +04:00
|
|
|
from lib.core.common import getLimitRange
|
2012-01-07 23:30:35 +04:00
|
|
|
from lib.core.common import isInferenceAvailable
|
2011-05-26 12:17:21 +04:00
|
|
|
from lib.core.common import isNoneValue
|
2010-12-18 00:45:20 +03:00
|
|
|
from lib.core.common import isNumPosStrValue
|
2011-01-12 04:13:32 +03:00
|
|
|
from lib.core.common import isTechniqueAvailable
|
2011-03-30 01:54:15 +04:00
|
|
|
from lib.core.common import safeSQLIdentificatorNaming
|
2015-07-28 10:33:40 +03:00
|
|
|
from lib.core.common import safeStringFormat
|
2018-02-13 17:53:50 +03:00
|
|
|
from lib.core.common import singleTimeLogMessage
|
2014-11-23 17:33:04 +03:00
|
|
|
from lib.core.common import unArrayizeValue
|
2011-03-30 01:54:15 +04:00
|
|
|
from lib.core.common import unsafeSQLIdentificatorNaming
|
2019-03-28 18:04:38 +03:00
|
|
|
from lib.core.compat import xrange
|
2010-03-23 01:57:57 +03:00
|
|
|
from lib.core.data import conf
|
|
|
|
from lib.core.data import kb
|
|
|
|
from lib.core.data import logger
|
|
|
|
from lib.core.data import queries
|
2012-02-29 18:36:23 +04:00
|
|
|
from lib.core.enums import CHARSET_TYPE
|
2016-12-21 12:33:35 +03:00
|
|
|
from lib.core.enums import DBMS
|
2010-12-10 16:04:36 +03:00
|
|
|
from lib.core.enums import EXPECTED
|
2011-01-15 13:14:05 +03:00
|
|
|
from lib.core.enums import PAYLOAD
|
2012-12-06 17:14:19 +04:00
|
|
|
from lib.core.exception import SqlmapNoneDataException
|
2012-02-16 18:42:28 +04:00
|
|
|
from lib.core.settings import CURRENT_DB
|
2010-03-23 01:57:57 +03:00
|
|
|
from lib.request import inject
|
|
|
|
from plugins.generic.enumeration import Enumeration as GenericEnumeration
|
2019-03-28 15:53:54 +03:00
|
|
|
from thirdparty import six
|
2010-03-23 01:57:57 +03:00
|
|
|
|
|
|
|
class Enumeration(GenericEnumeration):
|
2019-05-30 23:55:54 +03:00
|
|
|
def getPrivileges(self, *args, **kwargs):
|
2011-02-10 17:24:04 +03:00
|
|
|
warnMsg = "on Microsoft SQL Server it is not possible to fetch "
|
|
|
|
warnMsg += "database users privileges, sqlmap will check whether "
|
|
|
|
warnMsg += "or not the database users are database administrators"
|
2010-03-23 01:57:57 +03:00
|
|
|
logger.warn(warnMsg)
|
|
|
|
|
2011-02-10 17:24:04 +03:00
|
|
|
users = []
|
|
|
|
areAdmins = set()
|
|
|
|
|
|
|
|
if conf.user:
|
2013-01-10 14:54:07 +04:00
|
|
|
users = [conf.user]
|
2011-02-10 17:24:04 +03:00
|
|
|
elif not len(kb.data.cachedUsers):
|
|
|
|
users = self.getUsers()
|
|
|
|
else:
|
|
|
|
users = kb.data.cachedUsers
|
|
|
|
|
|
|
|
for user in users:
|
2014-11-23 17:33:04 +03:00
|
|
|
user = unArrayizeValue(user)
|
|
|
|
|
2011-02-10 17:24:04 +03:00
|
|
|
if user is None:
|
|
|
|
continue
|
|
|
|
|
|
|
|
isDba = self.isDba(user)
|
|
|
|
|
|
|
|
if isDba is True:
|
|
|
|
areAdmins.add(user)
|
|
|
|
|
|
|
|
kb.data.cachedUsersPrivileges[user] = None
|
|
|
|
|
2013-01-09 18:38:41 +04:00
|
|
|
return (kb.data.cachedUsersPrivileges, areAdmins)
|
2010-03-23 01:57:57 +03:00
|
|
|
|
|
|
|
def getTables(self):
|
2011-05-01 02:05:02 +04:00
|
|
|
if len(kb.data.cachedTables) > 0:
|
|
|
|
return kb.data.cachedTables
|
|
|
|
|
|
|
|
self.forceDbmsEnum()
|
|
|
|
|
2012-02-16 18:42:28 +04:00
|
|
|
if conf.db == CURRENT_DB:
|
2011-05-01 02:05:02 +04:00
|
|
|
conf.db = self.getCurrentDb()
|
|
|
|
|
2010-03-23 01:57:57 +03:00
|
|
|
if conf.db:
|
2017-04-18 16:56:24 +03:00
|
|
|
dbs = conf.db.split(',')
|
2011-05-01 02:05:02 +04:00
|
|
|
else:
|
|
|
|
dbs = self.getDbs()
|
|
|
|
|
|
|
|
for db in dbs:
|
|
|
|
dbs[dbs.index(db)] = safeSQLIdentificatorNaming(db)
|
|
|
|
|
2019-01-22 05:14:23 +03:00
|
|
|
dbs = [_ for _ in dbs if _]
|
2011-07-30 17:01:37 +04:00
|
|
|
|
2011-05-01 02:05:02 +04:00
|
|
|
infoMsg = "fetching tables for database"
|
2019-03-28 15:53:54 +03:00
|
|
|
infoMsg += "%s: %s" % ("s" if len(dbs) > 1 else "", ", ".join(db if isinstance(db, six.string_types) else db[0] for db in sorted(dbs)))
|
2010-03-23 01:57:57 +03:00
|
|
|
logger.info(infoMsg)
|
|
|
|
|
2016-12-21 12:33:35 +03:00
|
|
|
rootQuery = queries[DBMS.MSSQL].tables
|
2010-03-23 01:57:57 +03:00
|
|
|
|
2012-12-05 13:45:17 +04:00
|
|
|
if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct:
|
2010-03-23 01:57:57 +03:00
|
|
|
for db in dbs:
|
|
|
|
if conf.excludeSysDbs and db in self.excludeDbsList:
|
|
|
|
infoMsg = "skipping system database '%s'" % db
|
2018-02-13 17:53:50 +03:00
|
|
|
singleTimeLogMessage(infoMsg)
|
|
|
|
continue
|
2010-03-23 01:57:57 +03:00
|
|
|
|
2018-02-13 17:53:50 +03:00
|
|
|
if conf.exclude and db in conf.exclude.split(','):
|
|
|
|
infoMsg = "skipping database '%s'" % db
|
|
|
|
singleTimeLogMessage(infoMsg)
|
2010-03-23 01:57:57 +03:00
|
|
|
continue
|
|
|
|
|
2012-02-03 14:56:39 +04:00
|
|
|
for query in (rootQuery.inband.query, rootQuery.inband.query2, rootQuery.inband.query3):
|
2012-01-03 22:01:14 +04:00
|
|
|
query = query.replace("%s", db)
|
2012-10-28 01:16:25 +04:00
|
|
|
value = inject.getValue(query, blind=False, time=False)
|
2012-01-03 22:01:14 +04:00
|
|
|
if not isNoneValue(value):
|
|
|
|
break
|
2010-03-23 01:57:57 +03:00
|
|
|
|
2011-05-26 12:17:21 +04:00
|
|
|
if not isNoneValue(value):
|
2019-01-22 05:14:23 +03:00
|
|
|
value = [_ for _ in arrayizeValue(value) if _]
|
2014-12-22 07:56:48 +03:00
|
|
|
value = [safeSQLIdentificatorNaming(unArrayizeValue(_), True) for _ in value]
|
2012-02-29 18:05:53 +04:00
|
|
|
kb.data.cachedTables[db] = value
|
2010-03-23 01:57:57 +03:00
|
|
|
|
2012-01-07 23:30:35 +04:00
|
|
|
if not kb.data.cachedTables and isInferenceAvailable() and not conf.direct:
|
2010-03-23 01:57:57 +03:00
|
|
|
for db in dbs:
|
|
|
|
if conf.excludeSysDbs and db in self.excludeDbsList:
|
|
|
|
infoMsg = "skipping system database '%s'" % db
|
2018-02-13 17:53:50 +03:00
|
|
|
singleTimeLogMessage(infoMsg)
|
|
|
|
continue
|
2010-03-23 01:57:57 +03:00
|
|
|
|
2018-02-13 17:53:50 +03:00
|
|
|
if conf.exclude and db in conf.exclude.split(','):
|
|
|
|
infoMsg = "skipping database '%s'" % db
|
|
|
|
singleTimeLogMessage(infoMsg)
|
2010-03-23 01:57:57 +03:00
|
|
|
continue
|
|
|
|
|
2011-04-30 17:20:05 +04:00
|
|
|
infoMsg = "fetching number of tables for "
|
2010-03-23 01:57:57 +03:00
|
|
|
infoMsg += "database '%s'" % db
|
|
|
|
logger.info(infoMsg)
|
|
|
|
|
2012-02-03 14:56:39 +04:00
|
|
|
for query in (rootQuery.blind.count, rootQuery.blind.count2, rootQuery.blind.count3):
|
2012-02-01 16:53:07 +04:00
|
|
|
_ = query.replace("%s", db)
|
2012-10-28 02:36:09 +04:00
|
|
|
count = inject.getValue(_, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
|
2012-01-10 01:09:05 +04:00
|
|
|
if not isNoneValue(count):
|
|
|
|
break
|
2010-03-23 01:57:57 +03:00
|
|
|
|
2010-12-18 00:45:20 +03:00
|
|
|
if not isNumPosStrValue(count):
|
2012-04-03 16:19:37 +04:00
|
|
|
if count != 0:
|
2012-01-10 01:09:05 +04:00
|
|
|
warnMsg = "unable to retrieve the number of "
|
|
|
|
warnMsg += "tables for database '%s'" % db
|
|
|
|
logger.warn(warnMsg)
|
2010-03-23 01:57:57 +03:00
|
|
|
continue
|
|
|
|
|
|
|
|
tables = []
|
|
|
|
|
2011-10-22 02:34:27 +04:00
|
|
|
for index in xrange(int(count)):
|
2015-07-28 10:33:40 +03:00
|
|
|
_ = safeStringFormat((rootQuery.blind.query if query == rootQuery.blind.count else rootQuery.blind.query2 if query == rootQuery.blind.count2 else rootQuery.blind.query3).replace("%s", db), index)
|
2012-01-10 01:09:05 +04:00
|
|
|
|
2012-10-28 02:36:09 +04:00
|
|
|
table = inject.getValue(_, union=False, error=False)
|
2012-02-29 17:56:40 +04:00
|
|
|
if not isNoneValue(table):
|
|
|
|
kb.hintValue = table
|
|
|
|
table = safeSQLIdentificatorNaming(table, True)
|
|
|
|
tables.append(table)
|
2010-03-23 01:57:57 +03:00
|
|
|
|
|
|
|
if tables:
|
|
|
|
kb.data.cachedTables[db] = tables
|
|
|
|
else:
|
2011-04-30 17:20:05 +04:00
|
|
|
warnMsg = "unable to retrieve the tables "
|
2010-03-23 01:57:57 +03:00
|
|
|
warnMsg += "for database '%s'" % db
|
|
|
|
logger.warn(warnMsg)
|
|
|
|
|
2015-09-24 14:44:51 +03:00
|
|
|
if not kb.data.cachedTables and not conf.search:
|
2010-03-23 01:57:57 +03:00
|
|
|
errMsg = "unable to retrieve the tables for any database"
|
2012-12-06 17:14:19 +04:00
|
|
|
raise SqlmapNoneDataException(errMsg)
|
2011-10-28 16:49:35 +04:00
|
|
|
else:
|
|
|
|
for db, tables in kb.data.cachedTables.items():
|
2011-10-28 17:07:23 +04:00
|
|
|
kb.data.cachedTables[db] = sorted(tables) if tables else tables
|
2010-03-23 01:57:57 +03:00
|
|
|
|
|
|
|
return kb.data.cachedTables
|
2010-05-17 00:46:17 +04:00
|
|
|
|
|
|
|
def searchTable(self):
|
|
|
|
foundTbls = {}
|
2017-04-18 16:56:24 +03:00
|
|
|
tblList = conf.tbl.split(',')
|
2016-12-21 12:33:35 +03:00
|
|
|
rootQuery = queries[DBMS.MSSQL].search_table
|
2010-10-21 17:13:12 +04:00
|
|
|
tblCond = rootQuery.inband.condition
|
2010-05-17 00:46:17 +04:00
|
|
|
tblConsider, tblCondParam = self.likeOrExact("table")
|
|
|
|
|
2016-10-05 18:43:57 +03:00
|
|
|
if conf.db == CURRENT_DB:
|
|
|
|
conf.db = self.getCurrentDb()
|
|
|
|
|
|
|
|
if conf.db:
|
2017-04-18 16:56:24 +03:00
|
|
|
enumDbs = conf.db.split(',')
|
2012-07-21 02:37:56 +04:00
|
|
|
elif not len(kb.data.cachedDbs):
|
2010-05-17 00:46:17 +04:00
|
|
|
enumDbs = self.getDbs()
|
|
|
|
else:
|
|
|
|
enumDbs = kb.data.cachedDbs
|
|
|
|
|
|
|
|
for db in enumDbs:
|
2011-03-30 01:54:15 +04:00
|
|
|
db = safeSQLIdentificatorNaming(db)
|
2010-05-17 00:46:17 +04:00
|
|
|
foundTbls[db] = []
|
|
|
|
|
|
|
|
for tbl in tblList:
|
2011-03-30 01:54:15 +04:00
|
|
|
tbl = safeSQLIdentificatorNaming(tbl, True)
|
2011-03-28 15:01:55 +04:00
|
|
|
|
2010-05-17 00:46:17 +04:00
|
|
|
infoMsg = "searching table"
|
|
|
|
if tblConsider == "1":
|
2015-09-23 09:47:52 +03:00
|
|
|
infoMsg += "s LIKE"
|
2011-03-30 01:54:15 +04:00
|
|
|
infoMsg += " '%s'" % unsafeSQLIdentificatorNaming(tbl)
|
2010-05-17 00:46:17 +04:00
|
|
|
logger.info(infoMsg)
|
|
|
|
|
|
|
|
tblQuery = "%s%s" % (tblCond, tblCondParam)
|
2011-03-30 01:54:15 +04:00
|
|
|
tblQuery = tblQuery % unsafeSQLIdentificatorNaming(tbl)
|
2010-05-17 00:46:17 +04:00
|
|
|
|
|
|
|
for db in foundTbls.keys():
|
2011-03-30 01:54:15 +04:00
|
|
|
db = safeSQLIdentificatorNaming(db)
|
2011-03-28 15:01:55 +04:00
|
|
|
|
2010-05-17 20:16:49 +04:00
|
|
|
if conf.excludeSysDbs and db in self.excludeDbsList:
|
|
|
|
infoMsg = "skipping system database '%s'" % db
|
2018-02-13 17:53:50 +03:00
|
|
|
singleTimeLogMessage(infoMsg)
|
|
|
|
continue
|
2010-05-17 20:16:49 +04:00
|
|
|
|
2018-02-13 17:53:50 +03:00
|
|
|
if conf.exclude and db in conf.exclude.split(','):
|
|
|
|
infoMsg = "skipping database '%s'" % db
|
|
|
|
singleTimeLogMessage(infoMsg)
|
2010-05-17 20:16:49 +04:00
|
|
|
continue
|
|
|
|
|
2012-12-05 13:45:17 +04:00
|
|
|
if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct:
|
2012-02-01 16:53:07 +04:00
|
|
|
query = rootQuery.inband.query.replace("%s", db)
|
2010-05-17 00:46:17 +04:00
|
|
|
query += tblQuery
|
2012-10-28 01:16:25 +04:00
|
|
|
values = inject.getValue(query, blind=False, time=False)
|
2010-05-17 00:46:17 +04:00
|
|
|
|
2011-05-26 12:17:21 +04:00
|
|
|
if not isNoneValue(values):
|
2019-03-28 15:53:54 +03:00
|
|
|
if isinstance(values, six.string_types):
|
2013-01-10 14:54:07 +04:00
|
|
|
values = [values]
|
2010-05-17 00:46:17 +04:00
|
|
|
|
|
|
|
for foundTbl in values:
|
2011-02-10 14:34:16 +03:00
|
|
|
if foundTbl is None:
|
|
|
|
continue
|
|
|
|
|
2010-05-17 00:46:17 +04:00
|
|
|
foundTbls[db].append(foundTbl)
|
|
|
|
else:
|
|
|
|
infoMsg = "fetching number of table"
|
|
|
|
if tblConsider == "1":
|
2015-09-23 09:47:52 +03:00
|
|
|
infoMsg += "s LIKE"
|
2011-03-30 01:54:15 +04:00
|
|
|
infoMsg += " '%s' in database '%s'" % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(db))
|
2010-05-17 00:46:17 +04:00
|
|
|
logger.info(infoMsg)
|
|
|
|
|
2012-02-01 16:53:07 +04:00
|
|
|
query = rootQuery.blind.count
|
|
|
|
query = query.replace("%s", db)
|
2010-05-17 00:46:17 +04:00
|
|
|
query += " AND %s" % tblQuery
|
2012-10-28 02:36:09 +04:00
|
|
|
count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
|
2010-05-17 00:46:17 +04:00
|
|
|
|
2010-12-18 00:45:20 +03:00
|
|
|
if not isNumPosStrValue(count):
|
2010-05-17 00:46:17 +04:00
|
|
|
warnMsg = "no table"
|
|
|
|
if tblConsider == "1":
|
2015-09-23 09:47:52 +03:00
|
|
|
warnMsg += "s LIKE"
|
2011-03-30 01:54:15 +04:00
|
|
|
warnMsg += " '%s' " % unsafeSQLIdentificatorNaming(tbl)
|
|
|
|
warnMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(db)
|
2010-05-17 00:46:17 +04:00
|
|
|
logger.warn(warnMsg)
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
2012-02-16 18:42:28 +04:00
|
|
|
indexRange = getLimitRange(count)
|
2010-05-17 00:46:17 +04:00
|
|
|
|
|
|
|
for index in indexRange:
|
2012-02-01 16:53:07 +04:00
|
|
|
query = rootQuery.blind.query
|
|
|
|
query = query.replace("%s", db)
|
2010-05-17 00:46:17 +04:00
|
|
|
query += " AND %s" % tblQuery
|
|
|
|
query = agent.limitQuery(index, query, tblCond)
|
2012-10-28 02:36:09 +04:00
|
|
|
tbl = inject.getValue(query, union=False, error=False)
|
2010-05-17 00:46:17 +04:00
|
|
|
kb.hintValue = tbl
|
|
|
|
foundTbls[db].append(tbl)
|
|
|
|
|
2019-05-22 10:30:27 +03:00
|
|
|
for db, tbls in list(foundTbls.items()):
|
2010-05-17 00:46:17 +04:00
|
|
|
if len(tbls) == 0:
|
|
|
|
foundTbls.pop(db)
|
|
|
|
|
2012-07-21 02:37:56 +04:00
|
|
|
if not foundTbls:
|
|
|
|
warnMsg = "no databases contain any of the provided tables"
|
|
|
|
logger.warn(warnMsg)
|
|
|
|
return
|
|
|
|
|
|
|
|
conf.dumper.dbTables(foundTbls)
|
|
|
|
self.dumpFoundTables(foundTbls)
|
2010-05-17 20:16:49 +04:00
|
|
|
|
|
|
|
def searchColumn(self):
|
2016-12-21 12:33:35 +03:00
|
|
|
rootQuery = queries[DBMS.MSSQL].search_column
|
2010-05-17 20:16:49 +04:00
|
|
|
foundCols = {}
|
|
|
|
dbs = {}
|
2012-07-21 03:08:40 +04:00
|
|
|
whereTblsQuery = ""
|
|
|
|
infoMsgTbl = ""
|
2012-07-21 03:20:32 +04:00
|
|
|
infoMsgDb = ""
|
2017-04-18 16:56:24 +03:00
|
|
|
colList = conf.col.split(',')
|
2014-01-13 13:05:49 +04:00
|
|
|
|
2018-02-13 17:53:50 +03:00
|
|
|
if conf.exclude:
|
|
|
|
colList = [_ for _ in colList if _ not in conf.exclude.split(',')]
|
2014-01-13 13:05:49 +04:00
|
|
|
|
2012-07-21 03:08:40 +04:00
|
|
|
origTbl = conf.tbl
|
|
|
|
origDb = conf.db
|
2010-10-21 17:13:12 +04:00
|
|
|
colCond = rootQuery.inband.condition
|
2012-07-21 03:08:40 +04:00
|
|
|
tblCond = rootQuery.inband.condition2
|
2010-05-17 20:16:49 +04:00
|
|
|
colConsider, colCondParam = self.likeOrExact("column")
|
|
|
|
|
2016-10-05 18:43:57 +03:00
|
|
|
if conf.db == CURRENT_DB:
|
|
|
|
conf.db = self.getCurrentDb()
|
|
|
|
|
|
|
|
if conf.db:
|
2017-04-18 16:56:24 +03:00
|
|
|
enumDbs = conf.db.split(',')
|
2012-03-15 21:55:49 +04:00
|
|
|
elif not len(kb.data.cachedDbs):
|
2010-05-17 20:16:49 +04:00
|
|
|
enumDbs = self.getDbs()
|
|
|
|
else:
|
|
|
|
enumDbs = kb.data.cachedDbs
|
|
|
|
|
|
|
|
for db in enumDbs:
|
2011-03-30 01:54:15 +04:00
|
|
|
db = safeSQLIdentificatorNaming(db)
|
2010-05-17 20:16:49 +04:00
|
|
|
dbs[db] = {}
|
|
|
|
|
|
|
|
for column in colList:
|
2011-03-30 01:54:15 +04:00
|
|
|
column = safeSQLIdentificatorNaming(column)
|
2012-07-21 03:08:40 +04:00
|
|
|
conf.db = origDb
|
|
|
|
conf.tbl = origTbl
|
2011-03-28 15:01:55 +04:00
|
|
|
|
2010-05-17 20:16:49 +04:00
|
|
|
infoMsg = "searching column"
|
|
|
|
if colConsider == "1":
|
2015-09-23 09:47:52 +03:00
|
|
|
infoMsg += "s LIKE"
|
2011-03-30 01:54:15 +04:00
|
|
|
infoMsg += " '%s'" % unsafeSQLIdentificatorNaming(column)
|
2010-05-17 20:16:49 +04:00
|
|
|
|
|
|
|
foundCols[column] = {}
|
|
|
|
|
2012-07-21 03:08:40 +04:00
|
|
|
if conf.tbl:
|
2017-04-18 16:56:24 +03:00
|
|
|
_ = conf.tbl.split(',')
|
2012-07-21 03:08:40 +04:00
|
|
|
whereTblsQuery = " AND (" + " OR ".join("%s = '%s'" % (tblCond, unsafeSQLIdentificatorNaming(tbl)) for tbl in _) + ")"
|
|
|
|
infoMsgTbl = " for table%s '%s'" % ("s" if len(_) > 1 else "", ", ".join(tbl for tbl in _))
|
|
|
|
|
2016-10-05 18:43:57 +03:00
|
|
|
if conf.db == CURRENT_DB:
|
|
|
|
conf.db = self.getCurrentDb()
|
|
|
|
|
|
|
|
if conf.db:
|
2017-04-18 16:56:24 +03:00
|
|
|
_ = conf.db.split(',')
|
2012-07-21 03:20:32 +04:00
|
|
|
infoMsgDb = " in database%s '%s'" % ("s" if len(_) > 1 else "", ", ".join(db for db in _))
|
|
|
|
elif conf.excludeSysDbs:
|
2018-02-13 17:53:50 +03:00
|
|
|
infoMsgDb = " not in system database%s '%s'" % ("s" if len(self.excludeDbsList) > 1 else "", ", ".join(db for db in self.excludeDbsList))
|
2012-07-21 03:20:32 +04:00
|
|
|
else:
|
|
|
|
infoMsgDb = " across all databases"
|
|
|
|
|
|
|
|
logger.info("%s%s%s" % (infoMsg, infoMsgTbl, infoMsgDb))
|
2012-07-21 03:08:40 +04:00
|
|
|
|
2010-05-17 20:16:49 +04:00
|
|
|
colQuery = "%s%s" % (colCond, colCondParam)
|
2011-03-30 01:54:15 +04:00
|
|
|
colQuery = colQuery % unsafeSQLIdentificatorNaming(column)
|
2010-05-17 20:16:49 +04:00
|
|
|
|
2019-01-22 05:14:23 +03:00
|
|
|
for db in (_ for _ in dbs if _):
|
2011-03-30 01:54:15 +04:00
|
|
|
db = safeSQLIdentificatorNaming(db)
|
2011-03-28 15:01:55 +04:00
|
|
|
|
2010-05-17 20:16:49 +04:00
|
|
|
if conf.excludeSysDbs and db in self.excludeDbsList:
|
|
|
|
continue
|
|
|
|
|
2018-02-13 17:53:50 +03:00
|
|
|
if conf.exclude and db in conf.exclude.split(','):
|
|
|
|
continue
|
|
|
|
|
2012-12-05 13:45:17 +04:00
|
|
|
if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct:
|
2011-03-28 15:01:55 +04:00
|
|
|
query = rootQuery.inband.query % (db, db, db, db, db, db)
|
2010-05-17 20:16:49 +04:00
|
|
|
query += " AND %s" % colQuery.replace("[DB]", db)
|
2012-07-21 03:08:40 +04:00
|
|
|
query += whereTblsQuery.replace("[DB]", db)
|
2012-10-28 01:16:25 +04:00
|
|
|
values = inject.getValue(query, blind=False, time=False)
|
2010-05-17 20:16:49 +04:00
|
|
|
|
2011-05-26 12:17:21 +04:00
|
|
|
if not isNoneValue(values):
|
2019-03-28 15:53:54 +03:00
|
|
|
if isinstance(values, six.string_types):
|
2013-01-10 14:54:07 +04:00
|
|
|
values = [values]
|
2010-05-17 20:16:49 +04:00
|
|
|
|
|
|
|
for foundTbl in values:
|
2015-09-21 12:02:56 +03:00
|
|
|
foundTbl = safeSQLIdentificatorNaming(unArrayizeValue(foundTbl), True)
|
2011-03-28 15:01:55 +04:00
|
|
|
|
2011-02-10 14:28:24 +03:00
|
|
|
if foundTbl is None:
|
|
|
|
continue
|
|
|
|
|
2010-05-17 20:16:49 +04:00
|
|
|
if foundTbl not in dbs[db]:
|
|
|
|
dbs[db][foundTbl] = {}
|
|
|
|
|
2018-03-13 15:45:42 +03:00
|
|
|
if colConsider == '1':
|
2010-05-17 20:16:49 +04:00
|
|
|
conf.db = db
|
|
|
|
conf.tbl = foundTbl
|
|
|
|
conf.col = column
|
|
|
|
|
2013-12-06 17:26:34 +04:00
|
|
|
self.getColumns(onlyColNames=True, colTuple=(colConsider, colCondParam), bruteForce=False)
|
2011-06-16 18:27:44 +04:00
|
|
|
|
2018-03-13 15:45:42 +03:00
|
|
|
if db in kb.data.cachedColumns and foundTbl in kb.data.cachedColumns[db] and not isNoneValue(kb.data.cachedColumns[db][foundTbl]):
|
2011-03-28 15:01:55 +04:00
|
|
|
dbs[db][foundTbl].update(kb.data.cachedColumns[db][foundTbl])
|
2018-03-13 15:45:42 +03:00
|
|
|
|
2010-05-17 20:16:49 +04:00
|
|
|
kb.data.cachedColumns = {}
|
|
|
|
else:
|
|
|
|
dbs[db][foundTbl][column] = None
|
|
|
|
|
|
|
|
if db in foundCols[column]:
|
|
|
|
foundCols[column][db].append(foundTbl)
|
|
|
|
else:
|
2013-01-10 14:54:07 +04:00
|
|
|
foundCols[column][db] = [foundTbl]
|
2010-05-17 20:16:49 +04:00
|
|
|
else:
|
|
|
|
foundCols[column][db] = []
|
|
|
|
|
|
|
|
infoMsg = "fetching number of tables containing column"
|
|
|
|
if colConsider == "1":
|
2015-09-23 09:47:52 +03:00
|
|
|
infoMsg += "s LIKE"
|
2010-05-17 20:16:49 +04:00
|
|
|
infoMsg += " '%s' in database '%s'" % (column, db)
|
2012-07-21 03:20:32 +04:00
|
|
|
logger.info("%s%s" % (infoMsg, infoMsgTbl))
|
2010-05-17 20:16:49 +04:00
|
|
|
|
2012-02-01 16:53:07 +04:00
|
|
|
query = rootQuery.blind.count
|
2011-03-28 15:01:55 +04:00
|
|
|
query = query % (db, db, db, db, db, db)
|
2010-05-17 20:16:49 +04:00
|
|
|
query += " AND %s" % colQuery.replace("[DB]", db)
|
2012-07-21 03:20:32 +04:00
|
|
|
query += whereTblsQuery.replace("[DB]", db)
|
2012-10-28 02:36:09 +04:00
|
|
|
count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS)
|
2010-05-17 20:16:49 +04:00
|
|
|
|
2010-12-18 00:45:20 +03:00
|
|
|
if not isNumPosStrValue(count):
|
2010-05-17 20:16:49 +04:00
|
|
|
warnMsg = "no tables contain column"
|
|
|
|
if colConsider == "1":
|
2015-09-23 09:47:52 +03:00
|
|
|
warnMsg += "s LIKE"
|
2010-05-17 20:16:49 +04:00
|
|
|
warnMsg += " '%s' " % column
|
|
|
|
warnMsg += "in database '%s'" % db
|
|
|
|
logger.warn(warnMsg)
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
2012-02-16 18:42:28 +04:00
|
|
|
indexRange = getLimitRange(count)
|
2010-05-17 20:16:49 +04:00
|
|
|
|
|
|
|
for index in indexRange:
|
2012-02-01 16:53:07 +04:00
|
|
|
query = rootQuery.blind.query
|
2011-03-28 15:01:55 +04:00
|
|
|
query = query % (db, db, db, db, db, db)
|
2010-05-17 20:16:49 +04:00
|
|
|
query += " AND %s" % colQuery.replace("[DB]", db)
|
2012-07-21 03:20:32 +04:00
|
|
|
query += whereTblsQuery.replace("[DB]", db)
|
2010-05-17 20:16:49 +04:00
|
|
|
query = agent.limitQuery(index, query, colCond.replace("[DB]", db))
|
2012-10-28 02:36:09 +04:00
|
|
|
tbl = inject.getValue(query, union=False, error=False)
|
2010-05-17 20:16:49 +04:00
|
|
|
kb.hintValue = tbl
|
|
|
|
|
2011-03-30 01:54:15 +04:00
|
|
|
tbl = safeSQLIdentificatorNaming(tbl, True)
|
2011-03-28 15:01:55 +04:00
|
|
|
|
2010-05-17 20:16:49 +04:00
|
|
|
if tbl not in dbs[db]:
|
|
|
|
dbs[db][tbl] = {}
|
|
|
|
|
|
|
|
if colConsider == "1":
|
|
|
|
conf.db = db
|
|
|
|
conf.tbl = tbl
|
|
|
|
conf.col = column
|
|
|
|
|
2013-12-06 17:26:34 +04:00
|
|
|
self.getColumns(onlyColNames=True, colTuple=(colConsider, colCondParam), bruteForce=False)
|
2010-05-17 20:16:49 +04:00
|
|
|
|
2011-06-16 18:27:44 +04:00
|
|
|
if db in kb.data.cachedColumns and tbl in kb.data.cachedColumns[db]:
|
|
|
|
dbs[db][tbl].update(kb.data.cachedColumns[db][tbl])
|
2010-05-17 20:16:49 +04:00
|
|
|
kb.data.cachedColumns = {}
|
|
|
|
else:
|
|
|
|
dbs[db][tbl][column] = None
|
|
|
|
|
|
|
|
foundCols[column][db].append(tbl)
|
|
|
|
|
2012-07-21 03:08:40 +04:00
|
|
|
conf.dumper.dbColumns(foundCols, colConsider, dbs)
|
2010-05-17 20:16:49 +04:00
|
|
|
self.dumpFoundColumn(dbs, foundCols, colConsider)
|