跳转至

Windows域内协议

NTLM协议

NTML 全称 New Technology LAN Manager,是微软提供的一组安全协议,用来认证用户身份。它是一个基于 质询响应 的协议,在验证用户的过程中不需要传输用户的明文密码。

目前 NTLM 几个常见的使用场景:

  • 在域环境中用作 Kerberos 的备份,当Kerberos 失效时,就会使用 NTLM 进行认证。
  • 使用本地账户登录时也会使用 NTLM 认证。
  • 客户端尝试使用 ip 进行连接,而不是主机名时,也会使用 NTLM 进行认证。

提供服务的 dll 位于 %windir%\Windows\System32\msv1_0.dll

此处的服务器,指代的是 c/s 架构中的服务器。只要向外提供服务的主机,都可以称为服务器。

SSPI/SSP

SSPI

SSPI(Security Support Provider Interface),即 安全服务提供接口,这是 Windows 定义的一套接口,该接口定义了与安全有关的功能函数,包含但不限于:

  • 身份验证机制
  • 信息完整性
  • 为其他协议提供的会话安全机制

PS:SSPI只是定义了接口函数,并没有去实现具体内容

SSP

SSP(Security Service Provider),即 安全服务提供,他是 SSPI 的实现者,是对 SSPI 相关功能函数的具体实现。微软自己实现了如下的 SSP,用于提供安全功能:

  • NTLM SSP
  • Kerberos
  • Digest SSP
  • Cred SSP
  • ......

因为SSPI中定义了与Session Security有关的API,所以上层应用利用任何SSP与远程的服务进行身份验证后,此SSP都会为本次连接生成一个随机Key,这个随机Key被称为Session Key。

上层应用经过身份验证后,可以选择性地使用这个Key对之后发往服务端或接收自服务端的数据进行签名或加密。

在系统层面,SSP就是一个dII,用来实现身份验证等安全功能。

不同的SSP,实现的身份验证机制是不一样的,比如NTLM SSP实现的是一种基于质询/响应的身份验证机制,而Kerberos SSP实现的是基于Ticket(票据)的身份验证机制。我们可以编写自己的SSP,然后注册到操作系统中,让操作系统支持我们自定义的身份验证方法。

image.png

LM/NTLM HASH 加密算法

Windows操作系统通常使用两种方法对用户的明文密码进行加密处理。在域环境中,用户信息存储在ntds.dit中,加密后为散列值

Windows操作系统中的密码一般由两部分组成,一部分为 LM Hash,另一部分为NTLMHash。在Windows操作系统中,Hash的结构通常如下

Text Only
username:RID:LM‐HASH:NTLM‐HASH:::

LM Hash的全名为"LAN Manager Hash",是微软为了提高 Windows操作系统的安全性而采 用的散列加密算法,其本质是DES加密。

尽管 LM Hash较容易被破解,但为了保证系统的兼容性, Windows只是将LM Hash禁用了(从Windows vista和 Windows Server2008版本开始, Windows操作系统默认禁用 LM Hash)。

LM Hash明文密码被限定在 14 位以内,也就是说,如果要停止使用 LM Hash,将用 户的密码设置为14 位以上即可。如果 LM Hash被禁用了,攻击者通过工具抓取的 LM Hash通常 为“ad3b435b51404eead3b435b51404ee”(表示 LM Hash为空值或被禁用)

NTLM Hash是微软为了在提高安全性的同时保证兼容性而设计的散列加密算法。 NTLM Hash 是基于MD4加密算法进行加密的。个人版从 Windows vista以后,服务器版从 Windows Server 2003以后, Windows操作系统的认证方式均为 NTLM Hash

为了解决LM加密和身份验证方案中固有的安全弱点,Microsoft 于 1993 年在Windows NT 3.1中引入了NTLM协议。下面是各个版本对LM和NTLM的支持。

LM HASH 加密算法

  • 将明文口令转换为其大写形式 假设这里以明文Admin@123为例,转换为大写格式为:ADMIN@123

  • 将字符串大写后转换为16进制字符串转换后为

Text Only
41 44 4D 49 4E 40 31 32 33
  • 密码不足14字节(28长度)要求用0补全,1Byte=8bit,上面的16进制字符串共9个字节,还差5个字节,使用00
Text Only
00 00 00 00 00 

补全为

Text Only
41 44 4D 49 4E 40 31 32 33 00 00 00 00 00
  • 将上述编码分成2组7字节
Text Only
41 44 4D 49 4E 40 31 第一组

32 33 00 00 00 00 00 第二组
  • 将每一组7字节的十六进制转换为二进制,每7bit一组末尾加0,再转换成十六进制组成得到2组8字节的编码

第一组

Text Only
16进制:41 44 4D 49 4E 40 31

转换为二进制:01000001010001000100110101001001010011100100000000110001

七个为一组末尾补

01000000

10100010

00010010

10101000

10010100

01110010

00000000

01100010

合并后为0100000010100010000100101010100010010100011100100000000001100010

在转换为16进制:40A212A894720062

第二组

Text Only
16进制:32 33 00 00 00 00 00

转换为二进制:00110010001100110000000000000000000000000000000000000000

七个为一组末尾补

00110010

00011000

11000000

00000000

00000000

00000000

00000000

00000000

合并后为0011001000011000110000000000000000000000000000000000000000000000

在转换为16进制:3218C00000000000
  • 将以上步骤得到的两组8字节编码,分别作为DES加密key为魔术字符串“KGS!@#$% ”进行加密

KGS!@#$%的16进制为

Text Only
4B47532140232425

第一组:6F08D7B306B1DAD4

第二组:B75E0C8D76954A50

  • 最终结果拼接即可6F08D7B306B1DAD4B75E0C8D76954A50

NTLM HASH 加密算法

为了解决 LM Hash 加密和身份验证方案中固有的安全弱点,Microsoft 于1993年在Windows NT 3.1中引入了NTLM协议。下面是各个版本对LM和NTLM的支持。

也就是说从Windows Vista 和 Windows Server 2008开始,默认情况下只存储 NTLM Hash,LM Hash 将不再存在。(因此后面我们将不再介绍LM Hash)如果空密码或者不储蓄 LM Hash 的话,我们抓到的LM Hash是AAD3B435B51404EEAAD3B435B51404EE。所以在 Windows 7 中我们看到抓到 LM Hash 都是AAD3B435B51404EEAAD3B435B51404EE,这里的 LM Hash 已经没有任何价值了。

LM Hash的计算方式如下:

1.先将用户密码转换为十六进制格式。

2.将十六进制格式的密码进行Unicode编码。

3.使用MD4摘要算法对Unicode编码数据进行Hash计算


将明文口令转换成十六进制的格式 如:Admin@123

转换成Unicode格式,即在每个字节之后添加0x00

Text Only
Admin@123转16进制 41 64 6D 69 6E 40 31 32 33
# 每两位为一字节

添加00:410064006D0069006E004000310032003300

对Unicode字符串作MD4加密,生成32位的十六进制数字串

