2020-10-16 14:57:0611008人阅读
在渗透测试期间,为了提高审核员对信息系统的权限,很多人都会选择横向移动方法。在这种情况下,称为Pass The Hash(传递哈希)的技术被广泛应用,使审核员成为计算机上的管理员。
NTLM协议
NTLM协议是在Microsoft环境中使用的一种身份验证协议,特别是,它允许用户向服务器证明自己是谁,以便使用该服务器提供的服务。
注意:在本文中,术语“服务器”是在客户端/服务器意义上使用的,“服务器”很可能是一个工作站。
有两种可能的情况:
1. 用户使用服务器的本地帐户的凭据,在这种情况下,服务器在其本地数据库中便含有用户的秘密,将能够对用户进行身份验证。
2. 在Active Directory环境中,用户在身份验证期间使用域帐户,在这种情况下,服务器必须要求域控制器验证用户提供的信息。
在这两种情况下,身份验证都是从客户端和服务器之间的挑战/响应阶段开始的。
挑战/响应
使用挑战/响应原则,以便服务器验证用户是否知道他正在验证的帐户的秘密,而不需要通过网络传递密码。这被称为零知识证明。整个过程分3步:
1.协商:客户端告诉服务器它想要对其进行身份验证(NEGOTIATE_MESSAGE)。
2.挑战:服务器向客户端发送一个挑战。这只不过是一个64位的随机值,随每个身份验证请求而变化(CHALLENGE_MESSAGE)。
3.响应:客户端使用其密码的哈希版本作为密钥加密先前接收到的挑战,并将此加密版本连同其用户名和域(AUTHENTICATE_MESSAGE)返回给服务器。
你可以看到用户管理员试图连接到计算机LKAPP01.lion.king。
NTLM交换框顶部是红色的,底部是服务器响应CHALLENGE_MESSAGE中包含的信息。在这些交换之后,服务器拥有两件东西:
1. 发送给客户端的挑战;
2. 客户端的响应被自身的秘密加密了。
要完成身份验证,服务器只需检查客户端发送的响应的有效性。但在那之前,让我们来检查一下客户的秘密。
身份验证的秘密
我们说过,客户端使用一个哈希版本的密码作为密钥,原因如下:为了避免在服务器上以明文形式存储用户密码,它是存储的密码的哈希值。现在,此哈希是NT哈希,它不过是MD4函数的结果,不含盐值。
NThash = MD4(password)
综上所述,当客户端进行身份验证时,它使用其密码的MD4指纹来加密挑战。然后,让我们看看接收到此响应后服务器端会发生什么。
身份验证
如前所述,有两种不同的身份验证情况。首先,用于身份验证的帐户是一个本地帐户,因此服务器知道这个帐户,并拥有该帐户的秘密副本。第二种是使用域帐户,在这种情况下服务器不知道这个帐户或它的秘密,它必须将身份验证委托给域控制器。
本地帐户
在使用本地帐户进行身份验证的情况下,服务器将使用用户的密钥(更确切地说是用户秘密的MD4哈希) 对发送给客户端的挑战进行加密。然后,它将检查其操作的结果是否等于客户端的响应,从而证明用户拥有正确的秘密。如果没有,则用户使用的密钥不是正确的,因为挑战的加密没有给出预期的密钥。
为了执行此操作,服务器需要存储本地用户及其密码的哈希。这个数据库的名称是SAM(安全帐户管理器)。可以在注册表中找到SAM,特别是使用regedit工具时,但只能作为系统访问。不过,还可以使用psexec打开:
psexec.exe -i -s regedit.exe
副本也位于C:\Windows\System32\SAM的磁盘上,因此,它包含本地用户列表及其哈希密码,以及本地组列表。更准确地说,它包含了哈希的加密版本。但是,由于解密它们所需的所有信息也在注册表(SAM和SYSTEM)中,所以我们可以肯定地说哈希存储在其中。如果你想了解解密机制是如何工作的,你可以查看secretsdump.py代码或Mimikatz代码。
可以备份SAM和SYSTEM数据库,以提取用户的哈希密码数据库。
首先,我们将两个数据库保存在一个文件中。
reg.exe save hklm\sam save.save reg.exe save hklm\system system.save
然后,我们可以使用secretsdump.py来提取这些哈希。
secretsdump.py -sam sam.save -system system.save LOCAL
以上就是整个验证过程。
由于服务器发送了挑战(1),并且客户端使用其秘密的哈希值对该挑战进行加密,然后使用其用户名(2)将其发送回服务器,因此服务器将在其SAM中查找用户密码的哈希值数据库(3)。收到挑战后,它还将加密先前使用此哈希(4)发送的挑战,并将其结果与用户返回的挑战进行比较。如果相同(5),则说明用户已通过身份验证!否则,用户没有提供正确的秘密。
域帐户
当使用域帐户进行身份验证时,用户的NT哈希不再存储在服务器上,而是存储在域控制器上。用户希望对其进行身份验证的服务器接收其挑战的答案,但无法检查该答案是否有效。它将把这个任务委托给域控制器。
为此,它将使用Netlogon服务,该服务能够与域控制器建立安全连接。此安全连接称为安全通道,之所以可以进行这种安全连接,是因为服务器知道自己的密码,而域控制器也知道服务器密码的哈希值,他们可以安全地交换会话密钥并安全地进行通信。
我不会详细介绍,但是想法是服务器将以NETLOGON_NETWORK_INFO的结构将不同的元素发送到域控制器:
1. 客户端的用户名(Identity);
2. 先前发送给客户端的挑战(LmChallenge);
3. 客户端发送的对挑战的响应(NtChallengeResponse)。
域控制器将在其数据库中查找用户的NT哈希,对于域控制器,它不在SAM中,因为它是一个试图进行身份验证的域帐户。这次它位于一个名为NTDS.DIT的文件中,该文件是所有域用户的数据库。检索NT哈希后,它将使用该哈希和挑战计算预期的响应,并将此结果与客户的响应进行比较。
然后,一条消息将被发送到服务器(NETLOGON_VALIDATION_SAM_INFO4),指示客户端是否经过身份验证,它还将发送一组关于用户的信息。这与使用Kerberos身份验证时在PAC中发现的信息相同。
以下就是一个域控制器的验证过程:
与以前一样,服务器发送挑战(1),客户端使用其秘密的哈希值对该挑战进行加密,并将其连同用户名和域名一起发送回服务器(2)。这次服务器将使用Netlogon服务(3)在安全通道中将此信息发送到域控制器。掌握了这些信息后,域控制器还将使用在其NTDS.DIT数据库(4)中找到的用户哈希来对挑战进行加密,然后将其结果与用户返回的结果进行比较。如果相同(5),则对用户进行身份验证。否则,用户未提供正确的秘密。在这两种情况下,域控制器都将信息发送到服务器(6)。
NT哈希的安全隐患
在这些交换中从来不使用明文密码,而是使用名为NT哈希的哈希密码,它是明文密码的简单哈希。
仔细想想,窃取明文密码或窃取哈希值是完全相同的。因为它是用来响应挑战/响应的哈希,所以拥有该哈希可以对服务器进行身份验证。因此,将密码以明文显示根本没用。
可以这么说,在大多数情况下,使用NT哈希与使用明文密码是一样的。
传递哈希
如果攻击者知道一台计算机的本地管理员的NT哈希,那么他可以使用这个哈希轻松地对该计算机进行身份验证。类似地,如果他拥有主机上本地管理组成员的域用户的NT哈希,他也可以作为本地管理员向该主机进行身份验证。
本地管理员
现在,让我们看看它在实际环境中是如何工作的:一名新员工来到公司,公司为他/她提供了一个工作站。IT部门没有足够的时间为每个员工从头安装和配置Windows系统。因此,先设置一个安装和配置Windows系统的版本,以满足一个新员工的所有基本需求和要求。然后,这个称为master的基本版本保存在某处,并且该版本的副本提供给每个新手。
这意味着,本地管理员帐户在所有使用相同主服务器初始化的工作站中是相同的。如果其中一台主机被破坏,并且攻击者从工作站的本地管理员帐户提取NT哈希,因为所有其他工作站都具有相同的管理员帐户和相同的密码,那么它们也将具有相同的NT哈希。然后,攻击者可以使用在受损主机上找到的哈希,并在所有其他主机上重播该哈希,以便在这些主机上进行身份验证,以上的整个过程就叫做传递哈希。
例如,我们发现用户管理员的NT哈希是20cc650a5ac276a1cfc22fbc23beada1。我们可以在另一台计算机上重播它,并希望这台计算机以同样的方式配置。以下示例使用来自Impacket套件的psexec.py工具:
没错,这个哈希也可以在新主机上使用,而且我们在它上面有一个管理员shell。
特权域帐户
还有另一种使用传递哈希技术的方法,假设对于远程公园管理,在Active Directory中有一个“HelpDesk”组。为了使该组的成员能够管理用户的工作站,将该组添加到每个主机的本地“Administrators”组中。此时,这个本地组包含在计算机上具有管理权限的所有对象中。
你可以使用以下命令列出它们:
# Machine française net localgroup Administrateurs # ~Reste du monde net localgroup Administrators
结果将是这样的:
Nom alias Administrateur Commentaire Les membres du groupe Administrateurs disposent d'un accès complet et illimité à l'ordinateur et au domaine Membres ------------------------- Administrateur ADSEC\Admins du domaine ADSEC\HelpDesk
因此,我们拥有ADSEC \ HelpDesk域组,该域组是主机的本地管理员组的成员。如果攻击者从该组中的一个成员那里窃取了NT哈希,则他可以使用管理员列表中的ADSEC \ HelpDesk在所有主机上进行身份验证。
与本地帐户相比,其优势在于,无论使用什么主机来设置计算机,GPO都会将该组添加到主机的配置中。该帐户具有更广泛的管理权限的可能性更大,而与操作系统和计算机设置过程无关。
因此,当请求身份验证时,服务器会将身份验证委派给域控制器,如果身份验证成功,则域控制器将向服务器发送有关用户的信息,例如用户名,用户所属的组列表,密码到期日期等。
然后,服务器将知道该用户是HelpDesk组的一部分,并向该用户授予管理员访问权限。
另一个示例:我们发现用户jsnow的NT哈希为89db9cd74150fc8d8559c3c19768ca3f。此帐户是HelpDesk组的一部分,该组是所有用户工作站的本地管理员,让我们在另一台主机上使用他的哈希。
同样,身份验证成功了,我们成为了目标设备的管理员。
自动化
既然我们已经了解了NTLM身份验证的工作方式,以及为什么可以使用NT哈希对其他主机进行身份验证,那么通过并行化任务来自动对不同目标进行身份验证以获取尽可能多的信息将是非常有用的。
在此,我建议使用CrackMapExec工具。
# Compte local d'administration crackmapexec smb --local-auth -u Administrateur -H 20cc650a5ac276a1cfc22fbc23beada1 10.10.0.1 -x whoami # Compte de domaine crackmapexec smb -u jsnow -H 89db9cd74150fc8d8559c3c19768ca3f -d adsec.local 10.10.0.1 -x whoami
以下就是以simba用户为管理员的示例说明:
传递哈希是在一些计算机上执行,然后计算机随后遭到破坏。已经向CrackMapExec传递了一个参数,来列出当前登录到这些计算机上的用户。
拥有连接的用户列表很好,但是拥有他们的密码或NT哈希会更好!为此,我开发了lsassy,——远程提取lsass秘密的工具。
我们从连接的用户中检索所有NT哈希,由于我们已经是这些计算机的管理员,所以不会显示来自计算机帐户的文件。
传递哈希限制
传递哈希值是一项在服务器上启用NTLM身份验证时始终有效的技术,默认情况下,该技术是有效的。但是,Windows中有一些机制可以限制或可能限制管理任务。
在Windows上,使用访问令牌执行权限管理,从而可以知道谁有权做什么。“Administrators”组的成员有两个令牌。一个具有标准用户权限,另一个具有管理员权限。默认情况下,当管理员执行任务时,它是在标准的、有限的上下文中执行的。另一方面,如果需要管理任务,那么Windows将显示这个称为UAC(用户帐户控制)的众所周知的窗口。
可以看到出现用户警告:应用程序请求管理权限。
那么远程执行的管理任务是什么呢?有两种可能。
1. 属于主机“Administrators”组成员的域帐户都可以请求它们,在这种情况下,不会为此帐户激活UAC,他可以执行其管理任务。
2. 是由主机的“Administrators”组成员的本地帐户请求的,在这种情况下,UAC在某些情况下是启用的,但不是一直启用。
为了理解第二种情况,让我们看一下两个注册表项,这两个注册表项有时是未知的,但是当使用本地管理帐户进行NTLM身份验证后尝试执行管理任务时,有两个注册表项(LocalAccountTokenFilterPolicy,FilterAdministratorToken)扮演了关键角色。
下表总结了这两个注册表项的每种组合,每种组合都可以通过主机的身份验证。
总结
如今,NTLM身份验证仍在公司中广泛使用。以我的经验,我从未见过能够在整个网络上禁用NTLM的环境。这意味着,传递哈希的攻击仍然非常有效。
该技术是NTLM协议固有的,但是可以通过避免在所有工作站上使用相同的本地管理密码来缓解。微软的LAPS 解决方案是其中一种解决方案,它可以通过确保所有工作站上的密码(也包括NT哈希)都不同。
本文翻译自:https://en.hackndo.com/pass-the-hash/