|
|
@ -36,6 +36,7 @@ from thirdparty import six
|
|
|
|
|
|
|
|
|
|
|
|
class Enumeration(GenericEnumeration):
|
|
|
|
class Enumeration(GenericEnumeration):
|
|
|
|
def getPrivileges(self, *args, **kwargs):
|
|
|
|
def getPrivileges(self, *args, **kwargs):
|
|
|
|
|
|
|
|
# 打印用户权限的警告信息
|
|
|
|
warnMsg = "on Microsoft SQL Server it is not possible to fetch "
|
|
|
|
warnMsg = "on Microsoft SQL Server it is not possible to fetch "
|
|
|
|
warnMsg += "database users privileges, sqlmap will check whether "
|
|
|
|
warnMsg += "database users privileges, sqlmap will check whether "
|
|
|
|
warnMsg += "or not the database users are database administrators"
|
|
|
|
warnMsg += "or not the database users are database administrators"
|
|
|
@ -44,6 +45,7 @@ class Enumeration(GenericEnumeration):
|
|
|
|
users = []
|
|
|
|
users = []
|
|
|
|
areAdmins = set()
|
|
|
|
areAdmins = set()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 获取用户列表
|
|
|
|
if conf.user:
|
|
|
|
if conf.user:
|
|
|
|
users = [conf.user]
|
|
|
|
users = [conf.user]
|
|
|
|
elif not len(kb.data.cachedUsers):
|
|
|
|
elif not len(kb.data.cachedUsers):
|
|
|
@ -57,6 +59,7 @@ class Enumeration(GenericEnumeration):
|
|
|
|
if user is None:
|
|
|
|
if user is None:
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 检查用户是否为 DB Administrator
|
|
|
|
isDba = self.isDba(user)
|
|
|
|
isDba = self.isDba(user)
|
|
|
|
|
|
|
|
|
|
|
|
if isDba is True:
|
|
|
|
if isDba is True:
|
|
|
@ -67,11 +70,14 @@ class Enumeration(GenericEnumeration):
|
|
|
|
return (kb.data.cachedUsersPrivileges, areAdmins)
|
|
|
|
return (kb.data.cachedUsersPrivileges, areAdmins)
|
|
|
|
|
|
|
|
|
|
|
|
def getTables(self):
|
|
|
|
def getTables(self):
|
|
|
|
|
|
|
|
# 如果缓存中已经有表,则直接返回
|
|
|
|
if len(kb.data.cachedTables) > 0:
|
|
|
|
if len(kb.data.cachedTables) > 0:
|
|
|
|
return kb.data.cachedTables
|
|
|
|
return kb.data.cachedTables
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 强制执行数据库枚举
|
|
|
|
self.forceDbmsEnum()
|
|
|
|
self.forceDbmsEnum()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 如果当前数据库是默认值,则获取当前数据库名称
|
|
|
|
if conf.db == CURRENT_DB:
|
|
|
|
if conf.db == CURRENT_DB:
|
|
|
|
conf.db = self.getCurrentDb()
|
|
|
|
conf.db = self.getCurrentDb()
|
|
|
|
|
|
|
|
|
|
|
@ -80,6 +86,7 @@ class Enumeration(GenericEnumeration):
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
dbs = self.getDbs()
|
|
|
|
dbs = self.getDbs()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 安全化数据库名称
|
|
|
|
for db in dbs:
|
|
|
|
for db in dbs:
|
|
|
|
dbs[dbs.index(db)] = safeSQLIdentificatorNaming(db)
|
|
|
|
dbs[dbs.index(db)] = safeSQLIdentificatorNaming(db)
|
|
|
|
|
|
|
|
|
|
|
@ -93,11 +100,13 @@ class Enumeration(GenericEnumeration):
|
|
|
|
|
|
|
|
|
|
|
|
if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct:
|
|
|
|
if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct:
|
|
|
|
for db in dbs:
|
|
|
|
for db in dbs:
|
|
|
|
|
|
|
|
# 跳过系统数据库
|
|
|
|
if conf.excludeSysDbs and db in self.excludeDbsList:
|
|
|
|
if conf.excludeSysDbs and db in self.excludeDbsList:
|
|
|
|
infoMsg = "skipping system database '%s'" % db
|
|
|
|
infoMsg = "skipping system database '%s'" % db
|
|
|
|
singleTimeLogMessage(infoMsg)
|
|
|
|
singleTimeLogMessage(infoMsg)
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 跳过已排除的数据库
|
|
|
|
if conf.exclude and re.search(conf.exclude, db, re.I) is not None:
|
|
|
|
if conf.exclude and re.search(conf.exclude, db, re.I) is not None:
|
|
|
|
infoMsg = "skipping database '%s'" % db
|
|
|
|
infoMsg = "skipping database '%s'" % db
|
|
|
|
singleTimeLogMessage(infoMsg)
|
|
|
|
singleTimeLogMessage(infoMsg)
|
|
|
@ -114,6 +123,7 @@ class Enumeration(GenericEnumeration):
|
|
|
|
value = [safeSQLIdentificatorNaming(unArrayizeValue(_), True) for _ in value]
|
|
|
|
value = [safeSQLIdentificatorNaming(unArrayizeValue(_), True) for _ in value]
|
|
|
|
kb.data.cachedTables[db] = value
|
|
|
|
kb.data.cachedTables[db] = value
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 如果缓存表为空且可以进行推断,则进行推断查询
|
|
|
|
if not kb.data.cachedTables and isInferenceAvailable() and not conf.direct:
|
|
|
|
if not kb.data.cachedTables and isInferenceAvailable() and not conf.direct:
|
|
|
|
for db in dbs:
|
|
|
|
for db in dbs:
|
|
|
|
if conf.excludeSysDbs and db in self.excludeDbsList:
|
|
|
|
if conf.excludeSysDbs and db in self.excludeDbsList:
|
|
|
@ -145,6 +155,7 @@ class Enumeration(GenericEnumeration):
|
|
|
|
|
|
|
|
|
|
|
|
tables = []
|
|
|
|
tables = []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 根据表数量进行查询并获取表名
|
|
|
|
for index in xrange(int(count)):
|
|
|
|
for index in xrange(int(count)):
|
|
|
|
_ = 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)
|
|
|
|
_ = 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)
|
|
|
|
|
|
|
|
|
|
|
@ -187,10 +198,12 @@ class Enumeration(GenericEnumeration):
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
enumDbs = kb.data.cachedDbs
|
|
|
|
enumDbs = kb.data.cachedDbs
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 初始化数据库的表列表
|
|
|
|
for db in enumDbs:
|
|
|
|
for db in enumDbs:
|
|
|
|
db = safeSQLIdentificatorNaming(db)
|
|
|
|
db = safeSQLIdentificatorNaming(db)
|
|
|
|
foundTbls[db] = []
|
|
|
|
foundTbls[db] = []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 遍历所有待搜索的表名
|
|
|
|
for tbl in tblList:
|
|
|
|
for tbl in tblList:
|
|
|
|
tbl = safeSQLIdentificatorNaming(tbl, True)
|
|
|
|
tbl = safeSQLIdentificatorNaming(tbl, True)
|
|
|
|
|
|
|
|
|
|
|
@ -216,6 +229,7 @@ class Enumeration(GenericEnumeration):
|
|
|
|
singleTimeLogMessage(infoMsg)
|
|
|
|
singleTimeLogMessage(infoMsg)
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 使用不同的技术进行查询
|
|
|
|
if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct:
|
|
|
|
if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct:
|
|
|
|
query = rootQuery.inband.query.replace("%s", db)
|
|
|
|
query = rootQuery.inband.query.replace("%s", db)
|
|
|
|
query += tblQuery
|
|
|
|
query += tblQuery
|
|
|
@ -267,11 +281,13 @@ class Enumeration(GenericEnumeration):
|
|
|
|
if len(tbls) == 0:
|
|
|
|
if len(tbls) == 0:
|
|
|
|
foundTbls.pop(db)
|
|
|
|
foundTbls.pop(db)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 如果没有找到任何表,则记录警告
|
|
|
|
if not foundTbls:
|
|
|
|
if not foundTbls:
|
|
|
|
warnMsg = "no databases contain any of the provided tables"
|
|
|
|
warnMsg = "no databases contain any of the provided tables"
|
|
|
|
logger.warning(warnMsg)
|
|
|
|
logger.warning(warnMsg)
|
|
|
|
return
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 保存找到的表的信息
|
|
|
|
conf.dumper.dbTables(foundTbls)
|
|
|
|
conf.dumper.dbTables(foundTbls)
|
|
|
|
self.dumpFoundTables(foundTbls)
|
|
|
|
self.dumpFoundTables(foundTbls)
|
|
|
|
|
|
|
|
|
|
|
@ -303,10 +319,12 @@ class Enumeration(GenericEnumeration):
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
enumDbs = kb.data.cachedDbs
|
|
|
|
enumDbs = kb.data.cachedDbs
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 初始化数据库和列的搜索结果
|
|
|
|
for db in enumDbs:
|
|
|
|
for db in enumDbs:
|
|
|
|
db = safeSQLIdentificatorNaming(db)
|
|
|
|
db = safeSQLIdentificatorNaming(db)
|
|
|
|
dbs[db] = {}
|
|
|
|
dbs[db] = {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 遍历待搜索的列名
|
|
|
|
for column in colList:
|
|
|
|
for column in colList:
|
|
|
|
column = safeSQLIdentificatorNaming(column)
|
|
|
|
column = safeSQLIdentificatorNaming(column)
|
|
|
|
conf.db = origDb
|
|
|
|
conf.db = origDb
|
|
|
@ -319,6 +337,7 @@ class Enumeration(GenericEnumeration):
|
|
|
|
|
|
|
|
|
|
|
|
foundCols[column] = {}
|
|
|
|
foundCols[column] = {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 如果指定了表,构建查询条件
|
|
|
|
if conf.tbl:
|
|
|
|
if conf.tbl:
|
|
|
|
_ = conf.tbl.split(',')
|
|
|
|
_ = conf.tbl.split(',')
|
|
|
|
whereTblsQuery = " AND (" + " OR ".join("%s = '%s'" % (tblCond, unsafeSQLIdentificatorNaming(tbl)) for tbl in _) + ")"
|
|
|
|
whereTblsQuery = " AND (" + " OR ".join("%s = '%s'" % (tblCond, unsafeSQLIdentificatorNaming(tbl)) for tbl in _) + ")"
|
|
|
@ -327,6 +346,7 @@ class Enumeration(GenericEnumeration):
|
|
|
|
if conf.db == CURRENT_DB:
|
|
|
|
if conf.db == CURRENT_DB:
|
|
|
|
conf.db = self.getCurrentDb()
|
|
|
|
conf.db = self.getCurrentDb()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 获取当前数据库信息
|
|
|
|
if conf.db:
|
|
|
|
if conf.db:
|
|
|
|
_ = conf.db.split(',')
|
|
|
|
_ = conf.db.split(',')
|
|
|
|
infoMsgDb = " in database%s '%s'" % ("s" if len(_) > 1 else "", ", ".join(db for db in _))
|
|
|
|
infoMsgDb = " in database%s '%s'" % ("s" if len(_) > 1 else "", ", ".join(db for db in _))
|
|
|
@ -340,6 +360,7 @@ class Enumeration(GenericEnumeration):
|
|
|
|
colQuery = "%s%s" % (colCond, colCondParam)
|
|
|
|
colQuery = "%s%s" % (colCond, colCondParam)
|
|
|
|
colQuery = colQuery % unsafeSQLIdentificatorNaming(column)
|
|
|
|
colQuery = colQuery % unsafeSQLIdentificatorNaming(column)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 在每个数据库中搜索列
|
|
|
|
for db in (_ for _ in dbs if _):
|
|
|
|
for db in (_ for _ in dbs if _):
|
|
|
|
db = safeSQLIdentificatorNaming(db)
|
|
|
|
db = safeSQLIdentificatorNaming(db)
|
|
|
|
|
|
|
|
|
|
|
@ -349,6 +370,7 @@ class Enumeration(GenericEnumeration):
|
|
|
|
if conf.exclude and re.search(conf.exclude, db, re.I) is not None:
|
|
|
|
if conf.exclude and re.search(conf.exclude, db, re.I) is not None:
|
|
|
|
continue
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 使用不同的技术进行查询
|
|
|
|
if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct:
|
|
|
|
if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct:
|
|
|
|
query = rootQuery.inband.query % (db, db, db, db, db, db)
|
|
|
|
query = rootQuery.inband.query % (db, db, db, db, db, db)
|
|
|
|
query += " AND %s" % colQuery.replace("[DB]", db)
|
|
|
|
query += " AND %s" % colQuery.replace("[DB]", db)
|
|
|
@ -395,6 +417,7 @@ class Enumeration(GenericEnumeration):
|
|
|
|
infoMsg += " '%s' in database '%s'" % (column, db)
|
|
|
|
infoMsg += " '%s' in database '%s'" % (column, db)
|
|
|
|
logger.info("%s%s" % (infoMsg, infoMsgTbl))
|
|
|
|
logger.info("%s%s" % (infoMsg, infoMsgTbl))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 获取列表数量
|
|
|
|
query = rootQuery.blind.count
|
|
|
|
query = rootQuery.blind.count
|
|
|
|
query = query % (db, db, db, db, db, db)
|
|
|
|
query = query % (db, db, db, db, db, db)
|
|
|
|
query += " AND %s" % colQuery.replace("[DB]", db)
|
|
|
|
query += " AND %s" % colQuery.replace("[DB]", db)
|
|
|
@ -413,6 +436,7 @@ class Enumeration(GenericEnumeration):
|
|
|
|
|
|
|
|
|
|
|
|
indexRange = getLimitRange(count)
|
|
|
|
indexRange = getLimitRange(count)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 获取表名
|
|
|
|
for index in indexRange:
|
|
|
|
for index in indexRange:
|
|
|
|
query = rootQuery.blind.query
|
|
|
|
query = rootQuery.blind.query
|
|
|
|
query = query % (db, db, db, db, db, db)
|
|
|
|
query = query % (db, db, db, db, db, db)
|
|
|
@ -432,6 +456,7 @@ class Enumeration(GenericEnumeration):
|
|
|
|
conf.tbl = tbl
|
|
|
|
conf.tbl = tbl
|
|
|
|
conf.col = column
|
|
|
|
conf.col = column
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 获取列信息
|
|
|
|
self.getColumns(onlyColNames=True, colTuple=(colConsider, colCondParam), bruteForce=False)
|
|
|
|
self.getColumns(onlyColNames=True, colTuple=(colConsider, colCondParam), bruteForce=False)
|
|
|
|
|
|
|
|
|
|
|
|
if db in kb.data.cachedColumns and tbl in kb.data.cachedColumns[db]:
|
|
|
|
if db in kb.data.cachedColumns and tbl in kb.data.cachedColumns[db]:
|
|
|
@ -440,7 +465,9 @@ class Enumeration(GenericEnumeration):
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
dbs[db][tbl][column] = None
|
|
|
|
dbs[db][tbl][column] = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 记录找到的列
|
|
|
|
foundCols[column][db].append(tbl)
|
|
|
|
foundCols[column][db].append(tbl)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 保存找到的列的信息
|
|
|
|
conf.dumper.dbColumns(foundCols, colConsider, dbs)
|
|
|
|
conf.dumper.dbColumns(foundCols, colConsider, dbs)
|
|
|
|
self.dumpFoundColumn(dbs, foundCols, colConsider)
|
|
|
|
self.dumpFoundColumn(dbs, foundCols, colConsider)
|
|
|
|