Text Only
570a9a65db8fba761c1008a51d4c95ab

NTLM 身份认证

Windows 的 NTLM 认证就是利用 NTLM Hash 进行的认证,可以分为 本地认证 和 网络认证 两种方式。NTLM 的网络认证,既可用于域内的认证服务,又可用于工作组环境。NTLM 有 NTLMv1 、NTLMv2 、NTLMsession v2 三个版本,目前使用最多的是NTLMv2版本。

NTLM 本地认证

Windows的登陆密码是储存在系统本地的SAM文件中的,在登陆Windows的时候,系统会将用户输入的密码与 SAM文件中的密码进行对比,如果相同,则认证成功

SAM文件是位于**%SystemRoot%\system32\config\目录**下的,用于储存本地所有用户的凭证信息,但是这并不代表 着你可以随意去查看系统密码。

Windows本地认证流程如下:

Windows Logon Process(即winlogon.exe):是Windows NT 用户登陆程序,用于管理用户登陆和退出

LSASS:用于微软Windows系统的安全机制,它用于本地安全和登陆策略

本地认证中用来处理用户输入密码的进程即lsass.exe,密码会在这个进程中明文保存,供该进程将密码计算成NTLM Hash与sam进行比对,我们使用mimikatz来获取的明文密码,便是在这个进程中读取到的

当用户在 Windows 本地登录时,用户的密码存储在本地计算机的 SAM 这个文件里,SAM 文件的路径为%SystemRoot%\system32\config\SAM。当用户输入密码进行本地认证的过程中,用户输入的密码将为被转化为 NTLM Hash,然后与SAM中的NTLM Hash进行比较。

当用户注销、重启、锁屏后,操作系统会让 winlogon.exe 显示登录界面(输入框)。当 winlogon.exe 接收输入后,会将密码交给lsass进程。

lsass.exe 是一个系统进程,用于微软Windows系统的安全机制。它用于本地安全和登陆策略,这个进程中会存一份明文密码,将明文密码加密成 NTLM Hash,对SAM数据库比较认证。

NTLM 在工作组环境中的认证

NTLM 在网络环境中的认证采用的是一种 Challenge/Response 验证机制,由三种消息组成:

  • type 1:协商
  • type 2:质询
  • type 3:身份验证

下面详细介绍一下 NTLM 在工作组环境中的工作机制。

我们可以看看工作组中和域环境中的**NTLM**认证过程

img

(1)首先,如果客户端需要访问服务器的某个服务是需要进行身份认证的。于是,客户端要输入服务器的用户名和密码进行验证,此时客户端本地会缓存一份服务器密码的 NTLM Hash 值。客户端发送 **TYPE 1 Negotiate**协商消息去协商需要认证的主体,用户(服务器端的用户名),机器以及需要使用的安全服务等信息。

(2)服务端接收到客户端发送过来的 TYPE 1 消息后,会读取其中的内容,并从中选择出自己所能接受的服务内容,加密等级,安全服务等。然后传入 NTLM SSP,得到 **TYPE 2 Challenge**消息(被称为 Challenge 挑战消息),并将此 TYPE 2 消息发回给客户端。这个 TYPE 2 消息中包含了一个由服务端生成的16位随机值,此随机值被称为 Challenge,服务器也会将该 Challenge 保存起来。

(3)客户端收到服务端返回的 TYPE 2 消息后, 会读取出服务端所支持的内容,并取出其中的随机值 Challenge,用缓存的服务器端密码的 NTLM-Hash 对其进行加密,并与用户名、Challenge 等一起组合得到 Net-NTLMHash,最后将 **Net NTLM-Hash**封装到 **TYPE 3 Authenticate**消息中(被称为 Authenticate 认证消息),发往服务端。

(4)服务器在收到 TYPE 3 的消息之后,用自己的密码的 NTLM-Hash 对 Challenge 进行加密,并比较自己计算出的 Net NTLM-Hash 认证消息和客户端发送的认证消息是否匹配。如果匹配,则证明客户端掌握了正确的密码,认证成功,否则认证失败。

NTLM 在域环境中的认证

img

NTLM 在域环境中的认证的前三步与NTLM 在工作组环境中的认证是一样的,不同的地方开始出现在第四步:

(4)服务器接收到客户端发送来的 **TYPE 3**消息后,取出其中的 **Net NTLM-Hash**值,并向域控制器发送针对客户端的验证请求。该请求主要包含以下三方面的内容:用户名(服务器端的用户名)、原始的 Challenge 和 加密后的 Challenge(即Net NTLM-Hash)。

(5)然后域控制器会根据用户名获取该帐号的密码哈希值 NTLM Hash,用哈希值对原始的 Challenge 进行加密得到 Net NTLM-Hash。如果加密后的 Challenge 和服务器发送的一致,则意味着用户拥有正确的密码,验证通过,否则验证失败。并将验证结果发给服务器。

(6)服务器根据域控制器返回的结果,对客户端进行回复。

基于网络的NTLM认证流程

认证成功

首先,client会向server发送一个username,这个username是存在于server上的一个用户

然后会在本地查询是否存在这样的一个用户,如果存在,将会生成一个16位的随机字符,即Chalenge,然后用查询到的这个user的NTLM hash对Chalenge进行加密,生成Chalenge1,将Chalenge1存储在本地,并将Chalenge传给client。

当client接收到Chalenge时,将发送的username所对应的NTLM hash对Chalenge进行加密即Response,并Response发送给server

server在收到Response后,将其与Chalenge1进行比较,如果相同,则验证成功

认证失败

首先,client会向server发送一个username,这个username是存在于server上的一个用户

当server接收到这个信息时,首先会在本地查询是否存在这样的一个用户,如果不存在,则直接返回认证失败

Net-NTLM Hash

是指网络环境下NTLM认证中的hash

NTLM认证采用质询/应答(Challenge/Response)的消息交换模式,流程如下:

  • 客户端向服务器发送一个请求,请求中包含明文的登录用户名。服务器会提前存储登录用户名和对应的密码hash
  • 服务器接收到请求后,生成一个16位的随机数(这个随机数被称为Challenge),明文发送回客户端。使用存储的登录用户密码hash加密Challenge,获得Challenge1
  • 客户端接收到Challenge后,使用登录用户的密码hash对Challenge加密,获得Challenge2(这个结果被称为response),将response发送给服务器
  • 服务器接收客户端加密后的response,比较Challenge1和response,如果相同,验证成功

在以上流程中,登录用户的密码hash即 NTLM hash,response中包含Net-NTLM hash

更多NTLM认证的资料可参考:http://davenport.sourceforge.net/ntlm.html

在NTLM认证中,NTLM响应分为NTLM v1,NTLMv2,NTLM session v2三种协议,不同协议使用不同格式的Challenge和加密算法所以也就存在不同协议的Net-NTLM hash,即Net-NTLM v1 hash,Net-NTLM v2 hash

NTML协议v1/v2

