0%

windows认证协议之NTL

NTLM

域渗透基础的两个认证协议ntlm和Kerberos协议是最基础的, 这篇先简单总结下ntlm协议。先大概了解下在ntlm协议出现之前使用的LM

LM

windows系统内部保存密码都是经过加密存放的,早期采用的加密算法就是LM,全称是 LAN Manager Hash,是在NTLM出现之前windows使用的加密算法。本机用户的密码hash是放在本地的SAM文件,域内用户的密码hash是存在域控的NTDS.DIT文件。在我们日常登录过程中输入密码之后,系统会把我们输入的密码进行加密之后与SAM文件中存储的内容进行比对,如果相同,证明认证成功。LM现在已经意见很少了,所以大概看下加密过程和特点即可:

LM Hash加密过程

  1. 用户的密码转换为大写,密码转换为16进制字符串,不足14字节用0来补全。
  2. 密码的16进制字符串被分成两个7byte部分。每部分转换成比特流,并且长度位56bit,长度不足使用0在左边补齐长度
  3. 再分7bit为一组,每组末尾加0,加完之和合并为完整的比特流,再换算为16进制
  4. 将上步骤得到的16字节从中间分为二组,分别作为key 为 KGS!@#$%进行DES加密。
  5. 将加密后的两组拼接在一起,得到最终LM HASH值。

LM Hash算法弱点

  1. des加密的原文KGS!@#$%是固定的
  2. 密码不区分大小写并且长度最大为14位
  3. 可以根据hash判断密码长度是否大于7位,如果密码强度是小于7位,那么第二个分组加密后的结果肯定是aad3b435b51404ee
  4. 7+7字符分开加密的密码复杂度明显低于整体加密的复杂度,即95的7次方之和远小于95的14次方,其中95为可打印ascii字符集大小(这一点开始没太理解网上说的,感觉复杂度的计算应该是按照生成密文的集合去看,生成的LM HASH只能是14位长的16进制,那密码集合也就只有16的14次方,但是这个密码破解的方法是用大量的明文去破解,那明文最大集就是2个95个可打印字符的7次方之和)

NTLM

为了解决LM Hash的安全问题,微软于1993年在Windows NT 3.1中引入了NTLM协议。早期的Windows 2000 / XP / 2003等系统,在密码超过14位前使用LM Hash,在密码超过14位后使用NTLM Hash。而之后从Vista 和Server 2008开始的版本都使用NTLM Hash。

NTLM加密过程

NTLM Hash的计算方法为:

  • 将密码转换为16进制,进行Unicode编码
  • 基于MD4计算哈希值

NTLM认证过程

NTLM是基于挑战/应答的身份验证协议(庆幸下大学选修了安全协议),用通俗的意思可以理解如下:

  • 客户端在本地加密当前用户的密码成为密码散列
  • 客户端向服务器明文发送账号
  • 服务器端产生一个16位的随机数字发送给客户端,作为一个challenge
  • 客户端用加密后的密码散列来加密challenge,然后返回给服务器,作为response
  • 服务器端将用户名、challenge、response发送给域控制器
  • 域控制器用这个用户名在SAM密码管理库中找到这个用户的密码散列,然后使用这个密码散列来加密chellenge
  • 域控制器比较两次加密的challenge,如果一样那么认证成功,反之认证失败

将上面的步骤对应到NTLM协议认证的过程,根据 NTLM Message Type 的十六进制数值可以划分为以下3类:

  • Type 0x01 协商,包含包含客户端支持和服务器请求的功能列表,主要用于确认双方协议版本。
  • Type 0x02质询,对协商的消息进行响应,包含服务器支持和同意的功能列表与服务器产生的Challenge。
  • Type 0x03验证,用户客户端接收到 challenge 之后使用用户 hash 与 challenge 进行加密运算得到 response,然后将 response、username、challeng 发给服务器。其中的response是最关键的,因为服务器会把收到的 challenge 与hash进行加密运算得到 response2,如果response2和response相等则认证成功。这就是典型的挑战/响应机制,在整个交互过程中没有传递加密密码,但是客户端也依旧证明了自己的身份。

在实际场景中,如果用户 hash 是存储在域控里面,那么服务器因为没有用户 hash无法计算 response2也就无法直接验证。这个时候服务器就会通过 netlogon 协议联系域控建立一个安全通道,然后将 type 1、type 2、type 3 全部发给域控(这个过程也叫作Pass Through Authentication认证流程)。域控使用 challenge 和用户hash进行加密得到 response3与 type 3 的 response 进行比较并将结果返回给服务器。

type3响应类型

