diff --git a/src/sqlmap-master/lib/core/datatype.py b/src/sqlmap-master/lib/core/datatype.py index 866b114..9638f0d 100644 --- a/src/sqlmap-master/lib/core/datatype.py +++ b/src/sqlmap-master/lib/core/datatype.py @@ -5,13 +5,15 @@ Copyright (c) 2006-2024 sqlmap developers (https://sqlmap.org/) See the file 'LICENSE' for copying permission """ -import copy -import threading -import types +# 导入必要的模块 +import copy # 导入 copy 模块,用于对象复制 +import threading # 导入 threading 模块,用于线程同步 +import types # 导入 types 模块,用于类型判断 -from thirdparty.odict import OrderedDict -from thirdparty.six.moves import collections_abc as _collections +from thirdparty.odict import OrderedDict # 导入 thirdparty 中的 OrderedDict 类,用于实现有序字典 +from thirdparty.six.moves import collections_abc as _collections # 导入 six 库中的 collections_abc 模块,用于抽象集合类 +# 定义 AttribDict 类,继承自 dict,允许以属性方式访问字典成员 class AttribDict(dict): """ This class defines the dictionary with added capability to access members as attributes @@ -22,20 +24,20 @@ class AttribDict(dict): 1 """ + # 初始化方法,接受一个字典 indict,一个属性 attribute 和一个布尔值 keycheck def __init__(self, indict=None, attribute=None, keycheck=True): - if indict is None: + if indict is None: # 如果 indict 为空,初始化为空字典 indict = {} - # Set any attributes here - before initialisation - # these remain as normal attributes + # 设置属性,这些属性在初始化前是普通属性 self.attribute = attribute self.keycheck = keycheck - dict.__init__(self, indict) - self.__initialised = True + dict.__init__(self, indict) # 调用 dict 的初始化方法 + self.__initialised = True # 设置初始化完成标志 - # After initialisation, setting attributes - # is the same as setting an item + # 在初始化之后,设置属性与设置字典项相同 + # 定义 __getattr__ 方法,用于获取属性 def __getattr__(self, item): """ Maps values to attributes @@ -43,89 +45,95 @@ class AttribDict(dict): """ try: - return self.__getitem__(item) - except KeyError: - if self.keycheck: - raise AttributeError("unable to access item '%s'" % item) - else: - return None - + return self.__getitem__(item) # 尝试获取字典项 + except KeyError: # 如果字典中不存在此键 + if self.keycheck: # 如果 keycheck 为 True + raise AttributeError("unable to access item '%s'" % item) # 抛出属性错误 + else: # 如果 keycheck 为 False + return None # 返回 None + + # 定义 __delattr__ 方法,用于删除属性 def __delattr__(self, item): """ Deletes attributes """ try: - return self.pop(item) - except KeyError: - if self.keycheck: - raise AttributeError("unable to access item '%s'" % item) - else: - return None - + return self.pop(item) # 尝试从字典中删除项 + except KeyError: # 如果字典中不存在此键 + if self.keycheck: # 如果 keycheck 为 True + raise AttributeError("unable to access item '%s'" % item) # 抛出属性错误 + else: # 如果 keycheck 为 False + return None # 返回 None + + # 定义 __setattr__ 方法,用于设置属性 def __setattr__(self, item, value): """ Maps attributes to values Only if we are initialised """ - # This test allows attributes to be set in the __init__ method + # 在初始化方法中允许设置属性 if "_AttribDict__initialised" not in self.__dict__: return dict.__setattr__(self, item, value) - # Any normal attributes are handled normally + # 正常处理普通属性 elif item in self.__dict__: dict.__setattr__(self, item, value) - else: + else: # 其他情况,将属性映射到字典项 self.__setitem__(item, value) + # 定义 __getstate__ 方法,用于支持序列化 def __getstate__(self): return self.__dict__ + # 定义 __setstate__ 方法,用于支持反序列化 def __setstate__(self, dict): self.__dict__ = dict + # 定义 __deepcopy__ 方法,用于深拷贝 def __deepcopy__(self, memo): - retVal = self.__class__() - memo[id(self)] = retVal + retVal = self.__class__() # 创建一个新实例 + memo[id(self)] = retVal # 将新实例添加到 memo 中 - for attr in dir(self): - if not attr.startswith('_'): - value = getattr(self, attr) - if not isinstance(value, (types.BuiltinFunctionType, types.FunctionType, types.MethodType)): - setattr(retVal, attr, copy.deepcopy(value, memo)) + for attr in dir(self): # 遍历所有属性 + if not attr.startswith('_'): # 忽略私有属性 + value = getattr(self, attr) # 获取属性值 + if not isinstance(value, (types.BuiltinFunctionType, types.FunctionType, types.MethodType)): # 忽略内置函数、函数和方法 + setattr(retVal, attr, copy.deepcopy(value, memo)) # 深拷贝属性值 - for key, value in self.items(): - retVal.__setitem__(key, copy.deepcopy(value, memo)) + for key, value in self.items(): # 遍历所有字典项 + retVal.__setitem__(key, copy.deepcopy(value, memo)) # 深拷贝字典项 - return retVal + return retVal # 返回深拷贝后的实例 +# 定义 InjectionDict 类,继承自 AttribDict,用于存储注入相关信息 class InjectionDict(AttribDict): def __init__(self): - AttribDict.__init__(self) - - self.place = None - self.parameter = None - self.ptype = None - self.prefix = None - self.suffix = None - self.clause = None - self.notes = [] # Note: https://github.com/sqlmapproject/sqlmap/issues/1888 - - # data is a dict with various stype, each which is a dict with - # all the information specific for that stype + AttribDict.__init__(self) # 调用 AttribDict 的初始化方法 + + # 初始化注入信息 + self.place = None # 注入位置 + self.parameter = None # 注入参数 + self.ptype = None # 参数类型 + self.prefix = None # 前缀 + self.suffix = None # 后缀 + self.clause = None # 子句 + self.notes = [] # 备注列表 + + # data 字典存储不同类型的注入数据 self.data = AttribDict() - # conf is a dict which stores current snapshot of important - # options used during detection + # conf 字典存储检测期间使用的重要选项的快照 self.conf = AttribDict() - self.dbms = None - self.dbms_version = None - self.os = None + self.dbms = None # 数据库类型 + self.dbms_version = None # 数据库版本 + self.os = None # 操作系统 -# Reference: https://www.kunxi.org/2014/05/lru-cache-in-python +# 定义 LRUDict 类,实现 LRU 缓存字典 +# 参考:https://www.kunxi.org/2014/05/lru-cache-in-python class LRUDict(object): """ This class defines the LRU dictionary @@ -141,40 +149,41 @@ class LRUDict(object): """ def __init__(self, capacity): - self.capacity = capacity - self.cache = OrderedDict() - self.__lock = threading.Lock() + self.capacity = capacity # 设置缓存容量 + self.cache = OrderedDict() # 使用 OrderedDict 作为缓存 + self.__lock = threading.Lock() # 创建一个锁,用于线程同步 def __len__(self): - return len(self.cache) + return len(self.cache) # 返回缓存长度 def __contains__(self, key): - return key in self.cache + return key in self.cache # 判断键是否存在于缓存中 def __getitem__(self, key): - value = self.cache.pop(key) - self.cache[key] = value - return value + value = self.cache.pop(key) # 将键从缓存中移除 + self.cache[key] = value # 将键添加回缓存,移动到最后 + return value # 返回键的值 def get(self, key): - return self.__getitem__(key) + return self.__getitem__(key) # 获取键的值 def __setitem__(self, key, value): - with self.__lock: + with self.__lock: # 获取锁,保证线程安全 try: - self.cache.pop(key) - except KeyError: - if len(self.cache) >= self.capacity: - self.cache.popitem(last=False) - self.cache[key] = value + self.cache.pop(key) # 尝试从缓存中删除键 + except KeyError: # 如果键不存在 + if len(self.cache) >= self.capacity: # 如果缓存已满 + self.cache.popitem(last=False) # 删除最老的项 + self.cache[key] = value # 将键值添加到缓存中 def set(self, key, value): - self.__setitem__(key, value) + self.__setitem__(key, value) # 设置键值 def keys(self): - return self.cache.keys() + return self.cache.keys() # 返回缓存的所有键 -# Reference: https://code.activestate.com/recipes/576694/ +# 定义 OrderedSet 类,实现有序集合 +# 参考:https://code.activestate.com/recipes/576694/ class OrderedSet(_collections.MutableSet): """ This class defines the set with ordered (as added) items @@ -192,57 +201,57 @@ class OrderedSet(_collections.MutableSet): """ def __init__(self, iterable=None): - self.end = end = [] - end += [None, end, end] # sentinel node for doubly linked list - self.map = {} # key --> [key, prev, next] + self.end = end = [] # 创建哨兵节点 + end += [None, end, end] # 双向链表的哨兵节点 + self.map = {} # 存储键值和链表节点的映射 if iterable is not None: - self |= iterable + self |= iterable # 添加可迭代对象 def __len__(self): - return len(self.map) + return len(self.map) # 返回集合长度 def __contains__(self, key): - return key in self.map + return key in self.map # 判断键是否存在于集合中 def add(self, value): - if value not in self.map: + if value not in self.map: # 如果值不在集合中 end = self.end curr = end[1] - curr[2] = end[1] = self.map[value] = [value, curr, end] + curr[2] = end[1] = self.map[value] = [value, curr, end] # 添加新节点到链表尾部 def discard(self, value): - if value in self.map: - value, prev, next = self.map.pop(value) - prev[2] = next + if value in self.map: # 如果值在集合中 + value, prev, next = self.map.pop(value) # 移除节点 + prev[2] = next # 更新链表 next[1] = prev def __iter__(self): end = self.end - curr = end[2] + curr = end[2] # 从链表头开始遍历 while curr is not end: yield curr[0] - curr = curr[2] + curr = curr[2] # 移动到下一个节点 def __reversed__(self): end = self.end - curr = end[1] + curr = end[1] # 从链表尾开始遍历 while curr is not end: yield curr[0] - curr = curr[1] + curr = curr[1] # 移动到上一个节点 def pop(self, last=True): - if not self: + if not self: # 如果集合为空 raise KeyError('set is empty') - key = self.end[1][0] if last else self.end[2][0] - self.discard(key) - return key + key = self.end[1][0] if last else self.end[2][0] # 获取最后一个或第一个元素 + self.discard(key) # 移除元素 + return key # 返回元素值 def __repr__(self): - if not self: + if not self: # 如果集合为空 return '%s()' % (self.__class__.__name__,) - return '%s(%r)' % (self.__class__.__name__, list(self)) + return '%s(%r)' % (self.__class__.__name__, list(self)) # 返回字符串表示 def __eq__(self, other): - if isinstance(other, OrderedSet): - return len(self) == len(other) and list(self) == list(other) - return set(self) == set(other) + if isinstance(other, OrderedSet): # 如果另一个对象是有序集合 + return len(self) == len(other) and list(self) == list(other) # 比较长度和内容 + return set(self) == set(other) # 比较集合内容 \ No newline at end of file diff --git a/src/sqlmap-master/plugins/dbms/mssqlserver/fingerprint.py b/src/sqlmap-master/plugins/dbms/mssqlserver/fingerprint.py index 1e8e492..9a6ba86 100644 --- a/src/sqlmap-master/plugins/dbms/mssqlserver/fingerprint.py +++ b/src/sqlmap-master/plugins/dbms/mssqlserver/fingerprint.py @@ -5,89 +5,96 @@ Copyright (c) 2006-2024 sqlmap developers (https://sqlmap.org/) See the file 'LICENSE' for copying permission """ -from lib.core.common import Backend -from lib.core.common import Format -from lib.core.convert import getUnicode -from lib.core.data import conf -from lib.core.data import kb -from lib.core.data import logger -from lib.core.enums import DBMS -from lib.core.enums import OS -from lib.core.session import setDbms -from lib.core.settings import MSSQL_ALIASES -from lib.request import inject -from plugins.generic.fingerprint import Fingerprint as GenericFingerprint - +# 导入必要的模块 +from lib.core.common import Backend # 导入 Backend 类,用于访问后端数据库信息 +from lib.core.common import Format # 导入 Format 类,用于格式化输出信息 +from lib.core.convert import getUnicode # 导入 getUnicode 函数,用于获取 Unicode 字符串 +from lib.core.data import conf # 导入 conf 对象,用于访问全局配置信息 +from lib.core.data import kb # 导入 kb 对象,用于访问全局知识库 +from lib.core.data import logger # 导入 logger 对象,用于输出日志 +from lib.core.enums import DBMS # 导入 DBMS 枚举,定义数据库管理系统类型 +from lib.core.enums import OS # 导入 OS 枚举,定义操作系统类型 +from lib.core.session import setDbms # 导入 setDbms 函数,用于设置数据库类型 +from lib.core.settings import MSSQL_ALIASES # 导入 MSSQL_ALIASES 常量,定义 SQL Server 的别名 +from lib.request import inject # 导入 inject 函数,用于执行 SQL 注入请求 +from plugins.generic.fingerprint import Fingerprint as GenericFingerprint # 导入 GenericFingerprint 类,作为当前类的父类 + +# 定义 Fingerprint 类,继承自 GenericFingerprint class Fingerprint(GenericFingerprint): + # 初始化 Fingerprint 类,设置数据库类型为 MSSQL def __init__(self): GenericFingerprint.__init__(self, DBMS.MSSQL) + # 定义 getFingerprint 方法,用于获取数据库指纹信息 def getFingerprint(self): - value = "" - wsOsFp = Format.getOs("web server", kb.headersFp) + value = "" # 初始化指纹信息字符串 + wsOsFp = Format.getOs("web server", kb.headersFp) # 获取 Web 服务器操作系统信息 if wsOsFp: - value += "%s\n" % wsOsFp + value += "%s\ +" % wsOsFp # 将 Web 服务器操作系统信息添加到指纹信息 - if kb.data.banner: - dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp) + if kb.data.banner: # 如果存在数据库 banner 信息 + dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp) # 获取数据库操作系统信息 if dbmsOsFp: - value += "%s\n" % dbmsOsFp + value += "%s\ +" % dbmsOsFp # 将数据库操作系统信息添加到指纹信息 - value += "back-end DBMS: " - actVer = Format.getDbms() + value += "back-end DBMS: " # 添加数据库类型标签 + actVer = Format.getDbms() # 获取数据库类型 - if not conf.extensiveFp: - value += actVer - return value + if not conf.extensiveFp: # 如果不需要详细指纹信息 + value += actVer # 将数据库类型添加到指纹信息 + return value # 返回指纹信息 - blank = " " * 15 - value += "active fingerprint: %s" % actVer + blank = " " * 15 # 定义缩进空格 + value += "active fingerprint: %s" % actVer # 添加当前指纹信息 - if kb.bannerFp: - release = kb.bannerFp.get("dbmsRelease") - version = kb.bannerFp.get("dbmsVersion") - servicepack = kb.bannerFp.get("dbmsServicePack") + if kb.bannerFp: # 如果存在数据库 banner 信息 + release = kb.bannerFp.get("dbmsRelease") # 获取数据库版本发布信息 + version = kb.bannerFp.get("dbmsVersion") # 获取数据库版本信息 + servicepack = kb.bannerFp.get("dbmsServicePack") # 获取数据库服务包信息 - if release and version and servicepack: - banVer = "%s %s " % (DBMS.MSSQL, release) - banVer += "Service Pack %s " % servicepack - banVer += "version %s" % version + if release and version and servicepack: # 如果所有信息都存在 + banVer = "%s %s " % (DBMS.MSSQL, release) # 构建 banner 版本信息 + banVer += "Service Pack %s " % servicepack # 添加服务包信息 + banVer += "version %s" % version # 添加版本信息 - value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer) + value += "\ +%sbanner parsing fingerprint: %s" % (blank, banVer) # 将 banner 版本信息添加到指纹信息 - htmlErrorFp = Format.getErrorParsedDBMSes() + htmlErrorFp = Format.getErrorParsedDBMSes() # 获取 HTML 错误信息中的数据库信息 if htmlErrorFp: - value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp) + value += "\ +%shtml error message fingerprint: %s" % (blank, htmlErrorFp) # 将 HTML 错误信息中的数据库信息添加到指纹信息 - return value + return value # 返回指纹信息 + # 定义 checkDbms 方法,用于检查数据库类型是否为 MSSQL def checkDbms(self): - if not conf.extensiveFp and Backend.isDbmsWithin(MSSQL_ALIASES): - setDbms("%s %s" % (DBMS.MSSQL, Backend.getVersion())) - - self.getBanner() - - Backend.setOs(OS.WINDOWS) - - return True + if not conf.extensiveFp and Backend.isDbmsWithin(MSSQL_ALIASES): # 如果不需要详细指纹并且数据库别名匹配 + setDbms("%s %s" % (DBMS.MSSQL, Backend.getVersion())) # 设置数据库类型 + self.getBanner() # 获取数据库 banner 信息 + Backend.setOs(OS.WINDOWS) # 设置操作系统类型为 Windows + return True # 返回 True - infoMsg = "testing %s" % DBMS.MSSQL + infoMsg = "testing %s" % DBMS.MSSQL # 输出正在测试 MSSQL 的信息 logger.info(infoMsg) # NOTE: SELECT LEN(@@VERSION)=LEN(@@VERSION) FROM DUAL does not # work connecting directly to the Microsoft SQL Server database - if conf.direct: - result = True + if conf.direct: # 如果是直接连接 + result = True # 直接设置为 True else: - result = inject.checkBooleanExpression("UNICODE(SQUARE(NULL)) IS NULL") + result = inject.checkBooleanExpression("UNICODE(SQUARE(NULL)) IS NULL") # 使用 SQL 注入检查 - if result: - infoMsg = "confirming %s" % DBMS.MSSQL + if result: # 如果检查结果为 True + infoMsg = "confirming %s" % DBMS.MSSQL # 输出确认是 MSSQL 的信息 logger.info(infoMsg) + # 遍历不同的 MSSQL 版本及其检查语句 for version, check in ( ("2022", "CHARINDEX('16.0.',@@VERSION)>0"), ("2019", "CHARINDEX('15.0.',@@VERSION)>0"), @@ -100,48 +107,46 @@ class Fingerprint(GenericFingerprint): ("2005", "XACT_STATE()=XACT_STATE()"), ("2000", "HOST_NAME()=HOST_NAME()"), ): - result = inject.checkBooleanExpression(check) + result = inject.checkBooleanExpression(check) # 使用 SQL 注入检查版本 if result: - Backend.setVersion(version) + Backend.setVersion(version) # 设置数据库版本 break if Backend.getVersion(): - setDbms("%s %s" % (DBMS.MSSQL, Backend.getVersion())) + setDbms("%s %s" % (DBMS.MSSQL, Backend.getVersion())) # 设置数据库类型和版本 else: - setDbms(DBMS.MSSQL) + setDbms(DBMS.MSSQL) # 设置数据库类型 - self.getBanner() - - Backend.setOs(OS.WINDOWS) - - return True - else: - warnMsg = "the back-end DBMS is not %s" % DBMS.MSSQL + self.getBanner() # 获取数据库 banner 信息 + Backend.setOs(OS.WINDOWS) # 设置操作系统类型为 Windows + return True # 返回 True + else: # 如果检查结果为 False + warnMsg = "the back-end DBMS is not %s" % DBMS.MSSQL # 输出警告信息 logger.warning(warnMsg) + return False # 返回 False - return False - + # 定义 checkDbmsOs 方法,用于检查数据库操作系统信息 def checkDbmsOs(self, detailed=False): - if Backend.getOs() and Backend.getOsVersion() and Backend.getOsServicePack(): + if Backend.getOs() and Backend.getOsVersion() and Backend.getOsServicePack(): # 如果已获取操作系统信息,则直接返回 return - if not Backend.getOs(): - Backend.setOs(OS.WINDOWS) + if not Backend.getOs(): # 如果没有获取操作系统信息 + Backend.setOs(OS.WINDOWS) # 设置操作系统类型为 Windows - if not detailed: + if not detailed: # 如果不需要详细信息,则直接返回 return - infoMsg = "fingerprinting the back-end DBMS operating system " + infoMsg = "fingerprinting the back-end DBMS operating system " # 输出正在获取操作系统版本和服务包的信息 infoMsg += "version and service pack" logger.info(infoMsg) - infoMsg = "the back-end DBMS operating system is %s" % Backend.getOs() + infoMsg = "the back-end DBMS operating system is %s" % Backend.getOs() # 输出操作系统类型 - self.createSupportTbl(self.fileTblName, self.tblField, "varchar(1000)") - inject.goStacked("INSERT INTO %s(%s) VALUES (%s)" % (self.fileTblName, self.tblField, "@@VERSION")) + self.createSupportTbl(self.fileTblName, self.tblField, "varchar(1000)") # 创建支持表,用于存储版本信息 + inject.goStacked("INSERT INTO %s(%s) VALUES (%s)" % (self.fileTblName, self.tblField, "@@VERSION")) # 将 @@VERSION 写入支持表 - # Reference: https://en.wikipedia.org/wiki/Comparison_of_Microsoft_Windows_versions + # 参考:https://en.wikipedia.org/wiki/Comparison_of_Microsoft_Windows_versions # https://en.wikipedia.org/wiki/Windows_NT#Releases versions = { "NT": ("4.0", (6, 5, 4, 3, 2, 1)), @@ -155,50 +160,50 @@ class Fingerprint(GenericFingerprint): "10 or 11 or 2016 or 2019 or 2022": ("10.0", (0,)) } - # Get back-end DBMS underlying operating system version + # 获取数据库操作系统版本 for version, data in versions.items(): - query = "EXISTS(SELECT %s FROM %s WHERE %s " % (self.tblField, self.fileTblName, self.tblField) - query += "LIKE '%Windows NT " + data[0] + "%')" - result = inject.checkBooleanExpression(query) + query = "EXISTS(SELECT %s FROM %s WHERE %s " % (self.tblField, self.fileTblName, self.tblField) # 构建查询语句 + query += "LIKE '%Windows NT " + data[0] + "%')" # 添加版本判断条件 + result = inject.checkBooleanExpression(query) # 使用 SQL 注入检查 if result: - Backend.setOsVersion(version) - infoMsg += " %s" % Backend.getOsVersion() + Backend.setOsVersion(version) # 设置操作系统版本 + infoMsg += " %s" % Backend.getOsVersion() # 将操作系统版本信息添加到日志信息 break - if not Backend.getOsVersion(): - Backend.setOsVersion("2003") - Backend.setOsServicePack(2) + if not Backend.getOsVersion(): # 如果没有获取到操作系统版本 + Backend.setOsVersion("2003") # 默认设置为 2003 + Backend.setOsServicePack(2) # 默认设置为服务包 2 warnMsg = "unable to fingerprint the underlying operating " warnMsg += "system version, assuming it is Windows " warnMsg += "%s Service Pack %d" % (Backend.getOsVersion(), Backend.getOsServicePack()) logger.warning(warnMsg) - self.cleanup(onlyFileTbl=True) + self.cleanup(onlyFileTbl=True) # 清理支持表 return - # Get back-end DBMS underlying operating system service pack - sps = versions[Backend.getOsVersion()][1] + # 获取操作系统服务包 + sps = versions[Backend.getOsVersion()][1] # 获取服务包列表 for sp in sps: - query = "EXISTS(SELECT %s FROM %s WHERE %s " % (self.tblField, self.fileTblName, self.tblField) - query += "LIKE '%Service Pack " + getUnicode(sp) + "%')" - result = inject.checkBooleanExpression(query) + query = "EXISTS(SELECT %s FROM %s WHERE %s " % (self.tblField, self.fileTblName, self.tblField) # 构建查询语句 + query += "LIKE '%Service Pack " + getUnicode(sp) + "%')" # 添加服务包判断条件 + result = inject.checkBooleanExpression(query) # 使用 SQL 注入检查 if result: - Backend.setOsServicePack(sp) + Backend.setOsServicePack(sp) # 设置操作系统服务包 break - if not Backend.getOsServicePack(): - debugMsg = "assuming the operating system has no service pack" + if not Backend.getOsServicePack(): # 如果没有获取到服务包 + debugMsg = "assuming the operating system has no service pack" # 输出调试信息 logger.debug(debugMsg) - Backend.setOsServicePack(0) + Backend.setOsServicePack(0) # 默认设置为服务包 0 if Backend.getOsVersion(): - infoMsg += " Service Pack %d" % Backend.getOsServicePack() + infoMsg += " Service Pack %d" % Backend.getOsServicePack() # 将服务包信息添加到日志信息 logger.info(infoMsg) - self.cleanup(onlyFileTbl=True) + self.cleanup(onlyFileTbl=True) # 清理支持表 \ No newline at end of file diff --git a/src/sqlmap-master/plugins/dbms/vertica/fingerprint.py b/src/sqlmap-master/plugins/dbms/vertica/fingerprint.py index d31ef61..fe5e574 100644 --- a/src/sqlmap-master/plugins/dbms/vertica/fingerprint.py +++ b/src/sqlmap-master/plugins/dbms/vertica/fingerprint.py @@ -5,102 +5,107 @@ Copyright (c) 2006-2024 sqlmap developers (https://sqlmap.org/) See the file 'LICENSE' for copying permission """ -from lib.core.common import Backend -from lib.core.common import Format -from lib.core.data import conf -from lib.core.data import kb -from lib.core.data import logger -from lib.core.enums import DBMS -from lib.core.session import setDbms -from lib.core.settings import VERTICA_ALIASES -from lib.request import inject -from plugins.generic.fingerprint import Fingerprint as GenericFingerprint - +# 导入必要的模块 +from lib.core.common import Backend # 导入 Backend 类,用于访问后端数据库信息 +from lib.core.common import Format # 导入 Format 类,用于格式化输出信息 +from lib.core.data import conf # 导入 conf 对象,用于访问全局配置信息 +from lib.core.data import kb # 导入 kb 对象,用于访问全局知识库 +from lib.core.data import logger # 导入 logger 对象,用于输出日志 +from lib.core.enums import DBMS # 导入 DBMS 枚举,定义数据库管理系统类型 +from lib.core.session import setDbms # 导入 setDbms 函数,用于设置数据库类型 +from lib.core.settings import VERTICA_ALIASES # 导入 VERTICA_ALIASES 常量,定义 Vertica 数据库的别名 +from lib.request import inject # 导入 inject 函数,用于执行 SQL 注入请求 +from plugins.generic.fingerprint import Fingerprint as GenericFingerprint # 导入 GenericFingerprint 类,作为当前类的父类 + +# 定义 Fingerprint 类,继承自 GenericFingerprint class Fingerprint(GenericFingerprint): + # 初始化 Fingerprint 类,设置数据库类型为 Vertica def __init__(self): GenericFingerprint.__init__(self, DBMS.VERTICA) + # 定义 getFingerprint 方法,用于获取数据库指纹信息 def getFingerprint(self): - value = "" - wsOsFp = Format.getOs("web server", kb.headersFp) + value = "" # 初始化指纹信息字符串 + wsOsFp = Format.getOs("web server", kb.headersFp) # 获取 Web 服务器操作系统信息 if wsOsFp: - value += "%s\n" % wsOsFp + value += "%s\ +" % wsOsFp # 将 Web 服务器操作系统信息添加到指纹信息 - if kb.data.banner: - dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp) + if kb.data.banner: # 如果存在数据库 banner 信息 + dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp) # 获取数据库操作系统信息 if dbmsOsFp: - value += "%s\n" % dbmsOsFp + value += "%s\ +" % dbmsOsFp # 将数据库操作系统信息添加到指纹信息 - value += "back-end DBMS: " + value += "back-end DBMS: " # 添加数据库类型标签 - if not conf.extensiveFp: - value += DBMS.VERTICA - return value + if not conf.extensiveFp: # 如果不需要详细指纹信息 + value += DBMS.VERTICA # 将数据库类型添加到指纹信息 + return value # 返回指纹信息 - actVer = Format.getDbms() - blank = " " * 15 - value += "active fingerprint: %s" % actVer + actVer = Format.getDbms() # 获取数据库类型 + blank = " " * 15 # 定义缩进空格 + value += "active fingerprint: %s" % actVer # 添加当前指纹信息 - if kb.bannerFp: - banVer = kb.bannerFp.get("dbmsVersion") + if kb.bannerFp: # 如果存在数据库 banner 信息 + banVer = kb.bannerFp.get("dbmsVersion") # 获取数据库版本信息 if banVer: - banVer = Format.getDbms([banVer]) - value += "\n%sbanner parsing fingerprint: %s" % (blank, banVer) + banVer = Format.getDbms([banVer]) # 格式化数据库版本信息 + value += "\ +%sbanner parsing fingerprint: %s" % (blank, banVer) # 将 banner 版本信息添加到指纹信息 - htmlErrorFp = Format.getErrorParsedDBMSes() + htmlErrorFp = Format.getErrorParsedDBMSes() # 获取 HTML 错误信息中的数据库信息 if htmlErrorFp: - value += "\n%shtml error message fingerprint: %s" % (blank, htmlErrorFp) + value += "\ +%shtml error message fingerprint: %s" % (blank, htmlErrorFp) # 将 HTML 错误信息中的数据库信息添加到指纹信息 - return value + return value # 返回指纹信息 + # 定义 checkDbms 方法,用于检查数据库类型是否为 Vertica def checkDbms(self): - if not conf.extensiveFp and Backend.isDbmsWithin(VERTICA_ALIASES): - setDbms(DBMS.VERTICA) - - self.getBanner() - - return True + if not conf.extensiveFp and Backend.isDbmsWithin(VERTICA_ALIASES): # 如果不需要详细指纹并且数据库别名匹配 + setDbms(DBMS.VERTICA) # 设置数据库类型为 Vertica + self.getBanner() # 获取数据库 banner 信息 + return True # 返回 True - infoMsg = "testing %s" % DBMS.VERTICA + infoMsg = "testing %s" % DBMS.VERTICA # 输出正在测试 Vertica 的信息 logger.info(infoMsg) # NOTE: Vertica works too without the CONVERT_TO() - result = inject.checkBooleanExpression("BITSTRING_TO_BINARY(NULL) IS NULL") + result = inject.checkBooleanExpression("BITSTRING_TO_BINARY(NULL) IS NULL") # 使用 SQL 注入检查 - if result: - infoMsg = "confirming %s" % DBMS.VERTICA + if result: # 如果检查结果为 True + infoMsg = "confirming %s" % DBMS.VERTICA # 输出确认是 Vertica 的信息 logger.info(infoMsg) - result = inject.checkBooleanExpression("HEX_TO_INTEGER(NULL) IS NULL") + result = inject.checkBooleanExpression("HEX_TO_INTEGER(NULL) IS NULL") # 使用 SQL 注入检查 - if not result: - warnMsg = "the back-end DBMS is not %s" % DBMS.VERTICA + if not result: # 如果检查结果为 False + warnMsg = "the back-end DBMS is not %s" % DBMS.VERTICA # 输出警告信息 logger.warning(warnMsg) + return False # 返回 False - return False + setDbms(DBMS.VERTICA) # 设置数据库类型为 Vertica + self.getBanner() # 获取数据库 banner 信息 - setDbms(DBMS.VERTICA) + if not conf.extensiveFp: # 如果不需要详细指纹信息 + return True # 返回 True - self.getBanner() - - if not conf.extensiveFp: - return True - - infoMsg = "actively fingerprinting %s" % DBMS.VERTICA + infoMsg = "actively fingerprinting %s" % DBMS.VERTICA # 输出正在进行详细指纹识别的信息 logger.info(infoMsg) + # 根据 CALENDAR_HIERARCHY_DAY(NULL) 的结果判断 Vertica 版本 if inject.checkBooleanExpression("CALENDAR_HIERARCHY_DAY(NULL) IS NULL"): - Backend.setVersion(">= 9.0") + Backend.setVersion(">= 9.0") # 设置数据库版本为 >= 9.0 else: - Backend.setVersion("< 9.0") + Backend.setVersion("< 9.0") # 设置数据库版本为 < 9.0 - return True - else: - warnMsg = "the back-end DBMS is not %s" % DBMS.VERTICA + return True # 返回 True + else: # 如果检查结果为 False + warnMsg = "the back-end DBMS is not %s" % DBMS.VERTICA # 输出警告信息 logger.warning(warnMsg) - - return False + return False # 返回 False \ No newline at end of file diff --git a/src/sqlmap-master/plugins/generic/custom.py b/src/sqlmap-master/plugins/generic/custom.py index dbfd589..fe5e574 100644 --- a/src/sqlmap-master/plugins/generic/custom.py +++ b/src/sqlmap-master/plugins/generic/custom.py @@ -5,146 +5,107 @@ Copyright (c) 2006-2024 sqlmap developers (https://sqlmap.org/) See the file 'LICENSE' for copying permission """ -from __future__ import print_function - -import re -import sys - -from lib.core.common import Backend -from lib.core.common import dataToStdout -from lib.core.common import getSQLSnippet -from lib.core.common import isStackingAvailable -from lib.core.convert import getUnicode -from lib.core.data import conf -from lib.core.data import logger -from lib.core.dicts import SQL_STATEMENTS -from lib.core.enums import AUTOCOMPLETE_TYPE -from lib.core.enums import DBMS -from lib.core.exception import SqlmapNoneDataException -from lib.core.settings import METADB_SUFFIX -from lib.core.settings import NULL -from lib.core.settings import PARAMETER_SPLITTING_REGEX -from lib.core.shell import autoCompletion -from lib.request import inject -from thirdparty.six.moves import input as _input - -class Custom(object): - """ - This class defines custom enumeration functionalities for plugins. - """ - +# 导入必要的模块 +from lib.core.common import Backend # 导入 Backend 类,用于访问后端数据库信息 +from lib.core.common import Format # 导入 Format 类,用于格式化输出信息 +from lib.core.data import conf # 导入 conf 对象,用于访问全局配置信息 +from lib.core.data import kb # 导入 kb 对象,用于访问全局知识库 +from lib.core.data import logger # 导入 logger 对象,用于输出日志 +from lib.core.enums import DBMS # 导入 DBMS 枚举,定义数据库管理系统类型 +from lib.core.session import setDbms # 导入 setDbms 函数,用于设置数据库类型 +from lib.core.settings import VERTICA_ALIASES # 导入 VERTICA_ALIASES 常量,定义 Vertica 数据库的别名 +from lib.request import inject # 导入 inject 函数,用于执行 SQL 注入请求 +from plugins.generic.fingerprint import Fingerprint as GenericFingerprint # 导入 GenericFingerprint 类,作为当前类的父类 + +# 定义 Fingerprint 类,继承自 GenericFingerprint +class Fingerprint(GenericFingerprint): + # 初始化 Fingerprint 类,设置数据库类型为 Vertica def __init__(self): - pass - - def sqlQuery(self, query): - output = None - sqlType = None - query = query.rstrip(';') + GenericFingerprint.__init__(self, DBMS.VERTICA) - try: - for sqlTitle, sqlStatements in SQL_STATEMENTS.items(): - for sqlStatement in sqlStatements: - if query.lower().startswith(sqlStatement): - sqlType = sqlTitle - break + # 定义 getFingerprint 方法,用于获取数据库指纹信息 + def getFingerprint(self): + value = "" # 初始化指纹信息字符串 + wsOsFp = Format.getOs("web server", kb.headersFp) # 获取 Web 服务器操作系统信息 - if not re.search(r"\b(OPENROWSET|INTO)\b", query, re.I) and (not sqlType or "SELECT" in sqlType): - infoMsg = "fetching %s query output: '%s'" % (sqlType if sqlType is not None else "SQL", query) - logger.info(infoMsg) + if wsOsFp: + value += "%s\ +" % wsOsFp # 将 Web 服务器操作系统信息添加到指纹信息 - if Backend.isDbms(DBMS.MSSQL): - match = re.search(r"(\bFROM\s+)([^\s]+)", query, re.I) - if match and match.group(2).count('.') == 1: - query = query.replace(match.group(0), "%s%s" % (match.group(1), match.group(2).replace('.', ".dbo."))) + if kb.data.banner: # 如果存在数据库 banner 信息 + dbmsOsFp = Format.getOs("back-end DBMS", kb.bannerFp) # 获取数据库操作系统信息 - query = re.sub(r"(?i)\w+%s\.?" % METADB_SUFFIX, "", query) + if dbmsOsFp: + value += "%s\ +" % dbmsOsFp # 将数据库操作系统信息添加到指纹信息 - output = inject.getValue(query, fromUser=True) + value += "back-end DBMS: " # 添加数据库类型标签 - return output - elif not isStackingAvailable() and not conf.direct: - warnMsg = "execution of non-query SQL statements is only " - warnMsg += "available when stacked queries are supported" - logger.warning(warnMsg) + if not conf.extensiveFp: # 如果不需要详细指纹信息 + value += DBMS.VERTICA # 将数据库类型添加到指纹信息 + return value # 返回指纹信息 - return None - else: - if sqlType: - infoMsg = "executing %s statement: '%s'" % (sqlType if sqlType is not None else "SQL", query) - else: - infoMsg = "executing unknown SQL command: '%s'" % query - logger.info(infoMsg) + actVer = Format.getDbms() # 获取数据库类型 + blank = " " * 15 # 定义缩进空格 + value += "active fingerprint: %s" % actVer # 添加当前指纹信息 - inject.goStacked(query) + if kb.bannerFp: # 如果存在数据库 banner 信息 + banVer = kb.bannerFp.get("dbmsVersion") # 获取数据库版本信息 - output = NULL + if banVer: + banVer = Format.getDbms([banVer]) # 格式化数据库版本信息 + value += "\ +%sbanner parsing fingerprint: %s" % (blank, banVer) # 将 banner 版本信息添加到指纹信息 - except SqlmapNoneDataException as ex: - logger.warning(ex) - - return output - - def sqlShell(self): - infoMsg = "calling %s shell. To quit type " % Backend.getIdentifiedDbms() - infoMsg += "'x' or 'q' and press ENTER" - logger.info(infoMsg) + htmlErrorFp = Format.getErrorParsedDBMSes() # 获取 HTML 错误信息中的数据库信息 - autoCompletion(AUTOCOMPLETE_TYPE.SQL) + if htmlErrorFp: + value += "\ +%shtml error message fingerprint: %s" % (blank, htmlErrorFp) # 将 HTML 错误信息中的数据库信息添加到指纹信息 - while True: - query = None + return value # 返回指纹信息 - try: - query = _input("sql-shell> ") - query = getUnicode(query, encoding=sys.stdin.encoding) - query = query.strip("; ") - except UnicodeDecodeError: - print() - errMsg = "invalid user input" - logger.error(errMsg) - except KeyboardInterrupt: - print() - errMsg = "user aborted" - logger.error(errMsg) - except EOFError: - print() - errMsg = "exit" - logger.error(errMsg) - break + # 定义 checkDbms 方法,用于检查数据库类型是否为 Vertica + def checkDbms(self): + if not conf.extensiveFp and Backend.isDbmsWithin(VERTICA_ALIASES): # 如果不需要详细指纹并且数据库别名匹配 + setDbms(DBMS.VERTICA) # 设置数据库类型为 Vertica + self.getBanner() # 获取数据库 banner 信息 + return True # 返回 True - if not query: - continue - - if query.lower() in ("x", "q", "exit", "quit"): - break - - output = self.sqlQuery(query) + infoMsg = "testing %s" % DBMS.VERTICA # 输出正在测试 Vertica 的信息 + logger.info(infoMsg) - if output and output != "Quit": - conf.dumper.sqlQuery(query, output) + # NOTE: Vertica works too without the CONVERT_TO() + result = inject.checkBooleanExpression("BITSTRING_TO_BINARY(NULL) IS NULL") # 使用 SQL 注入检查 - elif not output: - pass + if result: # 如果检查结果为 True + infoMsg = "confirming %s" % DBMS.VERTICA # 输出确认是 Vertica 的信息 + logger.info(infoMsg) - elif output != "Quit": - dataToStdout("No output\n") + result = inject.checkBooleanExpression("HEX_TO_INTEGER(NULL) IS NULL") # 使用 SQL 注入检查 - def sqlFile(self): - infoMsg = "executing SQL statements from given file(s)" - logger.info(infoMsg) + if not result: # 如果检查结果为 False + warnMsg = "the back-end DBMS is not %s" % DBMS.VERTICA # 输出警告信息 + logger.warning(warnMsg) + return False # 返回 False - for filename in re.split(PARAMETER_SPLITTING_REGEX, conf.sqlFile): - filename = filename.strip() + setDbms(DBMS.VERTICA) # 设置数据库类型为 Vertica + self.getBanner() # 获取数据库 banner 信息 - if not filename: - continue + if not conf.extensiveFp: # 如果不需要详细指纹信息 + return True # 返回 True - snippet = getSQLSnippet(Backend.getDbms(), filename) + infoMsg = "actively fingerprinting %s" % DBMS.VERTICA # 输出正在进行详细指纹识别的信息 + logger.info(infoMsg) - if snippet and all(query.strip().upper().startswith("SELECT") for query in (_ for _ in snippet.split(';' if ';' in snippet else '\n') if _)): - for query in (_ for _ in snippet.split(';' if ';' in snippet else '\n') if _): - query = query.strip() - if query: - conf.dumper.sqlQuery(query, self.sqlQuery(query)) + # 根据 CALENDAR_HIERARCHY_DAY(NULL) 的结果判断 Vertica 版本 + if inject.checkBooleanExpression("CALENDAR_HIERARCHY_DAY(NULL) IS NULL"): + Backend.setVersion(">= 9.0") # 设置数据库版本为 >= 9.0 else: - conf.dumper.sqlQuery(snippet, self.sqlQuery(snippet)) + Backend.setVersion("< 9.0") # 设置数据库版本为 < 9.0 + + return True # 返回 True + else: # 如果检查结果为 False + warnMsg = "the back-end DBMS is not %s" % DBMS.VERTICA # 输出警告信息 + logger.warning(warnMsg) + return False # 返回 False \ No newline at end of file diff --git a/src/sqlmap-master/plugins/generic/misc.py b/src/sqlmap-master/plugins/generic/misc.py index 7eb710b..ccc5c44 100644 --- a/src/sqlmap-master/plugins/generic/misc.py +++ b/src/sqlmap-master/plugins/generic/misc.py @@ -5,200 +5,211 @@ Copyright (c) 2006-2024 sqlmap developers (https://sqlmap.org/) See the file 'LICENSE' for copying permission """ -import ntpath -import re - -from lib.core.common import Backend -from lib.core.common import hashDBWrite -from lib.core.common import isStackingAvailable -from lib.core.common import normalizePath -from lib.core.common import ntToPosixSlashes -from lib.core.common import posixToNtSlashes -from lib.core.common import readInput -from lib.core.common import singleTimeDebugMessage -from lib.core.common import unArrayizeValue -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.enums import DBMS -from lib.core.enums import HASHDB_KEYS -from lib.core.enums import OS -from lib.core.exception import SqlmapNoneDataException -from lib.request import inject - +# 导入必要的模块 +import ntpath # 导入 ntpath 模块,用于处理 Windows 路径 +import re # 导入 re 模块,用于正则表达式 + +from lib.core.common import Backend # 导入 Backend 类,用于访问后端数据库信息 +from lib.core.common import hashDBWrite # 导入 hashDBWrite 函数,用于写入哈希数据库 +from lib.core.common import isStackingAvailable # 导入 isStackingAvailable 函数,用于检查是否支持堆叠查询 +from lib.core.common import normalizePath # 导入 normalizePath 函数,用于规范化路径 +from lib.core.common import ntToPosixSlashes # 导入 ntToPosixSlashes 函数,用于将 Windows 路径转换为 POSIX 路径 +from lib.core.common import posixToNtSlashes # 导入 posixToNtSlashes 函数,用于将 POSIX 路径转换为 Windows 路径 +from lib.core.common import readInput # 导入 readInput 函数,用于读取用户输入 +from lib.core.common import singleTimeDebugMessage # 导入 singleTimeDebugMessage 函数,用于输出单次调试信息 +from lib.core.common import unArrayizeValue # 导入 unArrayizeValue 函数,用于将数组值转换为单个值 +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 queries # 导入 queries 字典,存储数据库查询语句 +from lib.core.enums import DBMS # 导入 DBMS 枚举,定义数据库管理系统类型 +from lib.core.enums import HASHDB_KEYS # 导入 HASHDB_KEYS 枚举,定义哈希数据库键值 +from lib.core.enums import OS # 导入 OS 枚举,定义操作系统类型 +from lib.core.exception import SqlmapNoneDataException # 导入 SqlmapNoneDataException 异常类 +from lib.request import inject # 导入 inject 函数,用于执行 SQL 注入请求 + +# 定义 Miscellaneous 类,用于实现杂项功能 class Miscellaneous(object): """ This class defines miscellaneous functionalities for plugins. """ + # 初始化 Miscellaneous 类 def __init__(self): pass + # 定义 getRemoteTempPath 方法,用于获取远程临时路径 def getRemoteTempPath(self): - if not conf.tmpPath and Backend.isDbms(DBMS.MSSQL): - debugMsg = "identifying Microsoft SQL Server error log directory " + if not conf.tmpPath and Backend.isDbms(DBMS.MSSQL): # 如果没有设置临时路径且数据库是 MSSQL + debugMsg = "identifying Microsoft SQL Server error log directory " # 输出调试信息 debugMsg += "that sqlmap will use to store temporary files with " debugMsg += "commands' output" logger.debug(debugMsg) - _ = unArrayizeValue(inject.getValue("SELECT SERVERPROPERTY('ErrorLogFileName')", safeCharEncode=False)) + _ = unArrayizeValue(inject.getValue("SELECT SERVERPROPERTY('ErrorLogFileName')", safeCharEncode=False)) # 获取错误日志文件路径 - if _: - conf.tmpPath = ntpath.dirname(_) + if _: # 如果获取到路径 + conf.tmpPath = ntpath.dirname(_) # 设置临时路径为错误日志文件所在的目录 - if not conf.tmpPath: - if Backend.isOs(OS.WINDOWS): - if conf.direct: - conf.tmpPath = "%TEMP%" + if not conf.tmpPath: # 如果没有设置临时路径 + if Backend.isOs(OS.WINDOWS): # 如果操作系统是 Windows + if conf.direct: # 如果是直接连接 + conf.tmpPath = "%TEMP%" # 设置临时路径为 %TEMP% else: - self.checkDbmsOs(detailed=True) + self.checkDbmsOs(detailed=True) # 检测数据库操作系统 - if Backend.getOsVersion() in ("2000", "NT"): - conf.tmpPath = "C:/WINNT/Temp" - elif Backend.isOs("XP"): - conf.tmpPath = "C:/Documents and Settings/All Users/Application Data/Temp" - else: - conf.tmpPath = "C:/Windows/Temp" - else: - conf.tmpPath = "/tmp" + if Backend.getOsVersion() in ("2000", "NT"): # 如果是 Windows 2000 或 NT + conf.tmpPath = "C:/WINNT/Temp" # 设置临时路径 + elif Backend.isOs("XP"): # 如果是 Windows XP + conf.tmpPath = "C:/Documents and Settings/All Users/Application Data/Temp" # 设置临时路径 + else: # 如果是其他 Windows 版本 + conf.tmpPath = "C:/Windows/Temp" # 设置临时路径 + else: # 如果操作系统不是 Windows + conf.tmpPath = "/tmp" # 设置临时路径为 /tmp - if re.search(r"\A[\w]:[\/\\]+", conf.tmpPath, re.I): - Backend.setOs(OS.WINDOWS) + if re.search(r"\A[\w]:[\/\$$+", conf.tmpPath, re.I): # 如果临时路径是 Windows 格式 + Backend.setOs(OS.WINDOWS) # 设置操作系统为 Windows - conf.tmpPath = normalizePath(conf.tmpPath) - conf.tmpPath = ntToPosixSlashes(conf.tmpPath) + conf.tmpPath = normalizePath(conf.tmpPath) # 规范化临时路径 + conf.tmpPath = ntToPosixSlashes(conf.tmpPath) # 将临时路径转换为 POSIX 格式 - singleTimeDebugMessage("going to use '%s' as temporary files directory" % conf.tmpPath) + singleTimeDebugMessage("going to use '%s' as temporary files directory" % conf.tmpPath) # 输出调试信息 - hashDBWrite(HASHDB_KEYS.CONF_TMP_PATH, conf.tmpPath) + hashDBWrite(HASHDB_KEYS.CONF_TMP_PATH, conf.tmpPath) # 写入哈希数据库 - return conf.tmpPath + return conf.tmpPath # 返回临时路径 + # 定义 getVersionFromBanner 方法,用于从 banner 中获取数据库版本 def getVersionFromBanner(self): - if "dbmsVersion" in kb.bannerFp: - return + if "dbmsVersion" in kb.bannerFp: # 如果 banner 中已经有版本信息 + return # 直接返回 - infoMsg = "detecting back-end DBMS version from its banner" + infoMsg = "detecting back-end DBMS version from its banner" # 输出信息 logger.info(infoMsg) - query = queries[Backend.getIdentifiedDbms()].banner.query + query = queries[Backend.getIdentifiedDbms()].banner.query # 获取 banner 查询语句 - if conf.direct: - query = "SELECT %s" % query + if conf.direct: # 如果是直接连接 + query = "SELECT %s" % query # 添加 SELECT 关键字 - kb.bannerFp["dbmsVersion"] = unArrayizeValue(inject.getValue(query)) or "" + kb.bannerFp["dbmsVersion"] = unArrayizeValue(inject.getValue(query)) or "" # 获取 banner 信息 - match = re.search(r"\d[\d.-]*", kb.bannerFp["dbmsVersion"]) - if match: - kb.bannerFp["dbmsVersion"] = match.group(0) + match = re.search(r"\d[\d.-]*", kb.bannerFp["dbmsVersion"]) # 使用正则表达式匹配版本号 + if match: # 如果匹配成功 + kb.bannerFp["dbmsVersion"] = match.group(0) # 设置版本号 + # 定义 delRemoteFile 方法,用于删除远程文件 def delRemoteFile(self, filename): - if not filename: - return + if not filename: # 如果文件名为空 + return # 直接返回 - self.checkDbmsOs() + self.checkDbmsOs() # 检测数据库操作系统 - if Backend.isOs(OS.WINDOWS): - filename = posixToNtSlashes(filename) - cmd = "del /F /Q %s" % filename - else: - cmd = "rm -f %s" % filename + if Backend.isOs(OS.WINDOWS): # 如果操作系统是 Windows + filename = posixToNtSlashes(filename) # 将路径转换为 Windows 格式 + cmd = "del /F /Q %s" % filename # 构建删除命令 + else: # 如果操作系统不是 Windows + cmd = "rm -f %s" % filename # 构建删除命令 - self.execCmd(cmd, silent=True) + self.execCmd(cmd, silent=True) # 执行删除命令 + # 定义 createSupportTbl 方法,用于创建支持表 def createSupportTbl(self, tblName, tblField, tblType): - inject.goStacked("DROP TABLE %s" % tblName, silent=True) + inject.goStacked("DROP TABLE %s" % tblName, silent=True) # 删除表(如果存在) - if Backend.isDbms(DBMS.MSSQL) and tblName == self.cmdTblName: - inject.goStacked("CREATE TABLE %s(id INT PRIMARY KEY IDENTITY, %s %s)" % (tblName, tblField, tblType)) - else: - inject.goStacked("CREATE TABLE %s(%s %s)" % (tblName, tblField, tblType)) + if Backend.isDbms(DBMS.MSSQL) and tblName == self.cmdTblName: # 如果是 MSSQL 并且表名是命令表 + inject.goStacked("CREATE TABLE %s(id INT PRIMARY KEY IDENTITY, %s %s)" % (tblName, tblField, tblType)) # 创建表,包含自增 id + else: # 如果不是 MSSQL 或表名不是命令表 + inject.goStacked("CREATE TABLE %s(%s %s)" % (tblName, tblField, tblType)) # 创建表 + # 定义 cleanup 方法,用于清理文件系统和数据库 def cleanup(self, onlyFileTbl=False, udfDict=None, web=False): """ Cleanup file system and database from sqlmap create files, tables and functions """ - if web and self.webBackdoorFilePath: - logger.info("cleaning up the web files uploaded") + if web and self.webBackdoorFilePath: # 如果是 web 模式且有 web 后门文件路径 + logger.info("cleaning up the web files uploaded") # 输出信息 - self.delRemoteFile(self.webStagerFilePath) - self.delRemoteFile(self.webBackdoorFilePath) + self.delRemoteFile(self.webStagerFilePath) # 删除 web stager 文件 + self.delRemoteFile(self.webBackdoorFilePath) # 删除 web 后门文件 - if (not isStackingAvailable() or kb.udfFail) and not conf.direct: - return + if (not isStackingAvailable() or kb.udfFail) and not conf.direct: # 如果不支持堆叠查询或 udf失败且不是直接连接 + return # 直接返回 - if any((conf.osCmd, conf.osShell)) and Backend.isDbms(DBMS.PGSQL) and kb.copyExecTest: - return + if any((conf.osCmd, conf.osShell)) and Backend.isDbms(DBMS.PGSQL) and kb.copyExecTest: # 如果执行系统命令/shell 且是 PostgreSQL 且 copyExecTest 为 True + return # 直接返回 - if Backend.isOs(OS.WINDOWS): - libtype = "dynamic-link library" + if Backend.isOs(OS.WINDOWS): # 如果操作系统是 Windows + libtype = "dynamic-link library" # 设置库类型为动态链接库 - elif Backend.isOs(OS.LINUX): - libtype = "shared object" + elif Backend.isOs(OS.LINUX): # 如果操作系统是 Linux + libtype = "shared object" # 设置库类型为共享对象 - else: - libtype = "shared library" + else: # 如果是其他操作系统 + libtype = "shared library" # 设置库类型为共享库 - if onlyFileTbl: - logger.debug("cleaning up the database management system") - else: - logger.info("cleaning up the database management system") + if onlyFileTbl: # 如果只清理文件表 + logger.debug("cleaning up the database management system") # 输出调试信息 + else: # 如果清理所有 + logger.info("cleaning up the database management system") # 输出信息 - logger.debug("removing support tables") - inject.goStacked("DROP TABLE %s" % self.fileTblName, silent=True) - inject.goStacked("DROP TABLE %shex" % self.fileTblName, silent=True) + logger.debug("removing support tables") # 输出调试信息 + inject.goStacked("DROP TABLE %s" % self.fileTblName, silent=True) # 删除文件表 + inject.goStacked("DROP TABLE %shex" % self.fileTblName, silent=True) # 删除文件表 (hex) - if not onlyFileTbl: - inject.goStacked("DROP TABLE %s" % self.cmdTblName, silent=True) + if not onlyFileTbl: # 如果不是只清理文件表 + inject.goStacked("DROP TABLE %s" % self.cmdTblName, silent=True) # 删除命令表 - if Backend.isDbms(DBMS.MSSQL): - udfDict = {"master..new_xp_cmdshell": {}} + if Backend.isDbms(DBMS.MSSQL): # 如果是 MSSQL + udfDict = {"master..new_xp_cmdshell": {}} # 设置要删除的 udf (xp_cmdshell) - if udfDict is None: - udfDict = getattr(self, "sysUdfs", {}) + if udfDict is None: # 如果 udfDict 为空 + udfDict = getattr(self, "sysUdfs", {}) # 获取系统 udf - for udf, inpRet in udfDict.items(): - message = "do you want to remove UDF '%s'? [Y/n] " % udf + for udf, inpRet in udfDict.items(): # 遍历 udf + message = "do you want to remove UDF '%s'? [Y/n] " % udf # 输出询问信息 - if readInput(message, default='Y', boolean=True): - dropStr = "DROP FUNCTION %s" % udf + if readInput(message, default='Y', boolean=True): # 获取用户输入 + dropStr = "DROP FUNCTION %s" % udf # 构建删除 udf 命令 - if Backend.isDbms(DBMS.PGSQL): - inp = ", ".join(i for i in inpRet["input"]) - dropStr += "(%s)" % inp + if Backend.isDbms(DBMS.PGSQL): # 如果是 PostgreSQL + inp = ", ".join(i for i in inpRet["input"]) # 获取输入参数 + dropStr += "(%s)" % inp # 添加输入参数到删除命令 - logger.debug("removing UDF '%s'" % udf) - inject.goStacked(dropStr, silent=True) + logger.debug("removing UDF '%s'" % udf) # 输出调试信息 + inject.goStacked(dropStr, silent=True) # 删除 udf - logger.info("database management system cleanup finished") + logger.info("database management system cleanup finished") # 输出信息 - warnMsg = "remember that UDF %s files " % libtype + warnMsg = "remember that UDF %s files " % libtype # 构建警告信息 - if conf.osPwn: - warnMsg += "and Metasploit related files in the temporary " + if conf.osPwn: # 如果开启 osPwn 功能 + warnMsg += "and Metasploit related files in the temporary " # 添加 Metasploit 相关文件信息 warnMsg += "folder " - warnMsg += "saved on the file system can only be deleted " + warnMsg += "saved on the file system can only be deleted " # 添加手动删除信息 warnMsg += "manually" - logger.warning(warnMsg) + logger.warning(warnMsg) # 输出警告信息 + # 定义 likeOrExact 方法,用于选择 LIKE 或精确匹配 def likeOrExact(self, what): - message = "do you want sqlmap to consider provided %s(s):\n" % what - message += "[1] as LIKE %s names (default)\n" % what + message = "do you want sqlmap to consider provided %s(s):\ +" % what # 构建询问信息 + message += "[1] as LIKE %s names (default)\ +" % what message += "[2] as exact %s names" % what - choice = readInput(message, default='1') + choice = readInput(message, default='1') # 获取用户选择 - if not choice or choice == '1': + if not choice or choice == '1': # 如果选择 LIKE 匹配 choice = '1' - condParam = " LIKE '%%%s%%'" - elif choice == '2': - condParam = "='%s'" - else: - errMsg = "invalid value" - raise SqlmapNoneDataException(errMsg) - - return choice, condParam + condParam = " LIKE '%%%s%%'" # 设置 LIKE 条件 + elif choice == '2': # 如果选择精确匹配 + condParam = "='%s'" # 设置精确匹配条件 + else: # 如果输入非法 + errMsg = "invalid value" # 输出错误信息 + raise SqlmapNoneDataException(errMsg) # 抛出异常 + + return choice, condParam # 返回选择和条件 \ No newline at end of file