NTLM V2协议,NTLMv1与NTLM v2最显著的区别就是Challenge与加密算法不同,共同点就是加密的原料都是NTLM Hash

  • NTLM v1的Challenge有8位;NTLM v1的主要加密算法是DES

  • NTLM v2的Challenge为16位;NTLM v2的主要加密算法是HMAC‐MD5

抓包分析

实验环境如下

使用如下命令进行远程连接,并且使用wireshark 包

Text Only
net use \\192.168.41.130 /u:kkk Admin@123

前5个数据包中前四条时协商,第五个是认证的第一个数据包

第6个数据包就是返回chalenge挑战值

分析该数据包得到chalenge值 53fb7eb8d40cc777

第7个数据包就是返回response的数据包

rsponse数据如下:

Text Only
3d00ee8a5618f85651098b8005883d5c0101000000000000f790f7af9b92d8019cba65f5e39a1ea90000000002000e0042004d002d00320030003000380001000e0042004d002d00320030003000380004000e0042004d002d00320030003000380003000e0042004d002d00320030003000380007000800f790f7af9b92d801060004000200000008003000300000000000000001000000002000009906b326309f0ba76eb46b2271795e5d12df73e87035391df48f0fad1ce073380a001000000000000000000000000000000000000900260063006900660073002f003100390032002e003100360038002e00340031002e003100330030000000000000000000

接下来得到NTLMv2 数据,NTLMv2格式如下:

Text Only
username::domain:challenge:HMAC‐MD5:blob

介绍如下:

  • username:对应数据包中 user name

  • domain:对应数据包中的 Domain name

  • HMAC‐MD5:对应数据包中的NTProofStr

  • blob:数据库包中rsponse去掉HMAC‐MD5的值

最终的到HTLNv2如下:

Text Only
kkk:::53fb7eb8d40cc777:3d00ee8a5618f85651098b8005883d5c:0101000000000000f790f7af9b92d8019cba65f5e39a1ea90000000002000e0042004d002d00320030003000380001000e0042004d002d00320030003000380004000e0042004d002d00320030003000380003000e0042004d002d00320030003000380007000800f790f7af9b92d801060004000200000008003000300000000000000001000000002000009906b326309f0ba76eb46b2271795e5d12df73e87035391df48f0fad1ce073380a001000000000000000000000000000000000000900260063006900660073002f003100390032002e003100360038002e00340031002e003100330030000000000000000000
密码破解

使用hashcat 破解密码

Bash
hashcat ‐m 5600 kkk:::53fb7eb8d40cc777:3d00ee8a5618f85651098b8005883d5c:0101000000000000f790f7af9b92d8019cba65f5e39a1ea90000000002000e0042004d002d00320030003000380001000e0042004d002d00320030003000380004000e0042004d002d00320030003000380003000e0042004d002d00320030003000380007000800f790f7af9b92d801060004000200000008003000300000000000000001000000002000009906b326309f0ba76eb46b2271795e5d12df73e87035391df48f0fad1ce073380a001000000000000000000000000000000000000900260063006900660073002f003100390032002e003100360038002e00340031002e003100330030000000000000000000 1.txt ‐‐force
# 一般都是基于字典进行爆破,字典请自行收集

使用hashcat破解得到密码

LAN Manager 身份验证级别

**LAN Manager 身份验证级别**设置确定用于网络登录的质询/响应身份验证协议。 此选项会影响客户端使用的身份验证协议级别、计算机协商的会话安全级别以及服务器接受的身份验证级别。 下表标识了策略设置,介绍了设置,并标识了在相应注册表设置中使用的安全级别(如果选择使用注册表来控制此设置而不是策略设置)。

设置 说明 注册表安全级别
发送 LM & NTLM 响应 客户端设备使用 LM 和 NTLM 身份验证,并且从不使用 NTLMv2 会话安全性。 域控制器接受 LM、NTLM 和 NTLMv2 身份验证。 0
发送 LM & NTLM - 使用 NTLMv2 会话安全性(如果协商) 客户端设备使用 LM 和 NTLM 身份验证,如果服务器支持,则它们使用 NTLMv2 会话安全性。 域控制器接受 LM、NTLM 和 NTLMv2 身份验证。 1
仅发送 NTLM 响应 客户端设备使用 NTLMv1 身份验证,如果服务器支持 NTLMv2 会话安全性,则使用 NTLMv2 会话安全性。 域控制器接受 LM、NTLM 和 NTLMv2 身份验证。 2
仅发送 NTLMv2 响应 客户端设备使用 NTLMv2 身份验证,如果服务器支持 NTLMv2 会话安全性,则使用 NTLMv2 会话安全性。 域控制器接受 LM、NTLM 和 NTLMv2 身份验证。 3
仅发送 NTLMv2 响应。 拒绝 LM 客户端设备使用 NTLMv2 身份验证,如果服务器支持 NTLMv2 会话安全性,则使用 NTLMv2 会话安全性。 域控制器拒绝接受 LM 身份验证,它们将仅接受 NTLM 和 NTLMv2 身份验证。 4
仅发送 NTLMv2 响应。 拒绝 LM & NTLM 客户端设备使用 NTLMv2 身份验证,如果服务器支持 NTLMv2 会话安全性,则使用 NTLMv2 会话安全性。 域控制器拒绝接受 LM 和 NTLM 身份验证,它们仅接受 NTLMv2 身份验证。
  • 策略位置

计算机配置\Windows 设置\安全设置\本地策略\安全选项

  • 注册表位置

HKLM\System\CurrentControlSet\Control\Lsa\LmCompatibilityLevel

参考官方文档:https://learn.microsoft.com/zh-cn/windows/security/threat-protection/security-policy-settings/network-security-lan-manager-authentication-level

NTML协议的安全问题

  • 哈希传递攻击(Pass The Hash)

在NTLM身份认证流程中可以看到Type 3中的Authenticate 认证消息是用用户密码Hash计算的,因此,如果拿到了用户的密码Hash,可以进行Pass The Hash(PTH)攻击

  • Net-NTML Relay攻击

在Type 3消息中,存在Net-NTML Hash,如果拿到了Net-NTML Hash,可以进行中间人攻击,重放Net-NTML Hash,也就是NTML Relay(NTML中继)攻击

  • Net-NTML V1 Hash破解

NTML V1协议加密过程存在缺陷,可以对Net-NTML V1 Hash进行破解,得到NTML Hash后可以进行横向移动

Kerberos协议

什么是Kerberos协议

Kerberos是由麻省理工学院提出的一种网络身份验证协议。它旨在通过使用密钥加密技术为客户端/服务器应用程序提供强身份验证。Kerberos协议有两个基础认证模块: AS_REQ &AS_REP**和 TGS_REQ & TGS_REP,以及微软扩展的两个认证模块**S4U**和**PAC。

kerberos是一种基于票据的认证方式。客户端如果要访问某个服务首先要获得相应的票据——Service Ticket(ST服务票据)。但是想要获取到服务票据ST,需要先获得一张认购权证——Ticket Granting Tikect(TGT) 。TGT和ST均有**KDC(Key Distribute Center)密钥分发中心**发售。从物理层面看,KDC由域控控制器担任,其中包括**AS(Authentication Service)认证服务**和**TGS(Ticket Granting Service)票据授予服务**。可以参考下图:

