Kerberos是一种由MIT(麻省理工大学)提出的一种网络身份验证协议。它旨在通过使用密钥加密技术为客户端/服务器应用程序提供强身份验证。
在kerberos协议之中主要是有三个角色存在:
在一个域林之中,KDC服务默认会安装在域控之中,而client和server是域内的用户或者服务。在kerberos认证过程中client是否有权限访问server的服务就由KDC发放的票据决定
简化的Kerberos认证流程图
名词概念
AD(Account Datebase):账户数据库
Master Key: 用户密码的一种hash值
Ticket(票据):域网络对象相互访问的凭证
TGT(Ticket Granting Ticket 票据授予票据):用于向KDC获取服务票据的凭证
TGS(Silver Ticket 服务票据):用于向Server请求服务的凭证
Authentication Service(身份认证服务):认证Client 的身份,并为其发放TGT的服务,是KDC的一部分
Ticket Granting Service(票据发放服务):检验Client发来的TGT,并为其生成某个Server的TGS,是KDC的一部分。
Kerberos
Record Mark: 294 bytes
0... .... .... .... .... .... .... .... = Reserved: Not set
.000 0000 0000 0000 0000 0001 0010 0110 = Record Length: 294
as-req
pvno: 5
msg-type: krb-as-req (10)
padata: 2 items
PA-DATA PA-ENC-TIMESTAMP
padata-type: kRB5-PADATA-ENC-TIMESTAMP (2)
padata-value: 3041a003020112a23a04384e3857102e1da38ea37695b42c…
etype: eTYPE-AES256-CTS-HMAC-SHA1-96 (18)
cipher: 4e3857102e1da38ea37695b42cc877f2dfbc29a67c6c8f21…
PA-DATA PA-PAC-REQUEST
padata-type: kRB5-PADATA-PA-PAC-REQUEST (128)
padata-value: 3005a0030101ff
include-pac: True
req-body
Padding: 0
kdc-options: 40810010
0... .... = reserved: False
.1.. .... = forwardable: True
..0. .... = forwarded: False
...0 .... = proxiable: False
.... 0... = proxy: False
.... .0.. = allow-postdate: False
.... ..0. = postdated: False
.... ...0 = unused7: False
1... .... = renewable: True
.0.. .... = unused9: False
..0. .... = unused10: False
...0 .... = opt-hardware-auth: False
.... 0... = unused12: False
.... .0.. = unused13: False
.... ..0. = constrained-delegation: False
.... ...1 = canonicalize: True
0... .... = request-anonymous: False
.0.. .... = unused17: False
..0. .... = unused18: False
...0 .... = unused19: False
.... 0... = unused20: False
.... .0.. = unused21: False
.... ..0. = unused22: False
.... ...0 = unused23: False
0... .... = unused24: False
.0.. .... = unused25: False
..0. .... = disable-transited-check: False
...1 .... = renewable-ok: True
.... 0... = enc-tkt-in-skey: False
.... .0.. = unused29: False
.... ..0. = renew: False
.... ...0 = validate: False
cname
name-type: kRB5-NT-PRINCIPAL (1)
cname-string: 1 item
CNameString: testuser
realm: HACKE
sname
name-type: kRB5-NT-SRV-INST (2)
sname-string: 2 items
SNameString: krbtgt
SNameString: HACKE
till: 2037-09-13 02:48:05 (UTC)
rtime: 2037-09-13 02:48:05 (UTC)
nonce: 19228112
etype: 6 items
ENCTYPE: eTYPE-AES256-CTS-HMAC-SHA1-96 (18)
ENCTYPE: eTYPE-AES128-CTS-HMAC-SHA1-96 (17)
ENCTYPE: eTYPE-ARCFOUR-HMAC-MD5 (23)
ENCTYPE: eTYPE-ARCFOUR-HMAC-MD5-56 (24)
ENCTYPE: eTYPE-ARCFOUR-HMAC-OLD-EXP (-135)
ENCTYPE: eTYPE-DES-CBC-MD5 (3)
addresses: 1 item WIN10-X64-TEST<20>
HostAddress WIN10-X64-TEST<20>
addr-type: nETBIOS (20)
NetBIOS Name: WIN10-X64-TEST<20> (Server service)
kerberos版本号
windows消息类型,AS_REQ的自然是krb-as-req
是一些认证信息,是一个列表,内部有若干个认证消息,每一个认证消息有type和value。
具体可看:Kerberos PA-DATA
req-body
这是一些KDC的option开启情况,属于一种标识位。 mit文档
这是Client的主机名,采用的是PrincipalName 类型和string类型的组合。sname也是采用这种格式
PrincipalName 类型
KRB_NT_PRINCIPAL 用户主体名称类型
KRB_NT_SRV-INST 服务和其他唯一实例(krbtgt)的名称类型
KRB_NT_SRV_HST 服务主机名称为实例名的名称类型
KRB_NT_SRV_XHST 服务与主机作为剩余组件名称类型
KRB_NT_UID 唯一ID名称类型
KRB_NT_UNKNOWN 未知名称类型
服务端域名
这是是服务端的身份和所属域,注意在AS_REQ中服务端指的是提供AS的KDC,所以正常的sname-string字段的值就应该是krbtgt和其所属域.
到期时间
加密类型,在请求报文之中每个有加密的数据都有一个etype字段对应,KDC就是从这段数据中加密方式,来从AD之中选择对应的hash来进行身份验证
地址相关信息@
两个重要的padata(pre-authentication data 预认证数据)
PA-ENC-TIMESTAMP
这个预认证数据是Client用自己的
Master key
加密时间戳得到的一串字符, AS拿到这个段数据之后就会根据etype去AD里面寻找对应的用户hash(用户名取自cname),并使用这个hash解密时间戳, 如果解密成功, 并且时间戳在一定范围之内,则这个预认证数据通过.PA-PAC-REQUEST
这个预认证数据是关于微软的一个扩展---PAC, 这个扩展的基本作用就是为kerberos添加"权限认证"的能力. 开启这项扩展,AS完成时间戳的认证之后就会将PAC(内部包涵Client的sid和所在组)放TGT的认证数据之中, 一起返回给Client, PAC关系到之后Server判断Client是否有权限访问服务
拆解数据包
Kerberos
Record Mark: 1550 bytes
0... .... .... .... .... .... .... .... = Reserved: Not set
.000 0000 0000 0000 0000 0110 0000 1110 = Record Length: 1550
as-rep
pvno: 5
msg-type: krb-as-rep (11)
padata: 1 item
PA-DATA PA-ENCTYPE-INFO2
padata-type: kRB5-PADATA-ETYPE-INFO2 (19)
padata-value: 3020301ea003020112a1171b154841434b452e544553544c…
ETYPE-INFO2-ENTRY
etype: eTYPE-AES256-CTS-HMAC-SHA1-96 (18)
salt: HACKE.TESTLABtestuser
crealm: HACKE.TESTLAB
cname
name-type: kRB5-NT-PRINCIPAL (1)
cname-string: 1 item
CNameString: testuser
ticket
tkt-vno: 5
realm: HACKE.TESTLAB
sname
name-type: kRB5-NT-SRV-INST (2)
sname-string: 2 items
SNameString: krbtgt
SNameString: HACKE.TESTLAB
enc-part
etype: eTYPE-AES256-CTS-HMAC-SHA1-96 (18)
kvno: 2
cipher: 07b5d35de5b1ac006b831ff508a5ced14a010563418fd736…
enc-part
etype: eTYPE-AES256-CTS-HMAC-SHA1-96 (18)
kvno: 4
cipher: 70246fe54be2b6395f20dc6845b970d16bb3319ab304e3bb…
主要关注与AS_REQ不同的点
ticket
这就是AS派发的TGT票据,内部所有密文的密钥都是krbtgt
的NTLM hash
,如果能拿到krbtgt
的NTLM hash
我们既可以伪造TGT,这就是黄金票据
tkt-vno
票据版本
realm
派发票据的KDC的所属域
sname
派发票据的角色再KDC的身份,一般是kbrtgt
enc-part
使用kbrtgt
的NTLM hash
作为密钥生成的TGT主体
enc-part
这部分是使用Client的hash为key加密Session key
得到的,主要用于作为下阶段(TGS阶段)的认证密钥。
在AS认证截断,用户名存在和密码错误的响应报文错误码不同,
用户名不存在的响应错误码是6:KDC_ERR_C_PRINCIPAL_UNKNOWN 未知的主机名
密码错误,用户名存在的响应错误码是24:KDC_ERR_PREAUTH_PAILED 预认证失败
通过这个比较AS_REP里的错误码就可实行 用户名枚举 .
AS_ERP里的tikcet的encpart是使用kbrtgt
的NTLM hash
为key
加密而成的,所以只要拿到了kbrtgt
的NTLM hash
就可以伪造TGT,这个伪造出来的票据就叫做 黄金票据
拆解数据包
Frame 40: 62 bytes on wire (496 bits), 62 bytes captured (496 bits) on interface \Device\NPF_{FBDB2B2D-DEF3-473C-87EF-787E4B606694}, id 0
Ethernet II, Src: VMware_f0:d8:2b (00:0c:29:f0:d8:2b), Dst: VMware_e6:ab:e6 (00:0c:29:e6:ab:e6)
Internet Protocol Version 4, Src: 192.168.1.2, Dst: 192.168.1.1
Transmission Control Protocol, Src Port: 49731, Dst Port: 88, Seq: 1461, Ack: 1, Len: 8
[2 Reassembled TCP Segments (1468 bytes): #39(1460), #40(8)]
Kerberos
Record Mark: 1464 bytes
tgs-req
pvno: 5
msg-type: krb-tgs-req (12)
padata: 2 items
PA-DATA PA-TGS-REQ
padata-type: kRB5-PADATA-TGS-REQ (1)
padata-value: 6e8204f4308204f0a003020105a10302010ea20703050000…
PA-DATA PA-PAC-OPTIONS
padata-type: kRB5-PADATA-PAC-OPTIONS (167)
padata-value: 3009a00703050040000000
req-body
Padding: 0
kdc-options: 40810000
0... .... = reserved: False
.1.. .... = forwardable: True
..0. .... = forwarded: False
...0 .... = proxiable: False
.... 0... = proxy: False
.... .0.. = allow-postdate: False
.... ..0. = postdated: False
.... ...0 = unused7: False
1... .... = renewable: True
.0.. .... = unused9: False
..0. .... = unused10: False
...0 .... = opt-hardware-auth: False
.... 0... = unused12: False
.... .0.. = unused13: False
.... ..0. = constrained-delegation: False
.... ...1 = canonicalize: True
0... .... = request-anonymous: False
.0.. .... = unused17: False
..0. .... = unused18: False
...0 .... = unused19: False
.... 0... = unused20: False
.... .0.. = unused21: False
.... ..0. = unused22: False
.... ...0 = unused23: False
0... .... = unused24: False
.0.. .... = unused25: False
..0. .... = disable-transited-check: False
...0 .... = renewable-ok: False
.... 0... = enc-tkt-in-skey: False
.... .0.. = unused29: False
.... ..0. = renew: False
.... ...0 = validate: False
realm: HACKE.TESTLAB
sname
name-type: kRB5-NT-SRV-HST (3)
sname-string: 2 items
SNameString: host
SNameString: win10-x64-test.hacke.testlab
till: 2037-09-13 02:48:05 (UTC)
nonce: 19595592
etype: 5 items
ENCTYPE: eTYPE-AES256-CTS-HMAC-SHA1-96 (18)
ENCTYPE: eTYPE-AES128-CTS-HMAC-SHA1-96 (17)
ENCTYPE: eTYPE-ARCFOUR-HMAC-MD5 (23)
ENCTYPE: eTYPE-ARCFOUR-HMAC-MD5-56 (24)
ENCTYPE: eTYPE-ARCFOUR-HMAC-OLD-EXP (-135)
msg-type
windows消息格式,krb-tgs-req
padata
这部分携带了TGS_REQ最重要的数据—TGT票据,TGT票据以ap-req的形式存放在数据包之中。KDC会校验TGT,如果正确就返回TGS票据
这部分数据和还包含PAC和S4U2SELF,这个之后其他文章单独说
req-body
格式和之前的请求报文基本一致,只是这里的sname换成了Client想要请求服务的Server的名字
数据包拆解
Kerberos
Record Mark: 1495 bytes
0... .... .... .... .... .... .... .... = Reserved: Not set
.000 0000 0000 0000 0000 0101 1101 0111 = Record Length: 1495
tgs-rep
pvno: 5
msg-type: krb-tgs-rep (13)
crealm: HACKE.TESTLAB
cname
name-type: kRB5-NT-PRINCIPAL (1)
cname-string: 1 item
CNameString: testuser
ticket
tkt-vno: 5
realm: HACKE.TESTLAB
sname
name-type: kRB5-NT-SRV-HST (3)
sname-string: 2 items
SNameString: host
SNameString: win10-x64-test.hacke.testlab
enc-part
etype: eTYPE-AES256-CTS-HMAC-SHA1-96 (18)
kvno: 1
cipher: 1fc40f7b907bea22e5606abf4f0575c113b8f5ee8d87ce4f…
enc-part
etype: eTYPE-AES256-CTS-HMAC-SHA1-96 (18)
cipher: e4705cfafb271944be50c33f4576bb4b4e449357fbdbb18f…
msg-type
windows消息格式,krb-tgs-rep
crealm
Client所属域
cname
Client的身份名
ticket
这就是最终的票据,是使用Client请求服务的Server的hash作为key来加密得到的。内部包含:Server session key
、Client info (Domain name\client)
、end time (到期时间)
enc-part
这一部分是使用AS认证中得Session key
为key加密成得内部有Server session key
,主要用于下轮用户认证(AP阶段)
# NTML协议
windows内部是不保存明文密码的,只保存密码的hash值
本机的用户密码hash是放在本地的SAM文件里面,域内用户的密码hash存在域控的NTDS.DIT文件的。
windows密码hash保存模式,类似如下
Administrator:500:AAD3B435B51404EEAAD3B435B51404EE:31D6CFE0D16AE931B73C59D7E0C089C0:::
AAD3B435B51404EEAAD3B435B51404EE
是LM hash
31D6CFE0D16AE931B73C59D7E0C089C0
是NTML hash
LM Hash 的算法
KGS!@#$%
进行DES加密。LM Hash的一些弊端
aad3b435b51404ee
,那么就意味着,这个密码的长度是小于等于7位的,密码强度大大减少NTLM hash 的算法
NTLM hash本地的认证
当用户注销、重启、锁屏之后,windows会让winlogon显示登陆界面,接收用户的输入之后,会将将密码交付给lsass进程,这个进程会将明文密码加密成NTLM hash,再与SAM数据库里对应的用户密码做对比。
winlogon(Windows logon process)windows注册进程:是windows NT 用户的登陆程序,用于管理用户的登陆与退出
lsass( Local Security Authority Service): 用于本地安全与登陆策略
- SAM(Security Account Manager 安全账户管理):windows采用的账户管理策略,这个策略会将本地组的用户的账户和hash加密之后保存到SAM数据库中,SAM数据库文件路径是
%systemroot%\system32\config\SAM
文件
NTLM 身份验证采用的是 Challenge(挑战)/Response(响应)
验证机制,有三步组成:协商,质询,身份验证
客户机与服务器的交互过程示意图(域控不参加的情况)
challenge
NTMLM hash
和质询 中的challenge
进行加密运算得到response,然后将response、用户名、challenge一起返回给Server关于challenge:服务端生成的一个随机字符用于验证Client的身份,NTLM v1中为8位,NTLM v2中为16位
关于Net-NTML hash:基于用户hash经过一定算法产生的。
关于response:本质上就是一个
net-NTLM hash