diff --git a/src/sqlmap-master/plugins/generic/search.py b/src/sqlmap-master/plugins/generic/search.py index 384936a..0b89b1e 100644 --- a/src/sqlmap-master/plugins/generic/search.py +++ b/src/sqlmap-master/plugins/generic/search.py @@ -5,355 +5,374 @@ Copyright (c) 2006-2024 sqlmap developers (https://sqlmap.org/) See the file 'LICENSE' for copying permission """ -import re - -from lib.core.agent import agent -from lib.core.common import arrayizeValue -from lib.core.common import Backend -from lib.core.common import filterPairValues -from lib.core.common import getLimitRange -from lib.core.common import isInferenceAvailable -from lib.core.common import isNoneValue -from lib.core.common import isNumPosStrValue -from lib.core.common import isTechniqueAvailable -from lib.core.common import readInput -from lib.core.common import safeSQLIdentificatorNaming -from lib.core.common import safeStringFormat -from lib.core.common import unArrayizeValue -from lib.core.common import unsafeSQLIdentificatorNaming -from lib.core.data import conf -from lib.core.data import kb -from lib.core.data import logger -from lib.core.data import paths -from lib.core.data import queries -from lib.core.enums import CHARSET_TYPE -from lib.core.enums import DBMS -from lib.core.enums import EXPECTED -from lib.core.enums import PAYLOAD -from lib.core.exception import SqlmapMissingMandatoryOptionException -from lib.core.exception import SqlmapUserQuitException -from lib.core.settings import CURRENT_DB -from lib.core.settings import METADB_SUFFIX -from lib.core.settings import UPPER_CASE_DBMSES -from lib.request import inject -from lib.utils.brute import columnExists -from lib.utils.brute import tableExists -from thirdparty import six +import re # 导入re模块,用于正则表达式操作 + +from lib.core.agent import agent # 导入agent模块,用于处理注入请求 +from lib.core.common import arrayizeValue # 导入arrayizeValue函数,用于将值转换为数组 +from lib.core.common import Backend # 导入Backend类,用于获取后端数据库信息 +from lib.core.common import filterPairValues # 导入filterPairValues函数,用于过滤键值对 +from lib.core.common import getLimitRange # 导入getLimitRange函数,用于获取限制范围 +from lib.core.common import isInferenceAvailable # 导入isInferenceAvailable函数,用于判断是否可以使用盲注 +from lib.core.common import isNoneValue # 导入isNoneValue函数,用于判断值是否为None +from lib.core.common import isNumPosStrValue # 导入isNumPosStrValue函数,用于判断字符串是否为正整数 +from lib.core.common import isTechniqueAvailable # 导入isTechniqueAvailable函数,用于判断注入技术是否可用 +from lib.core.common import readInput # 导入readInput函数,用于安全地读取用户输入 +from lib.core.common import safeSQLIdentificatorNaming # 导入safeSQLIdentificatorNaming函数,用于安全命名SQL标识符 +from lib.core.common import safeStringFormat # 导入safeStringFormat函数,用于安全格式化字符串 +from lib.core.common import unArrayizeValue # 导入unArrayizeValue函数,用于将数组转换为值 +from lib.core.common import unsafeSQLIdentificatorNaming # 导入unsafeSQLIdentificatorNaming函数,用于不安全命名SQL标识符 +from lib.core.data import conf # 导入conf对象,存储全局配置信息 +from lib.core.data import kb # 导入kb对象,存储全局知识库信息 +from lib.core.data import logger # 导入logger对象,用于记录日志 +from lib.core.data import paths # 导入paths对象,存储路径信息 +from lib.core.data import queries # 导入queries对象,存储查询语句信息 +from lib.core.enums import CHARSET_TYPE # 导入CHARSET_TYPE枚举类,定义字符集类型 +from lib.core.enums import DBMS # 导入DBMS枚举类,定义数据库类型 +from lib.core.enums import EXPECTED # 导入EXPECTED枚举类,定义预期返回类型 +from lib.core.enums import PAYLOAD # 导入PAYLOAD枚举类,定义Payload类型 +from lib.core.exception import SqlmapMissingMandatoryOptionException # 导入SqlmapMissingMandatoryOptionException异常类,表示缺少必要选项 +from lib.core.exception import SqlmapUserQuitException # 导入SqlmapUserQuitException异常类,表示用户退出 +from lib.core.settings import CURRENT_DB # 导入CURRENT_DB常量,表示当前数据库 +from lib.core.settings import METADB_SUFFIX # 导入METADB_SUFFIX常量,表示元数据后缀 +from lib.core.settings import UPPER_CASE_DBMSES # 导入UPPER_CASE_DBMSES常量,表示需要转换为大写的数据库类型 +from lib.request import inject # 导入inject模块,用于执行注入 +from lib.utils.brute import columnExists # 导入columnExists函数,用于爆破列是否存在 +from lib.utils.brute import tableExists # 导入tableExists函数,用于爆破表是否存在 +from thirdparty import six # 导入six模块,用于Python2和Python3的兼容 class Search(object): """ This class defines search functionalities for plugins. + 这个类定义了插件的搜索功能。 """ def __init__(self): - pass + pass # 初始化方法,此处为空 def searchDb(self): - foundDbs = [] - rootQuery = queries[Backend.getIdentifiedDbms()].search_db - dbList = conf.db.split(',') + """ + Searches for database names based on user input. + 根据用户输入搜索数据库名称。 + """ + foundDbs = [] # 初始化找到的数据库列表 + rootQuery = queries[Backend.getIdentifiedDbms()].search_db # 获取当前数据库的搜索数据库查询 + dbList = conf.db.split(',') # 获取用户输入的数据库列表,用逗号分割 if Backend.isDbms(DBMS.MYSQL) and not kb.data.has_information_schema: - dbCond = rootQuery.inband.condition2 + dbCond = rootQuery.inband.condition2 # 如果是MySQL且没有information_schema,则使用condition2 else: - dbCond = rootQuery.inband.condition + dbCond = rootQuery.inband.condition # 否则使用condition - dbConsider, dbCondParam = self.likeOrExact("database") + dbConsider, dbCondParam = self.likeOrExact("database") # 获取数据库搜索条件 - for db in dbList: - values = [] - db = safeSQLIdentificatorNaming(db) + for db in dbList: # 遍历数据库列表 + values = [] # 初始化查询结果列表 + db = safeSQLIdentificatorNaming(db) # 对数据库名称进行安全命名 if Backend.getIdentifiedDbms() in UPPER_CASE_DBMSES: - db = db.upper() + db = db.upper() # 如果是需要大写的数据库,则转换为大写 - infoMsg = "searching database" + infoMsg = "searching database" # 初始化日志信息 if dbConsider == "1": - infoMsg += "s LIKE" - infoMsg += " '%s'" % unsafeSQLIdentificatorNaming(db) - logger.info(infoMsg) - - if conf.excludeSysDbs: - exclDbsQuery = "".join(" AND '%s' != %s" % (unsafeSQLIdentificatorNaming(db), dbCond) for db in self.excludeDbsList) - infoMsg = "skipping system database%s '%s'" % ("s" if len(self.excludeDbsList) > 1 else "", ", ".join(db for db in self.excludeDbsList)) - logger.info(infoMsg) + infoMsg += "s LIKE" # 如果是LIKE匹配,则添加LIKE + infoMsg += " '%s'" % unsafeSQLIdentificatorNaming(db) # 添加不安全的数据库名称 + logger.info(infoMsg) # 打印日志信息 + + if conf.excludeSysDbs: # 如果排除系统数据库 + exclDbsQuery = "".join(" AND '%s' != %s" % (unsafeSQLIdentificatorNaming(db), dbCond) for db in self.excludeDbsList) # 构建排除系统数据库的SQL语句 + infoMsg = "skipping system database%s '%s'" % ("s" if len(self.excludeDbsList) > 1 else "", ", ".join(db for db in self.excludeDbsList)) # 构建跳过系统数据库的日志信息 + logger.info(infoMsg) # 打印跳过系统数据库的日志信息 else: - exclDbsQuery = "" + exclDbsQuery = "" # 如果不排除系统数据库,则SQL语句为空 - dbQuery = "%s%s" % (dbCond, dbCondParam) - dbQuery = dbQuery % unsafeSQLIdentificatorNaming(db) + dbQuery = "%s%s" % (dbCond, dbCondParam) # 构建数据库查询条件 + dbQuery = dbQuery % unsafeSQLIdentificatorNaming(db) # 将数据库名称添加到查询条件中 + # 如果支持UNION,ERROR或者QUERY注入,则使用带内注入 if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: if Backend.isDbms(DBMS.MYSQL) and not kb.data.has_information_schema: - query = rootQuery.inband.query2 + query = rootQuery.inband.query2 # 如果是MySQL且没有information_schema,则使用query2 else: - query = rootQuery.inband.query + query = rootQuery.inband.query # 否则使用query - query = query % (dbQuery + exclDbsQuery) - values = inject.getValue(query, blind=False, time=False) + query = query % (dbQuery + exclDbsQuery) # 将查询条件添加到SQL语句中 + values = inject.getValue(query, blind=False, time=False) # 执行SQL查询 - if not isNoneValue(values): - values = arrayizeValue(values) + if not isNoneValue(values): # 如果查询结果不为空 + values = arrayizeValue(values) # 将查询结果转换为数组 - for value in values: - value = safeSQLIdentificatorNaming(value) - foundDbs.append(value) + for value in values: # 遍历查询结果 + value = safeSQLIdentificatorNaming(value) # 对查询结果进行安全命名 + foundDbs.append(value) # 将结果添加到找到的数据库列表中 + # 如果带内注入失败,则尝试使用盲注 if not values and isInferenceAvailable() and not conf.direct: infoMsg = "fetching number of database" if dbConsider == "1": - infoMsg += "s LIKE" + infoMsg += "s LIKE" # 如果是LIKE匹配,则添加LIKE infoMsg += " '%s'" % unsafeSQLIdentificatorNaming(db) - logger.info(infoMsg) + logger.info(infoMsg) # 打印日志信息 if Backend.isDbms(DBMS.MYSQL) and not kb.data.has_information_schema: - query = rootQuery.blind.count2 + query = rootQuery.blind.count2 # 如果是MySQL且没有information_schema,则使用count2 else: - query = rootQuery.blind.count + query = rootQuery.blind.count # 否则使用count - query = query % (dbQuery + exclDbsQuery) - count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) + query = query % (dbQuery + exclDbsQuery) # 将查询条件添加到SQL语句中 + count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) # 执行盲注,获取数据库数量 - if not isNumPosStrValue(count): + if not isNumPosStrValue(count): # 如果数据库数量不是正整数 warnMsg = "no database" if dbConsider == "1": - warnMsg += "s LIKE" + warnMsg += "s LIKE" # 如果是LIKE匹配,则添加LIKE warnMsg += " '%s' found" % unsafeSQLIdentificatorNaming(db) - logger.warning(warnMsg) + logger.warning(warnMsg) # 打印日志信息 - continue + continue # 跳过当前数据库 - indexRange = getLimitRange(count) + indexRange = getLimitRange(count) # 获取索引范围 - for index in indexRange: + for index in indexRange: # 遍历索引范围 if Backend.isDbms(DBMS.MYSQL) and not kb.data.has_information_schema: - query = rootQuery.blind.query2 + query = rootQuery.blind.query2 # 如果是MySQL且没有information_schema,则使用query2 else: - query = rootQuery.blind.query - - query = query % (dbQuery + exclDbsQuery) - query = agent.limitQuery(index, query, dbCond) + query = rootQuery.blind.query # 否则使用query - value = unArrayizeValue(inject.getValue(query, union=False, error=False)) - value = safeSQLIdentificatorNaming(value) - foundDbs.append(value) + query = query % (dbQuery + exclDbsQuery) # 将查询条件添加到SQL语句中 + query = agent.limitQuery(index, query, dbCond) # 添加限制条件 + + value = unArrayizeValue(inject.getValue(query, union=False, error=False)) # 执行盲注,获取数据库名称 + value = safeSQLIdentificatorNaming(value) # 对查询结果进行安全命名 + foundDbs.append(value) # 将结果添加到找到的数据库列表中 - conf.dumper.lister("found databases", foundDbs) + conf.dumper.lister("found databases", foundDbs) # 打印找到的数据库列表 def searchTable(self): - bruteForce = False + """ + Searches for table names based on user input. + 根据用户输入搜索表名称。 + """ + bruteForce = False # 初始化是否进行爆破 if Backend.isDbms(DBMS.MYSQL) and not kb.data.has_information_schema: errMsg = "information_schema not available, " errMsg += "back-end DBMS is MySQL < 5.0" - bruteForce = True + bruteForce = True # 如果是MySQL且没有information_schema,则设置为进行爆破 - if bruteForce: - message = "do you want to use common table existence check? %s" % ("[Y/n/q]" if Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.MCKOI, DBMS.EXTREMEDB) else "[y/N/q]") - choice = readInput(message, default='Y' if 'Y' in message else 'N').upper() + if bruteForce: # 如果需要爆破 + message = "do you want to use common table existence check? %s" % ("[Y/n/q]" if Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.MCKOI, DBMS.EXTREMEDB) else "[y/N/q]") # 提示用户是否使用常用表名检查 + choice = readInput(message, default='Y' if 'Y' in message else 'N').upper() # 读取用户输入 - if choice == 'N': + if choice == 'N': # 如果用户选择不使用常用表名检查 return - elif choice == 'Q': + elif choice == 'Q': # 如果用户选择退出 raise SqlmapUserQuitException else: - regex = '|'.join(conf.tbl.split(',')) - return tableExists(paths.COMMON_TABLES, regex) + regex = '|'.join(conf.tbl.split(',')) # 构建用于匹配的正则表达式 + return tableExists(paths.COMMON_TABLES, regex) # 使用爆破方式检测表是否存在 - foundTbls = {} - tblList = conf.tbl.split(',') - rootQuery = queries[Backend.getIdentifiedDbms()].search_table - tblCond = rootQuery.inband.condition - dbCond = rootQuery.inband.condition2 - tblConsider, tblCondParam = self.likeOrExact("table") + foundTbls = {} # 初始化找到的表列表 + tblList = conf.tbl.split(',') # 获取用户输入的表列表,用逗号分割 + rootQuery = queries[Backend.getIdentifiedDbms()].search_table # 获取当前数据库的搜索表查询 + tblCond = rootQuery.inband.condition # 获取表查询条件 + dbCond = rootQuery.inband.condition2 # 获取数据库查询条件 + tblConsider, tblCondParam = self.likeOrExact("table") # 获取表搜索条件 - for tbl in tblList: - values = [] - tbl = safeSQLIdentificatorNaming(tbl, True) + for tbl in tblList: # 遍历表列表 + values = [] # 初始化查询结果列表 + tbl = safeSQLIdentificatorNaming(tbl, True) # 对表名进行安全命名 if Backend.getIdentifiedDbms() in UPPER_CASE_DBMSES: - tbl = tbl.upper() - conf.db = conf.db.upper() if conf.db else conf.db + tbl = tbl.upper() # 如果是需要大写的数据库,则转换为大写 + conf.db = conf.db.upper() if conf.db else conf.db # 如果用户指定了数据库,则转换为大写 infoMsg = "searching table" if tblConsider == '1': - infoMsg += "s LIKE" - infoMsg += " '%s'" % unsafeSQLIdentificatorNaming(tbl) + infoMsg += "s LIKE" # 如果是LIKE匹配,则添加LIKE + infoMsg += " '%s'" % unsafeSQLIdentificatorNaming(tbl) # 添加不安全的表名 if conf.db == CURRENT_DB: - conf.db = self.getCurrentDb() + conf.db = self.getCurrentDb() # 如果用户指定当前数据库,则获取当前数据库名 if dbCond and conf.db: - _ = conf.db.split(',') - whereDbsQuery = " AND (" + " OR ".join("%s = '%s'" % (dbCond, unsafeSQLIdentificatorNaming(db)) for db in _) + ")" - infoMsg += " for database%s '%s'" % ("s" if len(_) > 1 else "", ", ".join(db for db in _)) - elif conf.excludeSysDbs: - whereDbsQuery = "".join(" AND '%s' != %s" % (unsafeSQLIdentificatorNaming(db), dbCond) for db in self.excludeDbsList) - msg = "skipping system database%s '%s'" % ("s" if len(self.excludeDbsList) > 1 else "", ", ".join(db for db in self.excludeDbsList)) - logger.info(msg) + _ = conf.db.split(',') # 获取用户指定的数据库列表,用逗号分割 + whereDbsQuery = " AND (" + " OR ".join("%s = '%s'" % (dbCond, unsafeSQLIdentificatorNaming(db)) for db in _) + ")" # 构建数据库查询条件 + infoMsg += " for database%s '%s'" % ("s" if len(_) > 1 else "", ", ".join(db for db in _)) # 添加数据库信息到日志信息中 + elif conf.excludeSysDbs: # 如果排除系统数据库 + whereDbsQuery = "".join(" AND '%s' != %s" % (unsafeSQLIdentificatorNaming(db), dbCond) for db in self.excludeDbsList) # 构建排除系统数据库的SQL语句 + msg = "skipping system database%s '%s'" % ("s" if len(self.excludeDbsList) > 1 else "", ", ".join(db for db in self.excludeDbsList)) # 构建跳过系统数据库的日志信息 + logger.info(msg) # 打印日志信息 else: - whereDbsQuery = "" - + whereDbsQuery = "" # 如果不排除系统数据库,则SQL语句为空 + if dbCond and conf.exclude: - whereDbsQuery += " AND %s NOT LIKE '%s'" % (dbCond, re.sub(r"\.[*+]", '%', conf.exclude._original)) + whereDbsQuery += " AND %s NOT LIKE '%s'" % (dbCond, re.sub(r"\.[*+]", '%', conf.exclude._original)) # 添加排除条件 - logger.info(infoMsg) + logger.info(infoMsg) # 打印日志信息 - tblQuery = "%s%s" % (tblCond, tblCondParam) - tblQuery = tblQuery % unsafeSQLIdentificatorNaming(tbl) + tblQuery = "%s%s" % (tblCond, tblCondParam) # 构建表查询条件 + tblQuery = tblQuery % unsafeSQLIdentificatorNaming(tbl) # 将表名添加到表查询条件中 + # 如果支持UNION,ERROR或者QUERY注入,则使用带内注入 if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: - query = rootQuery.inband.query - - query = query % (tblQuery + whereDbsQuery) - values = inject.getValue(query, blind=False, time=False) + query = rootQuery.inband.query # 获取带内查询语句 + query = query % (tblQuery + whereDbsQuery) # 将查询条件添加到SQL语句中 + values = inject.getValue(query, blind=False, time=False) # 执行SQL查询 + # 如果是SQLite或Firebird数据库,则需要特殊处理 if values and Backend.getIdentifiedDbms() in (DBMS.SQLITE, DBMS.FIREBIRD): - newValues = [] - - if isinstance(values, six.string_types): - values = [values] - for value in values: - dbName = "SQLite" if Backend.isDbms(DBMS.SQLITE) else "Firebird" - newValues.append(["%s%s" % (dbName, METADB_SUFFIX), value]) - - values = newValues - - for foundDb, foundTbl in filterPairValues(values): - foundDb = safeSQLIdentificatorNaming(foundDb) - foundTbl = safeSQLIdentificatorNaming(foundTbl, True) - + newValues = [] # 初始化新的查询结果列表 + + if isinstance(values, six.string_types): # 如果查询结果是字符串 + values = [values] # 转换为列表 + for value in values: # 遍历查询结果 + dbName = "SQLite" if Backend.isDbms(DBMS.SQLITE) else "Firebird" # 获取数据库名称 + newValues.append(["%s%s" % (dbName, METADB_SUFFIX), value]) # 添加数据库名称和表名到查询结果列表 + + values = newValues # 更新查询结果 + + for foundDb, foundTbl in filterPairValues(values): # 遍历查询结果 + foundDb = safeSQLIdentificatorNaming(foundDb) # 对数据库名称进行安全命名 + foundTbl = safeSQLIdentificatorNaming(foundTbl, True) # 对表名进行安全命名 + if foundDb is None or foundTbl is None: continue - if foundDb in foundTbls: - foundTbls[foundDb].append(foundTbl) + if foundDb in foundTbls: # 如果数据库已经存在于结果列表中 + foundTbls[foundDb].append(foundTbl) # 则添加表名到该数据库的表列表中 else: - foundTbls[foundDb] = [foundTbl] + foundTbls[foundDb] = [foundTbl] # 否则新建数据库,并添加表名 + # 如果带内注入失败,则尝试使用盲注 if not values and isInferenceAvailable() and not conf.direct: + # 如果不是SQLite或Firebird数据库 if Backend.getIdentifiedDbms() not in (DBMS.SQLITE, DBMS.FIREBIRD): if len(whereDbsQuery) == 0: infoMsg = "fetching number of databases with table" if tblConsider == "1": - infoMsg += "s LIKE" + infoMsg += "s LIKE" # 如果是LIKE匹配,则添加LIKE infoMsg += " '%s'" % unsafeSQLIdentificatorNaming(tbl) - logger.info(infoMsg) + logger.info(infoMsg) # 打印日志信息 - query = rootQuery.blind.count - query = query % (tblQuery + whereDbsQuery) - count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) + query = rootQuery.blind.count # 获取盲注计数查询 + query = query % (tblQuery + whereDbsQuery) # 将查询条件添加到SQL语句中 + count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) # 执行盲注获取表数量 - if not isNumPosStrValue(count): + if not isNumPosStrValue(count): # 如果表数量不是正整数 warnMsg = "no databases have table" if tblConsider == "1": - warnMsg += "s LIKE" + warnMsg += "s LIKE" # 如果是LIKE匹配,则添加LIKE warnMsg += " '%s'" % unsafeSQLIdentificatorNaming(tbl) - logger.warning(warnMsg) + logger.warning(warnMsg) # 打印日志信息 - continue + continue # 跳过当前表 - indexRange = getLimitRange(count) + indexRange = getLimitRange(count) # 获取索引范围 for index in indexRange: - query = rootQuery.blind.query - query = query % (tblQuery + whereDbsQuery) - query = agent.limitQuery(index, query) - - foundDb = unArrayizeValue(inject.getValue(query, union=False, error=False)) - foundDb = safeSQLIdentificatorNaming(foundDb) + query = rootQuery.blind.query # 获取盲注查询语句 + query = query % (tblQuery + whereDbsQuery) # 将查询条件添加到SQL语句中 + query = agent.limitQuery(index, query) # 添加限制条件 + foundDb = unArrayizeValue(inject.getValue(query, union=False, error=False)) # 执行盲注,获取数据库名称 + foundDb = safeSQLIdentificatorNaming(foundDb) # 对数据库名称进行安全命名 + if foundDb not in foundTbls: - foundTbls[foundDb] = [] + foundTbls[foundDb] = [] # 如果数据库不存在于结果列表中,则新建 if tblConsider == "2": - foundTbls[foundDb].append(tbl) + foundTbls[foundDb].append(tbl) # 如果是精确匹配,则直接添加表名 if tblConsider == "2": - continue - else: - for db in conf.db.split(',') if conf.db else (self.getCurrentDb(),): - db = safeSQLIdentificatorNaming(db) + continue # 跳过当前表 + + else: # 如果指定了数据库 + for db in conf.db.split(',') if conf.db else (self.getCurrentDb(),): # 遍历数据库列表 + db = safeSQLIdentificatorNaming(db) # 对数据库名称进行安全命名 if db not in foundTbls: - foundTbls[db] = [] - else: - dbName = "SQLite" if Backend.isDbms(DBMS.SQLITE) else "Firebird" - foundTbls["%s%s" % (dbName, METADB_SUFFIX)] = [] + foundTbls[db] = [] # 如果数据库不存在于结果列表中,则新建 + else: # 如果是SQLite或Firebird数据库 + dbName = "SQLite" if Backend.isDbms(DBMS.SQLITE) else "Firebird" # 获取数据库名称 + foundTbls["%s%s" % (dbName, METADB_SUFFIX)] = [] # 添加数据库名称到结果列表中 - for db in foundTbls: - db = safeSQLIdentificatorNaming(db) + for db in foundTbls: # 遍历数据库列表 + db = safeSQLIdentificatorNaming(db) # 对数据库名称进行安全命名 infoMsg = "fetching number of table" if tblConsider == "1": - infoMsg += "s LIKE" - infoMsg += " '%s' in database '%s'" % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(db)) - logger.info(infoMsg) + infoMsg += "s LIKE" # 如果是LIKE匹配,则添加LIKE + infoMsg += " '%s' in database '%s'" % (unsafeSQLIdentificatorNaming(tbl), unsafeSQLIdentificatorNaming(db)) # 添加表名和数据库名到日志信息 + logger.info(infoMsg) # 打印日志信息 - query = rootQuery.blind.count2 + query = rootQuery.blind.count2 # 获取盲注计数查询 if Backend.getIdentifiedDbms() not in (DBMS.SQLITE, DBMS.FIREBIRD): - query = query % unsafeSQLIdentificatorNaming(db) - query += " AND %s" % tblQuery - - count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) - - if not isNumPosStrValue(count): + query = query % unsafeSQLIdentificatorNaming(db) # 将数据库名称添加到SQL语句中 + query += " AND %s" % tblQuery # 将表查询条件添加到SQL语句中 + + count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) # 执行盲注获取表数量 + + if not isNumPosStrValue(count): # 如果表数量不是正整数 warnMsg = "no table" if tblConsider == "1": - warnMsg += "s LIKE" + warnMsg += "s LIKE" # 如果是LIKE匹配,则添加LIKE warnMsg += " '%s' " % unsafeSQLIdentificatorNaming(tbl) warnMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(db) - logger.warning(warnMsg) + logger.warning(warnMsg) # 打印日志信息 - continue - - indexRange = getLimitRange(count) - - for index in indexRange: - query = rootQuery.blind.query2 + continue # 跳过当前数据库 + indexRange = getLimitRange(count) # 获取索引范围 + + for index in indexRange: # 遍历索引范围 + query = rootQuery.blind.query2 # 获取盲注查询语句 + if " ORDER BY " in query: - query = query.replace(" ORDER BY ", "%s ORDER BY " % (" AND %s" % tblQuery)) + query = query.replace(" ORDER BY ", "%s ORDER BY " % (" AND %s" % tblQuery)) # 如果查询语句包含 ORDER BY,则添加 AND 条件 elif query.endswith("'%s')"): - query = query[:-1] + " AND %s)" % tblQuery + query = query[:-1] + " AND %s)" % tblQuery # 如果查询语句以 ')' 结尾,则添加 AND 条件 else: - query += " AND %s" % tblQuery + query += " AND %s" % tblQuery # 否则直接添加 AND 条件 if Backend.isDbms(DBMS.FIREBIRD): - query = safeStringFormat(query, index) + query = safeStringFormat(query, index) # 如果是Firebird数据库,则格式化查询语句 if Backend.getIdentifiedDbms() not in (DBMS.SQLITE, DBMS.FIREBIRD): - query = safeStringFormat(query, unsafeSQLIdentificatorNaming(db)) - + query = safeStringFormat(query, unsafeSQLIdentificatorNaming(db)) # 如果不是SQLite或Firebird数据库,则格式化查询语句 + if not Backend.isDbms(DBMS.FIREBIRD): - query = agent.limitQuery(index, query) + query = agent.limitQuery(index, query) # 如果不是Firebird数据库,则添加限制条件 - foundTbl = unArrayizeValue(inject.getValue(query, union=False, error=False)) + foundTbl = unArrayizeValue(inject.getValue(query, union=False, error=False)) # 执行盲注,获取表名 if not isNoneValue(foundTbl): kb.hintValue = foundTbl - foundTbl = safeSQLIdentificatorNaming(foundTbl, True) - foundTbls[db].append(foundTbl) + foundTbl = safeSQLIdentificatorNaming(foundTbl, True) # 对表名进行安全命名 + foundTbls[db].append(foundTbl) # 将表名添加到结果列表中 - for db in list(foundTbls.keys()): - if isNoneValue(foundTbls[db]): - del foundTbls[db] + for db in list(foundTbls.keys()): # 遍历数据库列表 + if isNoneValue(foundTbls[db]): # 如果某个数据库的表列表为空 + del foundTbls[db] # 则删除该数据库 - if not foundTbls: + if not foundTbls: # 如果没有找到表 warnMsg = "no databases contain any of the provided tables" - logger.warning(warnMsg) - return + logger.warning(warnMsg) # 打印日志信息 + return # 返回 - conf.dumper.dbTables(foundTbls) - self.dumpFoundTables(foundTbls) + conf.dumper.dbTables(foundTbls) # 打印找到的表列表 + self.dumpFoundTables(foundTbls) # 导出找到的表 def searchColumn(self): - bruteForce = False + """ + Searches for column names based on user input. + 根据用户输入搜索列名称。 + """ + bruteForce = False # 初始化是否进行爆破 - self.forceDbmsEnum() + self.forceDbmsEnum() # 强制枚举数据库 if Backend.isDbms(DBMS.MYSQL) and not kb.data.has_information_schema: errMsg = "information_schema not available, " errMsg += "back-end DBMS is MySQL < 5.0" - bruteForce = True + bruteForce = True # 如果是MySQL且没有information_schema,则设置为进行爆破 if bruteForce: message = "do you want to use common column existence check? %s" % ("[Y/n/q]" if Backend.getIdentifiedDbms() in (DBMS.ACCESS, DBMS.MCKOI, DBMS.EXTREMEDB) else "[y/N/q]") @@ -374,267 +393,350 @@ class Search(object): return - rootQuery = queries[Backend.getIdentifiedDbms()].search_column - foundCols = {} - dbs = {} - whereDbsQuery = "" - whereTblsQuery = "" - infoMsgTbl = "" - infoMsgDb = "" - colList = conf.col.split(',') + rootQuery = queries[Backend.getIdentifiedDbms()].search_column # 获取当前数据库的搜索列查询 + foundCols = {} # 初始化找到的列列表 + dbs = {} # 初始化数据库列表 + whereDbsQuery = "" # 初始化数据库查询条件 + whereTblsQuery = "" # 初始化表查询条件 + infoMsgTbl = "" # 初始化表日志信息 + infoMsgDb = "" # 初始化数据库日志信息 + colList = conf.col.split(',') # 获取用户输入的列列表,用逗号分割 if conf.exclude: - colList = [_ for _ in colList if re.search(conf.exclude, _, re.I) is None] + colList = [_ for _ in colList if re.search(conf.exclude, _, re.I) is None] # 如果存在排除条件,则过滤列列表 origTbl = conf.tbl origDb = conf.db - colCond = rootQuery.inband.condition - dbCond = rootQuery.inband.condition2 - tblCond = rootQuery.inband.condition3 - colConsider, colCondParam = self.likeOrExact("column") + colCond = rootQuery.inband.condition # 获取列查询条件 + dbCond = rootQuery.inband.condition2 # 获取数据库查询条件 + tblCond = rootQuery.inband.condition3 # 获取表查询条件 + colConsider, colCondParam = self.likeOrExact("column") # 获取列搜索条件 - for column in colList: - values = [] - column = safeSQLIdentificatorNaming(column) - conf.db = origDb - conf.tbl = origTbl + for column in colList: # 遍历列列表 + values = [] # 初始化查询结果列表 + column = safeSQLIdentificatorNaming(column) # 对列名进行安全命名 + conf.db = origDb # 重置数据库名称 + conf.tbl = origTbl # 重置表名 if Backend.getIdentifiedDbms() in UPPER_CASE_DBMSES: - column = column.upper() - conf.db = conf.db.upper() if conf.db else conf.db - conf.tbl = conf.tbl.upper() if conf.tbl else conf.tbl + column = column.upper() # 如果是需要大写的数据库,则转换为大写 + conf.db = conf.db.upper() if conf.db else conf.db # 如果用户指定了数据库,则转换为大写 + conf.tbl = conf.tbl.upper() if conf.tbl else conf.tbl # 如果用户指定了表,则转换为大写 infoMsg = "searching column" if colConsider == "1": - infoMsg += "s LIKE" - infoMsg += " '%s'" % unsafeSQLIdentificatorNaming(column) + infoMsg += "s LIKE" # 如果是LIKE匹配,则添加LIKE + infoMsg += " '%s'" % unsafeSQLIdentificatorNaming(column) # 添加不安全的列名 - foundCols[column] = {} + foundCols[column] = {} # 初始化列结果列表 - if tblCond: - if conf.tbl: - tbls = conf.tbl.split(',') + if tblCond: # 如果指定了表条件 + if conf.tbl: # 如果指定了表 + tbls = conf.tbl.split(',') # 获取表列表,用逗号分割 if conf.exclude: - tbls = [_ for _ in tbls if re.search(conf.exclude, _, re.I) is None] - whereTblsQuery = " AND (" + " OR ".join("%s = '%s'" % (tblCond, unsafeSQLIdentificatorNaming(tbl)) for tbl in tbls) + ")" - infoMsgTbl = " for table%s '%s'" % ("s" if len(tbls) > 1 else "", ", ".join(unsafeSQLIdentificatorNaming(tbl) for tbl in tbls)) + tbls = [_ for _ in tbls if re.search(conf.exclude, _, re.I) is None] # 如果存在排除条件,则过滤表列表 + whereTblsQuery = " AND (" + " OR ".join("%s = '%s'" % (tblCond, unsafeSQLIdentificatorNaming(tbl)) for tbl in tbls) + ")" # 构建表查询条件 + infoMsgTbl = " for table%s '%s'" % ("s" if len(tbls) > 1 else "", ", ".join(unsafeSQLIdentificatorNaming(tbl) for tbl in tbls)) # 添加表信息到日志信息 if conf.db == CURRENT_DB: - conf.db = self.getCurrentDb() - - if dbCond: - if conf.db: - _ = conf.db.split(',') - whereDbsQuery = " AND (" + " OR ".join("%s = '%s'" % (dbCond, unsafeSQLIdentificatorNaming(db)) for db in _) + ")" - infoMsgDb = " in database%s '%s'" % ("s" if len(_) > 1 else "", ", ".join(unsafeSQLIdentificatorNaming(db) for db in _)) - elif conf.excludeSysDbs: - whereDbsQuery = "".join(" AND %s != '%s'" % (dbCond, unsafeSQLIdentificatorNaming(db)) for db in self.excludeDbsList) - msg = "skipping system database%s '%s'" % ("s" if len(self.excludeDbsList) > 1 else "", ", ".join(unsafeSQLIdentificatorNaming(db) for db in self.excludeDbsList)) - logger.info(msg) + conf.db = self.getCurrentDb() # 如果用户指定当前数据库,则获取当前数据库名 + + if dbCond: # 如果指定了数据库条件 + if conf.db: # 如果指定了数据库 + _ = conf.db.split(',') # 获取数据库列表,用逗号分割 + whereDbsQuery = " AND (" + " OR ".join("%s = '%s'" % (dbCond, unsafeSQLIdentificatorNaming(db)) for db in _) + ")" # 构建数据库查询条件 + infoMsgDb = " in database%s '%s'" % ("s" if len(_) > 1 else "", ", ".join(unsafeSQLIdentificatorNaming(db) for db in _)) # 添加数据库信息到日志信息 + elif conf.excludeSysDbs: # 如果排除系统数据库 + whereDbsQuery = "".join(" AND %s != '%s'" % (dbCond, unsafeSQLIdentificatorNaming(db)) for db in self.excludeDbsList) # 构建排除系统数据库的SQL语句 + msg = "skipping system database%s '%s'" % ("s" if len(self.excludeDbsList) > 1 else "", ", ".join(unsafeSQLIdentificatorNaming(db) for db in self.excludeDbsList)) # 构建跳过系统数据库的日志信息 + logger.info(msg) # 打印日志信息 else: - infoMsgDb = " across all databases" + infoMsgDb = " across all databases" # 如果不指定数据库,则表示在所有数据库中查找 if conf.exclude: - whereDbsQuery += " AND %s NOT LIKE '%s'" % (dbCond, re.sub(r"\.[*+]", '%', conf.exclude._original)) + whereDbsQuery += " AND %s NOT LIKE '%s'" % (dbCond, re.sub(r"\.[*+]", '%', conf.exclude._original)) # 添加排除条件 - logger.info("%s%s%s" % (infoMsg, infoMsgTbl, infoMsgDb)) + logger.info("%s%s%s" % (infoMsg, infoMsgTbl, infoMsgDb)) # 打印日志信息 - colQuery = "%s%s" % (colCond, colCondParam) - colQuery = colQuery % unsafeSQLIdentificatorNaming(column) + colQuery = "%s%s" % (colCond, colCondParam) # 构建列查询条件 + colQuery = colQuery % unsafeSQLIdentificatorNaming(column) # 将列名添加到查询条件中 + # 如果支持UNION,ERROR或者QUERY注入,则使用带内注入 if any(isTechniqueAvailable(_) for _ in (PAYLOAD.TECHNIQUE.UNION, PAYLOAD.TECHNIQUE.ERROR, PAYLOAD.TECHNIQUE.QUERY)) or conf.direct: if not all((conf.db, conf.tbl)): # Enumerate tables containing the column provided if # either of database(s) or table(s) is not provided - query = rootQuery.inband.query - query = query % (colQuery + whereDbsQuery + whereTblsQuery) - values = inject.getValue(query, blind=False, time=False) + query = rootQuery.inband.query # 获取带内查询语句 + query = query % (colQuery + whereDbsQuery + whereTblsQuery) # 将查询条件添加到SQL语句中 + values = inject.getValue(query, blind=False, time=False) # 执行SQL查询 else: # Assume provided databases' tables contain the # column(s) provided - values = [] + values = [] # 如果指定了数据库和表,则直接使用它们 - for db in conf.db.split(','): - for tbl in conf.tbl.split(','): - values.append([safeSQLIdentificatorNaming(db), safeSQLIdentificatorNaming(tbl, True)]) + for db in conf.db.split(','): # 遍历数据库列表 + for tbl in conf.tbl.split(','): # 遍历表列表 + values.append([safeSQLIdentificatorNaming(db), safeSQLIdentificatorNaming(tbl, True)]) # 将数据库和表添加到查询结果中 - for db, tbl in filterPairValues(values): - db = safeSQLIdentificatorNaming(db) - tbls = tbl.split(',') if not isNoneValue(tbl) else [] + for db, tbl in filterPairValues(values): # 遍历查询结果 + db = safeSQLIdentificatorNaming(db) # 对数据库名称进行安全命名 + tbls = tbl.split(',') if not isNoneValue(tbl) else [] # 如果表名不为空,则按逗号分割 - for tbl in tbls: - tbl = safeSQLIdentificatorNaming(tbl, True) + for tbl in tbls: # 遍历表列表 + tbl = safeSQLIdentificatorNaming(tbl, True) # 对表名进行安全命名 if db is None or tbl is None: continue + + conf.db = db # 设置数据库名称 + conf.tbl = tbl # 设置表名 + conf.col = column # 设置列名 - conf.db = db - conf.tbl = tbl - 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]: # 如果列信息已经缓存 if db not in dbs: - dbs[db] = {} + dbs[db] = {} # 如果数据库不在dbs中,则添加 if tbl not in dbs[db]: - dbs[db][tbl] = {} + dbs[db][tbl] = {} # 如果表不在dbs中,则添加 - dbs[db][tbl].update(kb.data.cachedColumns[db][tbl]) + dbs[db][tbl].update(kb.data.cachedColumns[db][tbl]) # 更新缓存的列信息 if db in foundCols[column]: - foundCols[column][db].append(tbl) + foundCols[column][db].append(tbl) # 如果数据库已经在foundCols中,则添加表 else: - foundCols[column][db] = [tbl] - - kb.data.cachedColumns = {} + foundCols[column][db] = [tbl] # 否则新建数据库,并添加表 + kb.data.cachedColumns = {} # 清空缓存的列信息 + + # 如果带内注入失败,则尝试使用盲注 if not values and isInferenceAvailable() and not conf.direct: + # 如果之前的带内注入尝试失败,并且当前可以使用盲注技术,并且没有使用直接连接模式,则执行此代码块。 if not conf.db: + # 如果用户没有指定要搜索的数据库(没有使用 -D 参数) infoMsg = "fetching number of databases with tables containing column" + # 准备日志消息,表示正在获取包含指定列的表所在的数据库数量 if colConsider == "1": + # 如果列名使用 LIKE 条件匹配 infoMsg += "s LIKE" + # 将 "s LIKE" 添加到日志消息中 infoMsg += " '%s'" % unsafeSQLIdentificatorNaming(column) + # 将不安全的列名添加到日志消息中 logger.info("%s%s%s" % (infoMsg, infoMsgTbl, infoMsgDb)) + # 打印带有表和数据库信息的日志消息 query = rootQuery.blind.count + # 获取当前数据库的盲注计数查询语句(用于获取匹配的数据库数量) query = query % (colQuery + whereDbsQuery + whereTblsQuery) + # 将列的查询条件、数据库的过滤条件和表的过滤条件添加到查询语句中 count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) + # 执行盲注查询,获取匹配的数据库数量,并将结果视为整数类型 if not isNumPosStrValue(count): + # 如果返回的数据库数量不是有效的正整数 warnMsg = "no databases have tables containing column" + # 准备警告消息,表示没有找到包含指定列的表 if colConsider == "1": + # 如果列名使用 LIKE 条件匹配 warnMsg += "s LIKE" + # 将 "s LIKE" 添加到警告消息中 warnMsg += " '%s'" % unsafeSQLIdentificatorNaming(column) + # 将不安全的列名添加到警告消息中 logger.warning("%s%s" % (warnMsg, infoMsgTbl)) + # 打印带有表信息的警告消息 continue + # 跳过当前列,继续处理下一个列 indexRange = getLimitRange(count) + # 获取从 1 到数据库数量的索引范围,用于循环遍历数据库 for index in indexRange: + # 遍历每个可能的数据库索引 query = rootQuery.blind.query + # 获取用于盲注提取数据库名称的查询语句 query = query % (colQuery + whereDbsQuery + whereTblsQuery) + # 将列的查询条件、数据库的过滤条件和表的过滤条件添加到查询语句中 query = agent.limitQuery(index, query) + # 将当前索引作为 LIMIT 条件添加到查询语句中,用于分页获取数据库名 db = unArrayizeValue(inject.getValue(query, union=False, error=False)) + # 执行盲注查询,获取数据库名称,并将其从数组中提取出来 db = safeSQLIdentificatorNaming(db) + # 对提取到的数据库名称进行安全命名 if db not in dbs: + # 如果数据库名称不在 dbs 字典中 dbs[db] = {} + # 在 dbs 字典中创建一个新的键值对,其中键为数据库名称,值为一个空字典 if db not in foundCols[column]: + # 如果数据库名称不在 foundCols[column] 字典中 foundCols[column][db] = [] + # 在 foundCols[column] 字典中创建一个新的键值对,其中键为数据库名称,值为一个空列表 else: + # 如果用户指定了要搜索的数据库(使用了 -D 参数) for db in conf.db.split(',') if conf.db else (self.getCurrentDb(),): + # 遍历用户指定的所有数据库,如果没有指定数据库,则使用当前数据库 db = safeSQLIdentificatorNaming(db) + # 对数据库名称进行安全命名 if db not in foundCols[column]: + # 如果数据库名称不在 foundCols[column] 字典中 foundCols[column][db] = [] + # 在 foundCols[column] 字典中创建一个新的键值对,其中键为数据库名称,值为一个空列表 origDb = conf.db + # 将原始的数据库名称存储在 origDb 变量中 origTbl = conf.tbl + # 将原始的表名称存储在 origTbl 变量中 for column, dbData in foundCols.items(): + # 遍历 foundCols 字典中的所有列及其对应的数据库数据 colQuery = "%s%s" % (colCond, colCondParam) + # 构建列的查询条件字符串 colQuery = colQuery % unsafeSQLIdentificatorNaming(column) + # 将不安全的列名添加到列的查询条件字符串中 for db in dbData: + # 遍历当前列对应的所有数据库 conf.db = origDb + # 将数据库名称重置为原始值 conf.tbl = origTbl + # 将表名称重置为原始值 infoMsg = "fetching number of tables containing column" + # 准备日志消息,表示正在获取包含指定列的表的数量 if colConsider == "1": + # 如果列名使用 LIKE 条件匹配 infoMsg += "s LIKE" + # 将 "s LIKE" 添加到日志消息中 infoMsg += " '%s' in database '%s'" % (unsafeSQLIdentificatorNaming(column), unsafeSQLIdentificatorNaming(db)) + # 将不安全的列名和数据库名称添加到日志消息中 logger.info(infoMsg) + # 打印日志消息 query = rootQuery.blind.count2 + # 获取用于盲注提取表数量的查询语句 if not re.search(r"(?i)%s\Z" % METADB_SUFFIX, db or ""): + # 如果数据库名称不是以元数据后缀结尾 query = query % unsafeSQLIdentificatorNaming(db) + # 将不安全的数据库名称添加到查询语句中 query += " AND %s" % colQuery + # 将列的查询条件添加到查询语句中 else: + # 如果数据库名称以元数据后缀结尾 query = query % colQuery + # 将列的查询条件添加到查询语句中 query += whereTblsQuery + # 将表的过滤条件添加到查询语句中 count = inject.getValue(query, union=False, error=False, expected=EXPECTED.INT, charsetType=CHARSET_TYPE.DIGITS) + # 执行盲注查询,获取匹配的表数量,并将结果视为整数类型 if not isNumPosStrValue(count): + # 如果返回的表数量不是有效的正整数 warnMsg = "no tables contain column" + # 准备警告消息,表示没有找到包含指定列的表 if colConsider == "1": + # 如果列名使用 LIKE 条件匹配 warnMsg += "s LIKE" + # 将 "s LIKE" 添加到警告消息中 warnMsg += " '%s' " % unsafeSQLIdentificatorNaming(column) + # 将不安全的列名添加到警告消息中 warnMsg += "in database '%s'" % unsafeSQLIdentificatorNaming(db) + # 将不安全的数据库名称添加到警告消息中 logger.warning(warnMsg) + # 打印警告消息 continue + # 跳过当前数据库,继续处理下一个数据库 indexRange = getLimitRange(count) + # 获取从 1 到表数量的索引范围,用于循环遍历表 for index in indexRange: + # 遍历每个可能的表索引 query = rootQuery.blind.query2 + # 获取用于盲注提取表名称的查询语句 if re.search(r"(?i)%s\Z" % METADB_SUFFIX, db or ""): + # 如果数据库名称以元数据后缀结尾 query = query % (colQuery + whereTblsQuery) + # 将列的查询条件和表的过滤条件添加到查询语句中 elif query.endswith("'%s')"): + # 如果查询语句以 '%s')' 结尾 query = query[:-1] + " AND %s)" % (colQuery + whereTblsQuery) + # 在结尾添加列的查询条件和表的过滤条件 elif " ORDER BY " in query: + # 如果查询语句包含 " ORDER BY " query = query.replace(" ORDER BY ", " AND %s ORDER BY " % (colQuery + whereTblsQuery)) + # 将列的查询条件和表的过滤条件添加到 " ORDER BY " 前面 else: + # 如果查询语句不满足以上所有条件 query += " AND %s" % (colQuery + whereTblsQuery) + # 将列的查询条件和表的过滤条件添加到查询语句中 query = safeStringFormat(query, unsafeSQLIdentificatorNaming(db)) + # 对查询语句进行格式化,将不安全的数据库名称添加到查询语句中 query = agent.limitQuery(index, query) + # 将当前索引作为 LIMIT 条件添加到查询语句中,用于分页获取表名 tbl = unArrayizeValue(inject.getValue(query, union=False, error=False)) + # 执行盲注查询,获取表名称,并将其从数组中提取出来 kb.hintValue = tbl - + # 将提取到的表名称设置为提示值 tbl = safeSQLIdentificatorNaming(tbl, True) + # 对提取到的表名称进行安全命名 conf.db = db + # 设置当前数据库名称 conf.tbl = tbl + # 设置当前表名称 conf.col = column + # 设置当前列名称 self.getColumns(onlyColNames=True, colTuple=(colConsider, colCondParam), bruteForce=False) + # 调用 getColumns 方法获取当前表中的列信息,但不进行爆破 if db in kb.data.cachedColumns and tbl in kb.data.cachedColumns[db]: + # 如果在 kb.data.cachedColumns 中已经缓存了数据库和表的列信息 if db not in dbs: + # 如果数据库不在 dbs 字典中 dbs[db] = {} + # 在 dbs 字典中创建一个新的键值对,其中键为数据库名称,值为一个空字典 if tbl not in dbs[db]: + # 如果表不在 dbs[db] 字典中 dbs[db][tbl] = {} + # 在 dbs[db] 字典中创建一个新的键值对,其中键为表名称,值为一个空字典 dbs[db][tbl].update(kb.data.cachedColumns[db][tbl]) + # 将缓存的列信息更新到 dbs[db][tbl] 中 kb.data.cachedColumns = {} + # 清空缓存的列信息 if db in foundCols[column]: + # 如果数据库名称已经在 foundCols[column] 字典中 foundCols[column][db].append(tbl) + # 将表名称添加到 foundCols[column][db] 的列表中 else: + # 如果数据库名称不在 foundCols[column] 字典中 foundCols[column][db] = [tbl] - - if dbs: - conf.dumper.dbColumns(foundCols, colConsider, dbs) - self.dumpFoundColumn(dbs, foundCols, colConsider) - else: - warnMsg = "no databases have tables containing any of the " - warnMsg += "provided columns" - logger.warning(warnMsg) - - def search(self): - if Backend.getIdentifiedDbms() in UPPER_CASE_DBMSES: - for item in ('db', 'tbl', 'col'): - if getattr(conf, item, None): - setattr(conf, item, getattr(conf, item).upper()) - - if conf.col: - self.searchColumn() - elif conf.tbl: - self.searchTable() - elif conf.db: - self.searchDb() - else: - errMsg = "missing parameter, provide -D, -T or -C along " - errMsg += "with --search" - raise SqlmapMissingMandatoryOptionException(errMsg) + # 在 foundCols[column] 字典中创建一个新的键值对,其中键为数据库名称,值为一个包含表名称的列表 + if dbs: + # 如果找到任何数据库和表 + conf.dumper.dbColumns(foundCols, colConsider, dbs) + # 使用 dumper 对象打印找到的列信息 + self.dumpFoundColumn(dbs, foundCols, colConsider) + # 调用 dumpFoundColumn 方法,对找到的列进行处理 + else: + # 如果没有找到任何数据库和表 + warnMsg = "no databases have tables containing any of the " + # 准备警告消息,表示没有找到包含指定列的表 + warnMsg += "provided columns" + # 将 "provided columns" 添加到警告消息中 + logger.warning(warnMsg) + # 打印警告消息 \ No newline at end of file