img

在网络的各种认证中随时都有可能存在中间人攻击的情况,Kerberos协议设计之初便考虑到了这个问题,所以Kerberos协议的整个认证过程实现不依赖于主机操作系统的认证,无需基于主机地址的信任,不要求整个网络中每台主机都是安全的,并假定网络上传送的数据包可以被任意地读取、修改和插入数据。在以上情况下, Kerberos作为一种可信任的第三方认证服务,是通过传统的密码技术(如:共享密钥)执行认证服务的。

在这种方式下让Kerberos的整个认证过程中不用担心受到中间人攻击。

Kerberos协议的组成角色

在古希腊神话故事中,kerberos是一只具有三颗头颅的地狱恶犬,他守护在地狱之外,能够识别所有经此路过的亡灵,防止活着的入侵者闯入地狱。

kerberos协议中也存在三个角色,分别是

  • 客户端(client):发送请求的一方

  • 服务端(Server):接收请求的一方

  • 密钥分发中心(Key Distribution Center,KDC)

  • AS(Authentication Server):认证服务器,专门用来认证客户端的身份并发放客户用于访问TGS的TGT(票据授予票据)

    • TGS(Ticket Granting Ticket):票据授予服务器,用来发放整个认证过程以及客户端访问服务端时所需的服务授予票据(Ticket)

相关概念

  • Principal(安全个体)

​ 被认证的个体,有一个名字(name)和口令(password)

  • KDC (Key Distribution Center)

​ 提供ticket和临时的会话密钥的网络服务

  • Ticket

​ 一个记录,用户可以用它来向服务器证明自己的身份,其中包括用户的标识、会话密钥、时间戳,以及其他一些信息。Ticket 中的大多数信息都被加密,密钥为服务器的密钥

  • Authenticator

​ 一个记录,其中包含一些最近产生的信息,产生这些信息需要用到用户和服务器之间共享的会话密钥

  • Credentials

​ 一个ticket加上一个秘密的会话密钥

  • Authentication Server (AS)

​ 通过 long-term key 认证用户AS 给予用户 ticket granting ticket 和 short-term key认证服务

  • Ticket Granting Server (TGS)

​ 通过 short-term key 和 Ticket Granting Ticket 认证用户TGS 发放 tickets 给用户以访问其他的服务器授权和访问控制服务

krbtgt用户

krbtgt用户是在创建域时系统自动创建的一个账号,其作用是密钥发行中心KDC的服务账号,其密码是系统随机生成的,无法正常登陆主机。

img

Kerberos认证的简单流程

简单来说,kerberos认证可以分为三大步:

第一步:Client与AS(Authentication Service认证服务)通信,获取TGT(Ticket Granting Ticket)认证权证

① AS-REQ

② AS-REP

第二步:Client拿着TGT,与TGS(Ticket Granting Service票据授予服务)通信,获取ST(Service Ticket服务票据)

③ TGS-REQ

④ TGS-REP

第三步:Client拿着ST,与Server通信,访问服务。

⑤ AP-REQ

⑥ AP-REP

当然有些情况下,中间还会经过一步PAC认证(Privilege Attribute Certificate特权属性证书)。

img

举个例子:

A现在想要去访问B完成一个任务。但是AB两人之间是从来没有见过面的,他们只知道对方的名字叫A,B。此时如果A直接去找B告诉B我就是A,那么B是有理由不相信A的,B同理也得不到A的认可,他们陷入了一个无法证明我就是我的困难

于是他们就想到了一个办法,AB找到了一个他俩共同信任的人C,且这个C既认识A又认识B,所以只要C告诉B,这个A确实就是真正的A那么B就会信任这个A,同理B经过C的认可后,A也会相信B的身份。此后,A在访问B之前会先去找C,C会交给A一个凭证,代表此时的A已经得到了C的认证,这时A拿着凭证再去找B,便可以得到B的确认了


再举个例子:

我们去动物园,动物园不认识你不让你进,你也怕进门后不是动物园,所以就很尴尬

如何解决呢?我们建立一个售票窗口,只要售票处认识你和动物园,你和动物园之间就可以相互信任。

  • 人:代表客户端

  • 动物园:代表服务端

  • 售票处:代表KDC

所以整个kerberos认证流程可以简化描述如下: 客户端在访问每个想要访问的网络服务时,他需要携带一个专门用于访问该服务并且能够证明自己身份的票据,当服务端收到了该票据他才能认定客户端身份正确,向客户端提供服务。所以整个认证流程可简化为两大步:

  • 客户端向KDC请求获取想要访问的目标服务的服务授予票据(Ticket)

  • 客户端拿着从KDC获取的服务授予票据(Ticket)访问相应的网络服务

Kerberos认证完成流程

Question

那么KDC怎么知道你(客户端)就是真正的客户端?凭什么给你发放服务授予票据(Ticket)呢?

我们以去动物园为例,售票处凭什么给你买票,你如果是一个逃犯怎么办?其实买票的过程我们可以分为两步

  • 第一步是你拿着身份证去验证
  • 第二步身份验证通过了才会给你票

  • 人:代表客户端

  • 动物园:代表服务端

  • 售票处:KDC

  • 身份校验人员:AS,负责验证用户身份的合法性,和给用户一个可以买票的票(TGT)

  • 卖票人员:TGS,负责客户端访问服务端时所需的服务授予票据的单位

所以kerberos通信可以分为3步,我们逐步详解

客户端和AS进行通信(身份验证/TGT发放)

为了获得能够用来访问服务端服务的票据,客户端首先需要来到KDC获得服务授予票据(Ticket)。由于客户端是第一次访问KDC,此时KDC也不确定该客户端的身份,所以第一次通信的目的为KDC认证客户端身份,确认客户端是一个可靠且拥有访问KDC权限的客户端,


  1. 客户端用户向KDC以明文的方式发起请求。该次请求中携带了自己的用户名,主机IP,和当前时间戳

  2. KDC当中的AS(Authentication Server)接收请求(AS是KDC中专门用来认证客户端身份的认证服务器)后去kerberos认证数据库中根据用户名查找是否存在该用户,此时只会查找是否有相同用户名的用户,并不会判断身份的可靠性

  3. 如果没有该用户名,认证失败,服务结束;如果存在该用户名,则AS认证中心便认为用户存在,此时便会返回响应给客户端,其中包含两部分内容:

  4. 第一部分内容称为TGT,他叫做票据授予票据,客户端需要使用TGT去KDC中的TGS(票据授予中心)获取访问网络服务所需的Ticket(服务授予票据),TGT中包含的内容有kerberos数据库中存在的该客户端的Name,IP,当前时间戳,客户端即将访问的TGS的Name,TGT的有效时间以及一把用于客户端和TGS间进行通信的Session_key(CT_SK)。整个TGT使用TGS密钥加密,客户端是解密不了的,由于密钥从没有在网络中传输过,所以也不存在密钥被劫持破解的情况。

  5. 第二部分内容是使用客户端密钥加密的一段内容,其中包括用于客户端和TGS间通信的Session_key(CT_SK),客户端即将访问的TGS的Name以及TGT的有效时间,和一个当前时间戳。该部分内容使用客户端密钥加密,所以客户端在拿到该部分内容时可以通过自己的密钥解密。


