代码批注

wangshenghui_new_branch
Warmlight 1 month ago
parent 97d70fe02a
commit 138eb2afc6

@ -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) # 比较集合内容

@ -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) # 清理支持表

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

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

@ -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 # 返回选择和条件
Loading…
Cancel
Save