数据库枚举模块

wangshenghui_branch
Warmlight 4 months ago
parent 35e72a1620
commit 39986e2ba6

@ -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)

Loading…
Cancel
Save