如果是一个假的客户端,那么他是不会拥有真正客户端的密钥的,因为该密钥也从没在网络中进行传输过。这也同时认证了客户端的身份,如果是假客户端会由于解密失败从而终端认证流程。至此,第一次通信完成。

客户端和TGS进行通信(ST发放)

此时的客户端收到了来自KDC(其实是AS)的响应,并获取到了其中的两部分内容。此时客户端会用自己的密钥将第二部分内容进行解密,分别获得时间戳,自己将要访问的TGS的信息,和用于与TGS通信时的密钥CT_SK。

首先他会根据时间戳判断该时间戳与自己发送请求时的时间之间的差值是否大于5分钟,如果大于五分钟则认为该AS是伪造的,认证至此失败。如果时间戳合理,客户端便准备向TGS发起请求

客户端行为:

  1. 客户端使用CT_SK加密将自己的客户端信息发送给KDC,其中包括客户端名,IP,时间戳;

  2. 客户端将自己想要访问的Server服务以明文的方式发送给KDC;

  3. 客户端将使用TGS密钥加密的TGT也原封不动的也携带给KDC;

TGS行为:

  1. 此时KDC中的TGS(票据授予服务器)收到了来自客户端的请求。他首先根据客户端明文传输过来的Server服务IP查看当前kerberos系统中是否存在可以被用户访问的该服务。如果不存在,认证失败结束。如果存在,继续接下来的认证。

  2. TGS使用自己的密钥将TGT中的内容进行解密,此时他看到了经过AS认证过后并记录的用户信息,包括Session_KEY即CT_SK,还有时间戳信息,他会根据时间戳判断此次通信是否真是可靠,有无超出时延。

  3. 如果时延正常,则TGS会使用CT_SK对客户端的第一部分内容进行解密(使用CT_SK加密的客户端信息),取出其中的用户信息和TGT中的用户信息进行比对,如果全部相同则认为客户端身份正确,方可继续进行下一步。

此时KDC将返回响应给客户端,响应内容包括:

  1. 第一部分:用于客户端访问网络服务的使用Server密码加密的ST(Servre Ticket),其中包括客户端的Name,IP,需要访问的网络服务的地址Server IP,ST的有效时间,时间戳以及用于客户端和服务端之间通信CS_SK(SessionKey)

  2. 第二部分:使用CT_SK加密的内容,其中包括CS_SK和时间戳,还有ST的有效时间。由于在第一次通信的过程中,AS已将CT_SK通过客户端密码加密交给了客户端,且客户端解密并缓存了CT_SK,所以该部分内容在客户端接收到时是可以自己解密的


至此,第二次通信完成。

客户端和服务端进行通信

此时的客户端收到了来自KDC(TGS)的响应,并使用缓存在本地的CT_SK解密了第二部分内容(第一部分内容中的ST是由Server密码加密的,客户端无法解密),检查时间戳无误后取出其中的CS_SK准备向服务端发起最后的请求

客户端:

  • 客户端使用CS_SK将自己的主机信息和时间戳进行加密作为交给服务端的第一部分内容,然后将ST(服务授予票据)作为第二部分内容都发送给服务端。

服务端:

  1. 服务器此时收到了来自客户端的请求,他会使用自己的密钥,即Server密钥将客户端第二部分内容进行解密,核对时间戳之后将其中的CS_SK取出,使用CS_SK将客户端发来的第一部分内容进行解密,从而获得经过TGS认证过后的客户端信息,此时他将这部分信息和客户端第二部分内容带来的自己的信息进行比对,最终确认该客户端就是经过了KDC认证的具有真实身份的客户端,是他可以提供服务的客户端
  2. 此时服务端返回一段使用CT_SK加密的表示接收请求的响应给客户端,在客户端收到请求之后,使用缓存在本地的CS_ST解密之后也确定了服务端的身份(其实服务端在通信的过程中还会使用数字证书证明自己身份)

至此,第三次通信完成。此时也代表着整个kerberos认证的完成,通信的双方都确认了对方的身份,此时便可以放心的进行整个网络通信了。

总体流程图

Kerberos扩展模块

kerberos认证过程中包含6个消息

  • KRB_AS_REQ,KRB_AS_REP (与 AS交互)
  • KRB_TGS_REQ,KRB_TGS_REP (与TGS交互)
  • KRB_AP_REQ和KRB_AP_REP (与Server交互)

此外,微软在标准kerberos的基础上,还实现了 PAC 和 S4U

PAC

Question

上面讲的kerberos流程看起来没错,却忽略一个最重要的因素,那就是用户有没有权限访问该服务?

在上面的流程里面,只要用户的hash正确,那么就可以拿到TGT,有了TGT,就可以拿到TGS,有了TGS,就可以访问服务,任何一个用户都可以访问任何服务。也就是说上面的流程解决了”Who am i?”的问题,并没有解决 “What can I do?”的问题。

PAC的全称是Privilege Attribute Certificate(特权属性证书), 其中所包含的是各种授权信息, 例如用户所属的用户组, 用户所具有的权限等。

当用户与KDC之间**完成了认证过程之后**, 用户需要访问服务器所提供的某项服务时, 服务器**为了判断用户是否具有合法的权限**必须通过**将用户的用户名**传递给KDC, KDC通过得到的用户名查询用户的用户组信息, 用户权限等, 进而返回给服务器, 服务器再将此信息与用户所索取的资源的ACL进行比较, 最后决定是否给用户提供相应的服务。

为了解决上面的这个问题,微软引进了PAC,引进PAC之后的kerberos流程变成

  1. 用户向KDC发起AS_REQ,请求凭据是用户hash加密的时间戳,KDC使用用户hash进行解密,如果结果正确返回用krbtgt hash加密的TGT票据,TGT里面包含PAC,PAC包含用户的sid,用户所在的组。

imgimg

