|
|
|
@ -5,31 +5,45 @@ Copyright (c) 2006-2024 sqlmap developers (https://sqlmap.org/)
|
|
|
|
|
See the file 'LICENSE' for copying permission
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
# ... 导入相关模块 ...
|
|
|
|
|
import re
|
|
|
|
|
|
|
|
|
|
from xml.sax.handler import ContentHandler
|
|
|
|
|
|
|
|
|
|
from lib.core.common import Backend
|
|
|
|
|
from lib.core.common import parseXmlFile
|
|
|
|
|
from lib.core.common import sanitizeStr
|
|
|
|
|
from lib.core.data import kb
|
|
|
|
|
from lib.core.data import paths
|
|
|
|
|
from lib.core.enums import DBMS
|
|
|
|
|
from lib.parse.handler import FingerprintHandler
|
|
|
|
|
|
|
|
|
|
class MSSQLBannerHandler(ContentHandler):
|
|
|
|
|
"""
|
|
|
|
|
该类用于解析和提取Microsoft SQL Server banner信息
|
|
|
|
|
基于XML文件中的数据进行匹配和处理
|
|
|
|
|
This class defines methods to parse and extract information from the
|
|
|
|
|
given Microsoft SQL Server banner based upon the data in XML file
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
def __init__(self, banner, info):
|
|
|
|
|
ContentHandler.__init__(self)
|
|
|
|
|
|
|
|
|
|
# 初始化banner信息和状态标志
|
|
|
|
|
self._banner = sanitizeStr(banner or "") # 清理并存储banner字符串
|
|
|
|
|
self._inVersion = False # 是否正在处理版本信息的标志
|
|
|
|
|
self._inServicePack = False # 是否正在处理ServicePack信息的标志
|
|
|
|
|
self._release = None # 发布版本信息
|
|
|
|
|
self._version = "" # 版本号
|
|
|
|
|
self._versionAlt = None # 替代版本号格式
|
|
|
|
|
self._servicePack = "" # ServicePack版本
|
|
|
|
|
self._info = info # 存储解析结果的字典
|
|
|
|
|
# 初始化banner
|
|
|
|
|
self._banner = sanitizeStr(banner or "")
|
|
|
|
|
# 初始化是否在version标签中
|
|
|
|
|
self._inVersion = False
|
|
|
|
|
# 初始化是否在servicepack标签中
|
|
|
|
|
self._inServicePack = False
|
|
|
|
|
# 初始化release
|
|
|
|
|
self._release = None
|
|
|
|
|
# 初始化version
|
|
|
|
|
self._version = ""
|
|
|
|
|
# 初始化versionAlt
|
|
|
|
|
self._versionAlt = None
|
|
|
|
|
# 初始化servicePack
|
|
|
|
|
self._servicePack = ""
|
|
|
|
|
# 初始化info
|
|
|
|
|
self._info = info
|
|
|
|
|
|
|
|
|
|
def _feedInfo(self, key, value):
|
|
|
|
|
"""
|
|
|
|
|
将解析到的信息存入结果字典
|
|
|
|
|
"""
|
|
|
|
|
value = sanitizeStr(value)
|
|
|
|
|
|
|
|
|
|
if value in (None, "None"):
|
|
|
|
@ -38,83 +52,91 @@ class MSSQLBannerHandler(ContentHandler):
|
|
|
|
|
self._info[key] = value
|
|
|
|
|
|
|
|
|
|
def startElement(self, name, attrs):
|
|
|
|
|
"""
|
|
|
|
|
处理XML元素开始标签
|
|
|
|
|
"""
|
|
|
|
|
# 如果标签名为signatures,则获取release属性
|
|
|
|
|
if name == "signatures":
|
|
|
|
|
self._release = sanitizeStr(attrs.get("release"))
|
|
|
|
|
|
|
|
|
|
# 如果标签名为version,则设置_inVersion为True
|
|
|
|
|
elif name == "version":
|
|
|
|
|
self._inVersion = True
|
|
|
|
|
|
|
|
|
|
# 如果标签名为servicepack,则设置_inServicePack为True
|
|
|
|
|
elif name == "servicepack":
|
|
|
|
|
self._inServicePack = True
|
|
|
|
|
|
|
|
|
|
def characters(self, content):
|
|
|
|
|
"""
|
|
|
|
|
处理XML元素的文本内容
|
|
|
|
|
"""
|
|
|
|
|
# 如果在version标签中,则将content添加到_version中
|
|
|
|
|
if self._inVersion:
|
|
|
|
|
self._version += sanitizeStr(content)
|
|
|
|
|
# 如果在servicepack标签中,则将content添加到_servicePack中
|
|
|
|
|
elif self._inServicePack:
|
|
|
|
|
self._servicePack += sanitizeStr(content)
|
|
|
|
|
|
|
|
|
|
def endElement(self, name):
|
|
|
|
|
"""
|
|
|
|
|
处理XML元素结束标签
|
|
|
|
|
"""
|
|
|
|
|
# 如果标签名为signature,则进行匹配
|
|
|
|
|
if name == "signature":
|
|
|
|
|
# 检查banner中是否包含匹配的版本信息
|
|
|
|
|
for version in (self._version, self._versionAlt):
|
|
|
|
|
# 如果version不为空,且banner不为空,且banner中包含version,则将release、version、servicePack添加到info中
|
|
|
|
|
if version and self._banner and re.search(r" %s[\.\ ]+" % re.escape(version), self._banner):
|
|
|
|
|
# 找到匹配后,保存相关信息
|
|
|
|
|
self._feedInfo("dbmsRelease", self._release)
|
|
|
|
|
self._feedInfo("dbmsVersion", self._version)
|
|
|
|
|
self._feedInfo("dbmsServicePack", self._servicePack)
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
# 重置临时变量
|
|
|
|
|
# 重置version、versionAlt、servicePack
|
|
|
|
|
self._version = ""
|
|
|
|
|
self._versionAlt = None
|
|
|
|
|
self._servicePack = ""
|
|
|
|
|
|
|
|
|
|
# 如果标签名为version,则将_version中的空格去除,并尝试匹配
|
|
|
|
|
elif name == "version":
|
|
|
|
|
self._inVersion = False
|
|
|
|
|
self._version = self._version.replace(" ", "")
|
|
|
|
|
|
|
|
|
|
# 处理特殊的版本号格式
|
|
|
|
|
# 尝试匹配
|
|
|
|
|
match = re.search(r"\A(?P<major>\d+)\.00\.(?P<build>\d+)\Z", self._version)
|
|
|
|
|
# 如果匹配成功,则将versionAlt设置为"%s.0.%s.0" % (match.group('major'), match.group('build'))
|
|
|
|
|
self._versionAlt = "%s.0.%s.0" % (match.group('major'), match.group('build')) if match else None
|
|
|
|
|
|
|
|
|
|
# 如果标签名为servicepack,则将_servicePack中的空格去除
|
|
|
|
|
elif name == "servicepack":
|
|
|
|
|
self._inServicePack = False
|
|
|
|
|
self._servicePack = self._servicePack.replace(" ", "")
|
|
|
|
|
|
|
|
|
|
def bannerParser(banner):
|
|
|
|
|
"""
|
|
|
|
|
根据不同的数据库类型调用相应的处理器来解析banner信息
|
|
|
|
|
This function calls a class to extract information from the given
|
|
|
|
|
DBMS banner based upon the data in XML file
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
xmlfile = None
|
|
|
|
|
|
|
|
|
|
# 根据数据库类型选择对应的XML配置文件
|
|
|
|
|
# 如果数据库类型为MSSQL,则设置xmlfile为paths.MSSQL_XML
|
|
|
|
|
if Backend.isDbms(DBMS.MSSQL):
|
|
|
|
|
xmlfile = paths.MSSQL_XML
|
|
|
|
|
# 如果数据库类型为MYSQL,则设置xmlfile为paths.MYSQL_XML
|
|
|
|
|
elif Backend.isDbms(DBMS.MYSQL):
|
|
|
|
|
xmlfile = paths.MYSQL_XML
|
|
|
|
|
# 如果数据库类型为ORACLE,则设置xmlfile为paths.ORACLE_XML
|
|
|
|
|
elif Backend.isDbms(DBMS.ORACLE):
|
|
|
|
|
xmlfile = paths.ORACLE_XML
|
|
|
|
|
# 如果数据库类型为PGSQL,则设置xmlfile为paths.PGSQL_XML
|
|
|
|
|
elif Backend.isDbms(DBMS.PGSQL):
|
|
|
|
|
xmlfile = paths.PGSQL_XML
|
|
|
|
|
|
|
|
|
|
# 如果xmlfile为空,则返回
|
|
|
|
|
if not xmlfile:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
# 针对MSSQL使用专门的处理器,其他数据库使用通用处理器
|
|
|
|
|
# 如果数据库类型为MSSQL,则使用MSSQLBannerHandler解析xmlfile,并使用FingerprintHandler解析paths.GENERIC_XML
|
|
|
|
|
if Backend.isDbms(DBMS.MSSQL):
|
|
|
|
|
handler = MSSQLBannerHandler(banner, kb.bannerFp)
|
|
|
|
|
parseXmlFile(xmlfile, handler)
|
|
|
|
|
|
|
|
|
|
handler = FingerprintHandler(banner, kb.bannerFp)
|
|
|
|
|
parseXmlFile(paths.GENERIC_XML, handler)
|
|
|
|
|
# 否则,使用FingerprintHandler解析xmlfile和paths.GENERIC_XML
|
|
|
|
|
else:
|
|
|
|
|
handler = FingerprintHandler(banner, kb.bannerFp)
|
|
|
|
|
parseXmlFile(xmlfile, handler)
|
|
|
|
|
parseXmlFile(paths.GENERIC_XML, handler)
|
|
|
|
|
parseXmlFile(paths.GENERIC_XML, handler)
|
|
|
|
|