0%

NTLM与Kerberos

 有关Windows下域内认证协议的学习笔记.

NTLM

 NTML协议是Windows的早期认证方式, 为保证后向兼容而保留. 可以用于域内认证和工作组认证. 主要分为本地认证和网络认证两种方式.

加密流程

1
2
3
--------      ---------      ------------     ---------
|Passwd| ---->|hex 编码|---->|Unicode编码|---->|计算MD4|
-------- --------- ------------ ---------

本地认证

 我们的密码不会明文保存在Windows中, Windows会在设置密码时把密码加密成NTLM Hash后储存在SAM文件中, 一般路径为system32/config/SAM.
 NTLM的本地认证发生在用户登录的过程中. 当我们登录系统的时候, Windows会调用winlogon.exe来接受密码输入, 之后密码会传递给lasaa.exe. 该进程会先在内存中保存一份明文密码, 再把明文密码加密为NTLM Hash后与SAM数据库中的对应Hash进行对比, 如果比对成功则登录成功.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
----------
|PassWord|
----------

输入

--------------
|winlogon.exe|
--------------

传递给lsass

----------- 保存一份明文 ------
|lsass.exe| --------------> |内存|
----------- ------

计算NTML Hash, 比对

---------- 比对失败 --------
|SAM数据库|-------->|登录失败|
---------- --------

比对成功, 发送User Sid与Group Sid给winlogon,
准备登录界面

--------------
|winlogon.exe|
--------------

网络认证

 在域环境中需要进行网络认证, 虽然一般使用的都是Kerberos协议, 但是NTLM协议也可以用于认证. 一般基于挑战应答机制.

  1. 用户在客户端C输入账号和密码, C缓存NTLM Hash, 并明文发送用户名到服务端S
  2. S生成随机的16字节挑战字符串t, 明文发送给C
  3. C接收到t后, 使用NTLM Hash对t进行加密, 生成响应r并发送到S
  4. S接收到r后, 将第一步发来的用户名, 挑战字符串t, 响应r一并发给域控(DC)
  5. DC在本地数据库中找到用户名对应的NTLM Hash, 对发来的t进行加密, 如果加密结果r1===r, 则认为认证成功, 将认证结果返回给服务端S

 在整个挑战-应答机制中, 密码和NTLM Hash并没有在网络上进行传递. 同时为了提高安全性, DC中也不会储存用户的明文密码. 由此, 如果攻击者能够获取用户的NTLM Hash, 则也不需要获得明文密码也可冒充用户进行登录操作. 从而产生Hash 传递攻击(Pass The Hash)

1
2
3
4
5
6
7
8
9
        ----            --------                   --------
|DC|------------|Server|-------------------|Client|
---- -------- --------
0x00 | | |<--发送用户名u------|
0x01 | | |---发送挑战字符串t->| 加密t
0x02 | | |<---发送加密响应r---|
0x03 |<-发送u,t,r-|
0x04 加密t, 和r比对
0x05 |--认证成功->|

Kerberos

 Kerberos常用于域内的认证, 不要求网络上所有主机都是安全的, 并且假定网络上的数据包都是不可信的. 在这种情况下, Kerberos能够提供一种可靠的第三方认证服务.

 在一次Kerberos认证过程中, 会出现多个角色: AD, AS, TGS组成的KDC(域控); 提供服务的服务端; 申请服务的客户端
 AD储存着用户白名单, 只有存在于白名单中的客户端才能申请到TGT.
 AS是为客户端生成TGT(Ticket Granting Ticket)的服务.
 TGS是为客户端生成对应服务的ticket的服务.

粗略流程

  1. 客户端C向Kerberos请求服务, 希望获取访问服务端S的权限
  2. Kerberos的AS接收到请求, 判断用户是否在白名单中, 成功后AS返回TGT给C
  3. C获取TGT后, 向Kerberos请求访问服务S的权限, 由于这次带着TGT, 所以就由TGS模块生成访问S的ticket给C
  4. C获取Ticket后就可以带着Ticket访问S了, 如果要访问其他的S, 则需要重新向TGS申请Ticket.

认证流程

第一步

  1. 客户端发送身份信息(用户名, 域控的信息)到KDC
  2. KDC验证客户端的信息, 计算机名, 地址等是否存在于AD中, 查找用户名对应的NTLM Hash.
  3. KDC使用用户对应的NTLM Hash加密一个随机生成的session key(类似上面的挑战字符串)称之为TGS Session Key, 用于客户端和TGS进行通信.
  4. KDC使用TGS的密钥(krbtgt)加密 上面的Session Key, 用户ID, 用户地址, 有效期 这几个信息, 称为TGT
  5. KDC发送3,4两步生成的TGS Session Key和TGT给用户.
  6. 第一步结束, 后续客户端会继续和TGS进行认证.

第二步

  1. 客户端解密第一步接收到的TGS Session Key, 得到session key. 然后使用session Key加密用户ID和时间戳, 构造认证符.
  2. 发送第一步接收到的TGT, 客户端信息, 服务端信息和构造好的认证符到KDC的TGS服务
  3. TGS服务接收到上面的信息后开始认证流程, 首先利用TGS密钥解密TGT, 获取session key, 然后通过session key解密上面加密的认证符. 确定时间戳是否超时失效. 然后比较本次收到的信息和之前第一步发送出去的信息是否相等. 如果相等则会生成新的随机session key, 称为server session key. 利用一直使用的session key加密server session key
  4. TGS 利用上一步收到的服务端信息, 使用服务端的NTLM Hash加密server session key, 客户端信息, 失效时间这些信息, 构造ticket
  5. 把ticket 和加密后的server session key发送给客户端

第三步

  1. 客户端解密, 获得对应的sever session key. 使用key加密客户端信息和时间戳, 配合ticket 发送到服务端.
  2. 服务端利用自己的NTLM 解密Ticket, 获取其中的server session key和客户端信息. 再利用server session key解密出发过来的客户端信息, 比对客户端信息是否相同. 如果相同就提供服务.

认证流程本质

 客户端和DC之间不停的交换密钥, 利用对称加密算法, 验证时间戳和身份来完成可信认证.

锐意更新中(剩下的图明天画)