2.用户凭借TGT票据向KDC发起针对特定服务的TGS_REQ请求,KDC使用krbtgt hash进行解密,如果结果正确,就返回用服务hash 加密的TGS票据(这一步不管用户有没有访问服务的权限,只要TGT正确,就返回TGS票据,这也是kerberoating能利用的原因,任何一个用户,只要hash正确,可以请求域内任何一个服务的TGS票据

3.用户拿着TGS票据去请求服务,服务使用自己的hash解密TGS票据。如果解密正确,就拿着PAC去KDC那边询问用户有没有访问权限,域控解密PAC。获取用户的sid,以及所在的组,再判断用户是否有访问服务的权限,有访问权限**(有些服务并没有验证PAC这一步,这也是白银票据能成功的前提,因为就算拥有用户hash,可以制作TGS,也不能制作PAC,PAC当然也验证不成功,但是有些服务不去验证PAC,这是白银票据成功的前提)**就允许用户访问。

特别说明的是,PAC对于用户和服务全程都是不可见的。只有KDC能制作和查看PAC。

详细PAC参考文章:Windows内网协议学习Kerberos篇之PAC

S4U

这是微软为解决委派问题提出的

详细参考文章:Kerberos 委派攻击原理之 S4U2 利用详解

Kerberos协议的安全问题

img

AS-REQ阶段

在AS-REQ阶段,存在用户NTLM Hash加密的时间戳,所以也就造成了**哈希传递攻击**。

而当用户不存在时,返回包会有所不同,我们可以基于此进行用户名枚举,所以也就造成了**域内用户枚举攻击**(当我们不在域内,可以使用这个方法枚举域内用户)。

**密码喷洒(Password Spraying)**攻击,它属于自动化密码猜测的一种,是用固定的密码去跑用户名。这种针对所有用户的自动密码猜测通常是为了避免帐户被锁定,因为针对同一个用户的连续密码猜测会导致帐户被锁定。所以只有对所有用户同时执行特定的密码登录尝试,才能增加破解的概率,消除帐户被锁定的概率。

AS-REP阶段

在AS-REP阶段,由于返回的TGT认购权证是由krbtgt用户的密码Hash加密的,因此如果我们拥有krbtgt的 hash 就可以自己制作一个TGT认购权证,这就造成了**黄金票据攻击**

在AS-REP阶段,Login Session key(最外层的enc-part)是用用户密码 Hash 加密的。对于域用户,如果设置了选项” Do not require Kerberos preauthentication”,此时向域控制器的 88 端口发送 AS_REQ 请求,对收到的AS_REP内容(数据包enc-part底下的cipher,因为这部分是使用用户 hash 加密的 Login Session Key,我们通过进行离线爆破就可以获得用户hash)重新组合,能够拼接成”Kerberos 5 AS-REP etype 23”(18200)的格式,接下来可以使用hashcat对其破解,最终获得该用户的明文口令,这就造成了 AS-REP Roasting攻击。

img

TSG-REP阶段

在TGS-REP阶段,由于内层enc-part是用服务账号的NTLM Hash加密的,所以当我们得到了ST服务票据,可以通过爆破获得该计算机服务账号的密码hash,这就是**Kerberoast攻击**。

这个问题存在的另外一个因素是因为用户向KDC发起TGS_REQ请求,不管用户对服务有没有访问权限,只要TGT正确,那么肯定会返回TGS。

在TGS-REP阶段,TGS_REP里面的ticket的enc-part(内层enc-part)是使用服务账号的ntlm hash进行加密的,如果我们拥有服务账号的ntlm hash,就可以给我们自己签发该服务的ST票据,这个票据也被称为**白银票据**。相较于黄金票据,白银票据使用要访问服务的hash,而不是krbtgt的hash,由于生成的是ST票据,不需要跟域控打交道,但是白银票票据只能访问特定服务。但是要注意的一点是,伪造的白银票据没有带有有效KDC签名的PAC。如果将目标主机配置为验证KDC PAC签名,则银票将不起作用。

说白了,kerberoast攻击就是 :有ST服务票据,去爆破服务账号的NTLM Hash ;而白银票据,就是有服务账号的NTLM Hash,去签发该服务的ST服务票据。

img

AS-REQ阶段

哈希传递攻击(Pass The Hash)

在工作组环境中:

  • Windows Vista 之前的机器,可以使用本地管理员组内用户进行攻击。
  • Windows Vista 之后的机器,只能是administrator用户的哈希值才能进行哈希传递攻击,其他用户(包括管理员组用户但是非administrator)也不能使用哈希传递攻击,会提示拒绝访问。

在域环境中:

  • 只能是域管理员组内用户(可以是域管理员组内非administrator用户)的哈希值才能进行哈希传递攻击,攻击成功后,可以访问域内任何一台机器

LDAP协议

什么是LDAP协议?

LDAP全称是Lightweight Directory Access Protocol,轻量目录访问协议。顾名思义,LDAP是设计用来访问目录数据库的一个协议。

在这之前我们先介绍一下目录服务。目录数据库是由目录服务数据库和一套访问协议组成。

目录服务数据库也是一种数据库,这种数据库相对于我们熟知的关系型数据库(比如MySQL,Oracle),主要有以下几个方面的特点。

  1. 它成树状结构组织数据,类似文件目录一样。
  2. 它是为查询、浏览和搜索而优化的数据库,也就是说LDAP的读性能特别强,但是写性能差,而且还不支持事务处理、回滚等复杂功能。

为了能够访问目录数据库,必须设计一台能够访问目录服务数据库的协议,LDAP是其中一种实现协议。

LDAP的基础结构

img

如上图所示是目录服务数据库,它成树状结构组织数据。下面介绍一些基本概念

  1. 目录树:如上图所示,在一个目录服务系统中,整个目录信息集可以表示为一个目录信息树,树中的每个节点是一个条目。
  2. 条目:每个条目就是一条记录,每个条目有自己的唯一可区别的名称(DN)。比如图中的每个圆圈都是一条记录。
  3. DN,RDN:比如说第一个叶子条目,他有一个唯一可区分的名称DN:uid=bob,ou=people,dc=acme,dc=org。类似于文件目录的相对路径绝对路径,他除了有个DN之外,还有个RDN,他与目录结构无关,比如之前咱们提过的uid=bob,ou=people,dc=acme,dc=org,他的RDN就是uid=bob
  4. 属性:描述条目具体信息。比如uid=bill,ou=people,dc=acme,dc=org,他有属性name 为bill,属性age为11,属性school 为xx。

img

DAP通过属性objectClass来控制哪一个属性必须出现或允许出现在一个条目中,它的值决定了该条目必须遵守的模式规则。

关键字 英文全称 含义
dc Domain Component 域名的部分,其格式是将完整的域名分成几部分,如域名为example.com变成dc=example,dc=com
uid User Id 用户ID,如“tom”
ou Organization Unit 组织单位,类似于Linux文件系统中的子目录,它是一个容器对象,组织单位可以包含其他各种对象(包括其他组织单元),如“market”
cn Common Name 公共名称,如“Thomas Johansson”
sn Surname 姓,如“Johansson”
dn Distinguished Name 惟一辨别名,类似于Linux文件系统中的绝对路径,每个对象都有一个惟一的名称,如“uid= tom,ou=market,dc=example,dc=com”,在一个目录树中DN总是惟一的
rdn Relative dn 相对辨别名,类似于文件系统中的相对路径,它是与目录树结构无关的部分,如“uid=tom”或“cn= Thomas Johansson”
c Country 国家,如“CN”或“US”等。
o Organization 组织名,如“Example, Inc.”

LDAP与数据库有什么区别?

LDAP是一个数据库,但是又不是一个数据库。说他是数据库,因为他是一个数据存储的东西。但是说他不是数据库,是因为他的作用没有数据库这么强大,而是一个目录

LDAP目的不是为了写,主要是为了查找。这就回答了有同志问,有人要写有人要读的并发怎么解决的问题。LDAP的用途不是针对这个来设计的,如果你有这样的需求,解决办法就应该是数据库,而不是LDAP。这就是另外一个例子,Access和SQL Server。Access就是一个数据库产品,但是主要用于家庭,功能和性能都比较弱。SQL Server就是一个专业的数据库系统,功能强大。LDAP是一个轻量级的产品,主要目的是为了查,因此在架构和优化主要是针对读,而不是写。但并不是说LDAP不能满足,只是说强项不在这里。

LDAP作为一个统一认证的解决方案,主要的优点就在能够快速响应用户的查找需求。比如用户的认证,这可能会有大量的并发。如果用数据库来实现,由于数据库结构分成了各个表,要满足认证这个非常简单的需求,每次都需要去搜索数据库,合成过滤,效率慢也没有好处。虽然可以有Cache,但是还是有点浪费。LDAP就是一张表,只需要用户名和口令,加上一些其他的东西,非常简单。从效率和结构上都可以满足认证的需求。这就是为什么LDAP成为现在很人们的统一认证的解决方案的优势所在。 当然LDAP也有数据写入的借口,是可以满足录入的要求的。这里就不多说了。

LDAP这种数据库有什么特殊的呢?

我们知道,像MySQL数据库,数据都是按记录一条条记录存在表中。而LDAP数据库,是树结构的,数据存储在叶子节点上。看看下面

  • 假设你要树上的一个苹果(一条记录),你怎么告诉园丁它的位置呢?当然首先要说明是哪一棵树(dc,相当于MYSQL的DB),然后是从树根到那个苹果所经过的所有“分叉”(ou),最后就是这个苹果的名字(uid,相当于MySQL表主键id)。

  • 好了!这时我们可以清晰的指明这个苹果的位置了,就是那棵“歪脖树”的东边那个分叉上的靠西边那个分叉的再靠北边的分叉上的半红半绿的……,晕了!你直接爬上去吧!

就这样就可以描述清楚“树结构”上的一条记录了。 说一下LDAP里如何定义一个记录的位置吧。

JavaScript
树(dc=ljheee)
分叉(ou=bei,ou=xi,ou= dong)
苹果(cn=redApple)

好了,redApple的位置出来了: dn:cn=honglv,ou=bei,ou=xi,ou=dong,dc=ljheee 其中dn标识一条记录,描述了一条数据的详细路径。 咦!有人疑问,为什么ou会有多个值?你想想,从树根到达苹果的位置,可能要经过好几个树杈,所有ou可能有多个值。关于dn后面一长串,分别是cn,ou,dc;中间用逗号隔开。

LDAP 类和继承

在域内每个条目都是类的实例。而类是一组属性的集合

img

右侧是这台机器对应的属性。查看objectClass属性

img

看到这个对象中的Values值中,有Computer的值。说明Computer的实例对象。

子类可以继承父类的所有属性,Top类是所有类的父类。

Computer等这些对象都存储在Schema NC中。

LDAP身份认证

LDAP 目录服务器使用灵活的架构,意味着它们可以用企业需要的格式来存储各种属性,包括用户凭据、电话号码、组关联等。因此,常见的 LDAP 用例是存储核心用户身份。

由于 LDAP 目录可以存储用户数据和凭证,因此它们可以作为 LDAP 身份认证的真实来源。在 LDAP 身份认证过程中,用户通过系统或应用输入其凭证,然后将其与存储在 LDAP 目录数据库中的凭据进行比较。如果匹配,用户将通过身份认证并被授予访问权限。

访问LDAP认证服务架构图

img

身份验证的步骤

LDAP利用登录名和密码进行验证,进行身份验证通常需要以下步骤:

  • 通过用户登录获取用户名密码。
  • 匿名或默认用户绑定LDAP服务器,绑定成功后执行下面步聚。
  • 根据输入的登录名,执行一个搜索。请求参数形如:"(|(uid={login})(mail={login}))“,请求如果返回一个entry,可以通过该entry得到DN,后面步聚使用。如果返回多个或没有返回,说明用户输入用户名有误,验证失败。
  • 如果上一步验证成功,得到用户信息所在entry的DN,使用这个DN和用户输入password重新绑定LDAP服务器。如果绑定成功,说明验证成功。绑定失败,返回密码错误的信息。

CLDAP协议

轻量目录访问协议(LDAP)被定义在RFC2251(LDAPv3)中,由于LDAP是以TCP字节流的方式进行数据传输,其必要的绑定操作和频繁的数据搜索查询会在一定程度消耗较多的TCP连接资源,于是IETF在1995年发布了面向无连接的轻量目录访问协议(CLDAP),官方文档为RFC1798(2003年 RFC3352将CLDAP置为历史状态)。在CLDAP中只提供三种操作:searchRequest、searchResponse (searchResEntry和searchResDone)、abandonRequest,在不提供身份验证功能的情况下,客户端可以使用UDP数据报对LDAP服务器389端口发起操作请求。

RPC协议

RPC 代表“远程过程调用”,它不是 Windows 特定的概念。RPC 的第一个实现是在80年代在UNIX系统上实现的。这允许机器在网络上相互通信,它甚至被“用作网络文件系统(NFS)的基础”。

由微软开发并在Windows上使用的RPC实现是DCE/RPC,它是“分布式计算环境/远程过程调用”的缩写。DCE/RPC只是Windows中使用的众多 IPC(进程间通信)机制之一。例如,它用于允许本地进程甚至网络上的远程客户端与本地或远程机器上的另一个进程或服务交互。

因此,这种协议的安全含义特别有趣。RPC服务器中的漏洞可能会产生各种结果,从拒绝服务 (DoS) 到远程代码执行 (RCE),包括本地权限提升 (LPE)。由于历史遗留问题,Windows上遗留RPC服务器的代码通常很旧,如果我们排除更新的 (D)COM模型,这使它成为一个非常有趣的模糊测试目标。

RPC的工作原理

RPC 工具使用户看起来就像客户端直接调用位于远程服务器程序中的过程一样。 客户端和服务器各有其自己的地址空间;也就是说,每个资源都有自己的内存资源分配给过程使用的数据。 下图演示了 RPC 体系结构。

rpc 体系结构

如图所示,客户端应用程序调用本地存根过程,而不是实现该过程的实际代码。 存根被编译并与客户端应用程序链接。 客户端存根代码不是包含实现远程过程的实际代码:

  • 从客户端地址空间检索所需的参数。
  • 根据需要将参数转换为标准 NDR 格式,以便通过网络传输。
  • 调用 RPC 客户端运行时库中的函数,将请求及其参数发送到服务器。

服务器执行以下步骤来调用远程过程。

  1. 服务器 RPC 运行时库函数接受请求并调用服务器存根过程。
  2. 服务器存根从网络缓冲区检索参数,并将其从网络传输格式转换为服务器所需的格式。
  3. 服务器存根调用服务器上的实际过程。

然后,远程过程运行,可能生成输出参数和返回值。 远程过程完成后,类似的步骤序列会将数据返回给客户端。

  1. 远程过程将其数据返回到服务器存根。
  2. 服务器存根将输出参数转换为通过网络传输所需的格式,并将其返回到 RPC 运行时库函数。
  3. 服务器 RPC 运行时库函数将网络上的数据传输到客户端计算机。

客户端通过网络接受数据并将其返回到调用函数,从而完成该过程。

  1. 客户端 RPC 运行时库接收远程过程返回值,并将其返回到客户端存根。
  2. 客户端存根将数据从其 NDR 转换为客户端计算机使用的格式。 存根将数据写入客户端内存,并将结果返回给客户端上的调用程序。
  3. 调用过程继续,就像在同一台计算机上调用该过程一样。

运行时库分为两个部分:与应用程序链接的导入库和 RPC 运行时库(作为动态链接库实现 (DLL) )。

服务器应用程序包含对服务器运行时库函数的调用,这些函数注册服务器的接口并允许服务器接受远程过程调用。 服务器应用程序还包含客户端应用程序调用的特定于应用程序的远程过程。

参考Windows文档:https://learn.microsoft.com/zh-cn/windows/win32/rpc/how-rpc-works

MS-NRPC

工作原理

使用一种称为“接口定义语言 (IDL)”的描述性语言来定义过程及其参数。每个接口都被分配了一个唯一标识符(称为 UUID),服务器和客户端都使用它来处理服务器公开的确切接口。

然后,使用 Microsoft 的 IDL 编译器将 IDL 文件编译成标头文件和源代码文件,其中包含运行时功能。从技术上讲,这些是服务器和客户端都会使用的存根,它们将控制权传递给 RPC 运行时(在 rpcrt4.dll 中实施)。客户端的 RPC 运行时对数据进行整理并传递给另一端的 RPC 运行时(图 1)。

RPC 运行时

您可能想知道,从网络(或本地)的角度来看,服务器和客户端是如何通信的。服务器通过注册一个协议序列和一个端点的组合来监听传入的 RPC 连接。例如,协议序列可以是 ncacn_ip_tcp (TCP)、 ncacn_np (指定的管道),或 ncalrpc (LPC)。端点可以是一个端口,比如 TCP 5555 或 \pipe\example(如果使用了指定的管道)。通过 TCP 445 端口上的 SMB 传输携带指定的管道(使用隐藏的 IPC$ 共享)。协议序列的完整列表可 在 Microsoft 网站上找到。

因此,服务器在某个端点上监听连接。客户端如何知道在哪里连接?答案取决于它是哪种类型的端点——是动态的,还是已知的(又称静态的)。

动态端点是在服务器端通过端点映射器注册的端点。端点映射器(又称 epmapper)是一个 RPC 服务,它将一个服务映射到实际的端点。epmapper 通过 HTTP 使用 TCP 端口 135 和 593 进行 RPC。因此,客户端可以使用 epmapper 枚举(使用 指定的 API)远程机器上所有动态注册的 RPC 服务器。

已知的端点是没有通过 epmapper 注册的端点。客户端应该事先知道服务器注册的端点。如果端点在客户端和服务器的代码中都是硬编码的,或者端点存在于 IDL 文件中,就可以做到这一点。下面是一个来自 print spooler 服务 IDL 的示例。

Text Only
[
uuid(12345678-1234-ABCD-EF00-0123456789AB),
version(1.0),
ms_union,
endpoint("ncacn_np:[\\pipe\\spoolss]"),
pointer_default(unique)
]

RPC 使用一个绑定句柄来表示客户端与服务器之间的逻辑连接。服务器和客户端都使用函数来操作绑定数据,例如,在设置身份验证信息时。当客户端在绑定上设置身份验证时,绑定被认为已经过身份验证。当客户端程序调用 RPC 函数时,就会发生网络绑定。从网络流量的角度来看,RPC 客户端通过在数据包中发送一个带有身份验证信息的绑定请求开始 RPC 交互。服务器可以回应 bind_ack(确认)或 bind_nak(发生错误)。

显示动态端点解析的 Wireshark 代码段

在图 2 的 Wireshark 代码段中,我们可以看到任务计划程序接口的动态端点解析。一旦客户端有了任务计划程序的端点信息,它就会创建一个新连接。然后我们可以看到与另一个绑定进程的新连接,同时在绑定身份验证中包含一个 AUTH3 数据包。

像端点一样,绑定也有自动、隐式和显式三种类型(图 3)。它们的不同之处在于应用程序对绑定进程的控制程度。

  • 自动绑定(废弃)——客户端和服务器应用程序不处理绑定过程,而是让 RPC 运行时完全控制此过程。
  • 隐式绑定——客户端可以选择在绑定发生之前配置绑定句柄。在客户端建立绑定后,RPC 运行时库会处理其余的任务。
  • 显式绑定——客户端需要配置绑定句柄。然后,RPC 运行时只是把它传递给服务器。

不同绑定类型的比较

参考文章:

https://www.akamai.com/zh/blog/security-research/msrpc-security-mechanisms

红队视角下RPC的利用

Netlogon协议

Netlogon服务为域控制器注册所有的srv资源纪录。这些记录出现在DNS服务器的正向查询区域你的域名中的_msdcs, _sites, _tcp, and _udp等文件夹中。其他计算机利用这些记录查询域活动目录相关的信息。

“网络登录”系统服务维护计算机和域控制器之间的安全通道,对用户和服务进行身份验证。它将用户的凭据传递给域控制器,然后返回用户的域安全标识符和用户权限。这通常称为 pass-through 身份验证。“网络登录”被配置为仅在成员计算机或域控制器加入域时自动启动。在 Windows 2000 Server 系列和 Windows Server 2003 系列中,“网络登录”发布 DNS 中的服务资源定位器记录。当此服务运行时,它依赖“服务器”服务和“本地安全机构”服务来侦听传入的请求。在域成员计算机上,“网络登录”使用命名管道上的 RPC。在域控制器上,它使用命名管道上的 RPC、RPC over TCP/IP、邮筒以及轻型目录访问协议 (LDAP)。

Netlogon是Windows Server进程,用于对域中的用户和其他服务进行身份验证。由于Netlogon是服务而不是应用程序,因此除非手动或由于运行时错误而停止,否则Netlogon会在后台连续运行。Netlogon可以从命令行终端停止或重新启动。其他机器与域控的netlogon通讯使用RPC协议MS-NRPC。

MS-NRPC指定了Netlogon远程协议,主要功能有基于域的网络上的用户和计算机身份验证;为早于Windows 2000备份域控制器的操作系统复制用户帐户数据库;维护从域成员到域控制器,域的域控制器之间以及跨域的域控制器之间的域关系;并发现和管理这些关系。

我们在MS-NRPC的文档里面可以看到为了维护这些功能所提供的RPC函数。机器用户访问这些RPC函数之前会利用本身的hash进行校验,这次的问题就出现在认证协议的校验上。

img