在type3中的响应,有六种类型的响应

  1. LM(LAN Manager)响应 – 由大多数较早的客户端发送,这是“原始”响应类型。
  2. NTLM v1响应 – 这是由基于NT的客户端发送的,包括Windows 2000和XP。
  3. NTLM v2响应 – 在Windows NT Service Pack 4中引入的一种较新的响应类型。它替换启用了 NTLM版本2的系统上的NTLM响应。
  4. LMv2响应 – 替代NTLM版本2系统上的LM响应。
  5. NTLM2会话响应 – 用于在没有NTLMv2身份验证的情况下协商NTLM2会话安全性时,此方案会更改LM NTLM响应的语义。
  6. 匿名响应 – 当匿名上下文正在建立时使用; 没有提供实际的证书,也没有真正的身份验证。“存 根”字段显示在类型3消息中。

这六种使用的加密流程基本一致,都是前面我们说的Challenge/Response 验证机制,区别在与客户端与服务端在会话过程中计算 response 的算法不同,接下来看下 NTLMv1 和 NTLMv2 的 response 计算原理。

NTLMv1 response

NTLMv1 response的计算过程如下:

  1. 首先是本地存储的16字节的NTLM哈希值被填充为21个字节。
  2. 16字节的NTLM哈希值被空填充为21个字节。
  3. 平分成三组7字节数据并将三个值作为DES加密密钥(即每个密钥7字节)
  4. 将三组创建三个DES密钥(每个7字节的三分之一)。
  5. 使用上面产生的3个密钥,分别对服务端传递过来的8字节challenge进行des加密生成3组8字节密文(很多翻译说是3DES是错误的)
  6. 将3组8字节密文值连接起来形成一个24字节的值,这就是NTLMV1的response了。

在一个英文文档就有说明这种response的算法和LM其实是一致的,区别仅仅是对于本地NTLMhash的计算方式不一样而已。

Note that only the calculation of the hash value differs from the LM scheme; the response calculation is the same.

NTLMv2 response

自Windows Vista起,微软默认使用 NTLMv2 协议,其基本流程如下:

  1. 首先是将用户名转换为大写再与协议消息中的 TargetName 进行拼接,逐个字符转换为16进制并每个字符都需要填充为4位,末尾增加00。
  2. 上面转换的值作为原文,本机NTLM hash 作为密钥进行 HMAC-MD5 运算生成新的hash A。
  3. 根据时间戳构建一个blob,然后再把challenge拼接在blob开头作为一个完整的消息
  4. 使用步骤2生成新的hash A作为密钥来做 HMAC-MD5 运算生成NTProofStr (NTProofStr为协议对该参数的命名)
  5. NTProofStr再与拼接在blob开头作为response

相关利用

在上面我讨论的流程中,NTLM hash 指的是登录用户存在本地的密码hash,Net-NTLM hash则指 response 中经过运算返回给服务端的hash,因此在实际的利用场景中是可以通过不同途径获取以上2种hash来进行进一步的利用,下面分部看看

Net-ntlm hash v1的格式为:

1
username::hostname:LM response:NTLM response:challenge

Net-ntlm hash v2的格式为:

1
username::domain:challenge:HMAC-MD5:blob

ntlm hash获取

本地帐号

  1. 本地sam文件
  2. lsass转储或procdump

域控多个帐号

  1. ntdsutil 域快照
  2. DiskShadow/vshadow
  3. vssadmin
  4. secretsdump
  5. mimikatz的dcsync

net-ntlm hash获取

捕获工具 Responder or Inveigh or netsh

  1. php的 LFI
  2. xxe
  3. XPath Injection
  4. mysql or mssql
  5. 利用图标文件获取连接文件服务器的NTLMv2-Hash
  6. 利用PDF文件获取Net-NTLM hash
  7. 通过HTTP协议获得Net-NTLM hash
  8. 利用PHP脚本从浏览器中获得Net-NTLM
  9. 这里的方式还有很多,只要是能发起ntlm请求的都可以,很多方法可以参考这里这里

net-ntlmV1 hash 破解

Net-NTLM v1 有2种加密方式,上面我们讨论的是方式1,这种方式的破解难度低,而第二种方式因为有client challenge的参与整体破解难度大幅增加,在使用responder的时候可以加上参数--lm来让客户端采用第一种加密方式来方便我们的破解(仅限于smb 协议)

net-ntlmV2 hash 破解

Net-NTLM v2 现在也没有什么比较好用的破解方式,一般就是利用hashcat 离线爆破明文密码,能不能跑出来就看字典里面有没有了。

Net-NTLM Relay

在上面Net-NTLM Hash的破解里面,我们可以发现实际场景下只有采取V1的加密方式1是最容易破解的,而如果遇到的是其他加密方式而且密码强度有较高的话,暴力破解基本就跑不出来了,这种情况底下,不妨试一试Relay。

Net-NTLM Relay 的原理是典型的中间人攻击,作为中间人,攻击者将来自客户端的包(type 1)转发给服务端,将来自服务端的challenge(type 2)转发给客户端,然后客户端计算完response 之后,再把response(type 3) 转发给服务端,服务端验证rsponse通过之后,授予攻击者访问的权限。

要想完成中间人攻击就得先想办法获进入到ntlm的会话过程中去,由于SMB、HTTP、LDAP等协议都可以携带NTLM认证的消息,所以只要是使用SMB、HTTP、LDAP等协议来进行NTLM认证的程序,都可以尝试向攻击者发送NTLM认证,从而让截获用户的Net-NTLM hash 来进行relay。

ntlm是一个需要交互的认证协议,消息的传输依赖于使用上层的通信协议,比如SMB,LDAP,HTTP等。那ntlm的上层协议是smb的情况下,ntlm relay就是smb relay。那如果上层协议是http,我们也可以叫做http relay,但是都统称ntlmrelay,因此,后面统一用ntlm_relay,就不再纠结这个字样了。

smb relay

最直接最有效的方法就是SMB协议的Relay攻击。可以直接控制该服务器(包括但不限于在远程服务器上执行命令、上传exe到远程主机上执行、dump 服务器的用户hash等等)。这里主要有两种场景,分别是工作组环境和域环境。

工作组环境

在工作组环境里面,工作组中的机器之间相互没有信任关系,每台机器的账号密码Hash只是保存在自己的SAM文件中,这个时候要想Relay到别的机器,只有两台机器的账号密码一样才会成功(不过如果2台机器的账号密码一样,我为啥不直接pth呢)

因此在这种场景下的攻击手段就是将机器reflect回机器本身。因此微软在ms08-068(这个补丁在CVE-2019-1384(Ghost Potato)被绕过)中对smb reflect到 smb 做了限制,防止了同一主机从SMB协议向SMB协议的Net-NTLMhash relay,禁止直接relay本机的情况下可以尝试使用切换协议来relay

域环境

域环境底下域用户的账号密码Hash保存在域控的 ntds.dit里面。如下没有限制域用户登录到某台机子,那就可以将该域用户relay到另外的设备完成横向移动(需确保目标已经禁用了smb 签名)。相关的工具如下:

  • Responder中的MultiRelayx.py
  • Impacket中的smbrelayx.py
  • Impcaket中的ntlmrelayx.py

ews relay

ews是Exchange Web Services的缩写,默认情况下,Exchange中一的些服务(MAPI,RPC和EWS)支持NTLM身份验证,攻击者就可以通过触发NTLM认证来执行relay攻击,整个就可以叫做 ews relay。

可以通过首先使用 ExchangeRelayX 来确定服务器是否支持NTLM认证,如果支持再进行后续的攻击操作,细节可以参考:https://pentestlab.blog/2019/09/09/microsoft-exchange-ntlm-relay/

relay ldap

LDAP(Lightweight Directory Access Protocol)(轻量目录访问协议),通过IP协议提供访问控制和维护分布式信息的目录信息,在windows中LDAP的实现就是Active Directory,其中存储着整个域内所有的计算机,用户等的所有信息。在daiker 描述的利用场景中主要是操作用户,其中有些操作现在还不理解,先放着后面再看吧。

ntlm relay 防御

SMB Signing

SMB签名开启的情况下可能认证能给成功,但是认证完毕之后无法进行别的操作,因为在开启签名的情况下,需要使用一个客户端和服务端都知道的key 对后续所有的操作进行加密,攻击者由于没有key,也没法对内容进行加密解密,所以也就没办法进行Relay,最多只能将流量原封不动转发过去。在域内的默认设置是仅在域控制器上启用,域成员机器并没有启用。对于一些开启签名的机器可以通过CVE-2015-0005进行绕过

EPA

Extended Protection for Authentication,增强的身份认证保护,大概的意思就是在原有的认证基础上加上额外的身份识别信息以防止relay攻击,具体方法包括Channel Binding和 Service Binding

pass the hash

即hash传递,又称pth,这类攻击的利用原理是利用了我们前面讲的ntlm response的生成特点,因为NTLM 验证过程中在 type 3 阶段计算 response 的时候客户端是使用用户的 hash 进行计算的而不是用户密码进行计算的。因此在向用户端模拟用户登录的时候是不需要用户明文密码的只需要用户 hash(注意pth需要利用的是ntlm hash,并不是Net-NTLM hash)。

  1. mimikatz
  2. impacket
  3. msf
  4. CobalStrike

信息收集

ntlm协议的认证过程中type2返回challenge时也会返回很多服务器的信息,因此可以利用ntlm的交互特点来收集信息,已有实现工具包括:msf 中的 smb_version、python的smb-version

总结

本文就根据前人的文章自己学习吸收下,因为涉及到的理论和概念还挺多,实际操作环境搭建有点费时间,所以这里就先不进行实际操作了,后续随着另外知识的学习深入再回头来深入学习。

参考链接

https://www.freebuf.com/articles/244375.html

https://daiker.gitbook.io/windows-protocol/ntlm-pian

https://www.freebuf.com/articles/system/224171.html

http://davenport.sourceforge.net/ntlm.html

https://3gstudent.github.io/3gstudent.github.io/Windows%E4%B8%8B%E7%9A%84%E5%AF%86%E7%A0%81hash-NTLM-hash%E5%92%8CNet-NTLM-hash%E4%BB%8B%E7%BB%8D/