需要云计算吗? 即刻开始体验

将 DHCP DNS 欺骗武器化 — 实践指南

Ori David

寫於

Ori David

December 21, 2023

Ori David

寫於

Ori David

Ori David is a Security Researcher at Akamai. His research is focused on offensive security, malware analysis, and threat hunting. 

基于本系列博文中介绍的所有功能和技术,我们打造了 DDSpoof — 一种能够实现 DHCP DNS 攻击效果的工具包。

简介

在本系列博文的 第一部分 中,我们介绍了一系列利用 Microsoft 动态主机配置协议 (DHCP) 服务器对 Active Directory 域发起的新攻击。在这种攻击中,攻击者通过滥用 DHCP DNS 动态更新功能,来假冒 Active Directory 集成 DNS (ADIDNS) 区域中的 DNS 记录。我们探讨了该功能的操作,并着重介绍了可能遭到攻击者滥用以假冒敏感 DNS 记录的错误配置。

在第二部分中,我们将深入讲解利用该攻击面所需要的一些技术细节。我们将详细说明用于收集实施攻击所需之必要信息的方法,介绍一些攻击限制,并探讨如何通过滥用一个有意思的 DHCP 服务器行为来假冒多个 DNS 记录。

最后,我们会介绍一款可纳入您工具箱的新工具。我们依据了解到的各种功能和技术,打造了 DDSpoof ,这是一款 Python 工具,有助于红队和蓝队实施和研究 DHCP DNS 攻击。在这篇博文的后半部分,我们将解释如何在几种攻击场景中使用该工具。

免责声明:DDSpoof 可以帮助安全团队识别风险,同时提高对该攻击面的认识。但是,该工具本身并不足以造成实际损害,它需要网络访问和进一步利用漏洞,才能滥用 DNS 欺骗原语。

DHCP 枚举

上一篇博文中,我们分享了 DHCP DNS 欺骗背后的理论。实际上,要想有效执行我们所述的攻击,还需要收集几项信息。凑巧的是,攻击者通过利用 DHCP 协议本身,就能够 发现 DHCP 服务器并了解其配置,使侦查过程变得轻而易举。

在后续部分中,我们将介绍攻击者在未经身份验证的情形中可用于收集这些信息的不同方法和技巧。

识别 DHCP 服务器

DHCP DNS 攻击中最重要的是攻击目标 DHCP 服务器,因此第一步是识别 DHCP 服务器。其实,识别网络中活跃的 DHCP 服务器非常简单。攻击者只需发送 DHCP Discover 广播并检查来自服务器传回的 Offer 响应即可。

要发送 DHCP 报文,我们可以运行 Linux 实用程序 dhclient ,这是一个可配置的 DHCP 客户端,可实现与 DHCP 服务器的交互。我们可通过编辑 dhclient 的配置文件,来配置该实用程序,该文件位于 /etc/dhcp/dhclient.conf

在运行时, dhclient 将向 DHCP 服务器请求网络配置,并将配置应用到我们的计算机,以便覆盖当前的 IP 地址。为避免这种情况,我们可以使用如下语法,在 虚拟接口 上运行该命令:

  dhclient <interface_name>:<virtual_interface_name>

运行该命令后,我们可以看到原始 IP 地址 (172.25.14.55) 保持不变,而虚拟接口则从 DHCP 服务器接收到新的 IP 地址(图 1)。

运行该命令后,我们可以看到原始 IP 地址 (172.25.14.55) 保持不变,而虚拟接口则从 DHCP 服务器接收到新的 IP 地址(图 1)。 图 1:在虚拟接口上使用 dhclient,保留原始 IP

如果我们记录流量并检查 DHCP Offer 报文,将能够识别所有活跃的 DHCP 服务器(图 2)。

如果我们记录流量并检查 DHCP Offer 报文,将能够识别所有活跃的 DHCP 服务器(图 2)。 图 2:发送 DHCP Discover 以识别网络中活跃的 DHCP 服务器

获取 DHCP 服务器的域和 DNS 服务器

在识别出网络中的 DHCP 服务器后,我们还需要知道哪些记录可以通过每个服务器进行假冒。DHCP 服务器只能在其关联的 ADI 区域内创建记录,与“aka.test”域关联的服务器只能写入具有相同后缀的 DNS 记录: <主机名>.aka.test。要了解可以假冒哪些记录,我们需要识别此后缀。

此外,我们还需要知道哪个 DNS 服务器将托管新记录,这样我们就能查询这些记录,验证攻击是否成功。

攻击者可以用来找出这两个参数的一个技巧是“参数请求列表”选项,该选项允许查询 DHCP 服务器以获取特定设置。出于我们的目的,我们可以查询服务器关联的 域名域名 服务器选项。

我们可以再次使用 dhclient。为了将“参数请求列表”选项添加到 Discover 报文中,我们在 dhclient的配置文件中包含了以下行:

  request domain-name, domain-name-servers;

在运行 dhclient (像之前一样,在虚拟接口上运行)并检查 Discover 报文时,我们看到其中包含“参数请求列表”选项并带有我们所请求的字段(图 3)。

在运行 dhclient(像之前一样,在虚拟接口上运行)并检查 Discover 报文时,我们看到其中包含“参数请求列表”选项并带有我们所请求的字段(图 3)。 图 3:DHCP Discover 报文中的“参数请求列表”选项

Microsoft DHCP 侦听服务器应发送对此条 Discover 报文的 Offer 响应,其中包含所请求的参数(图 4)。

Microsoft DHCP 侦听服务器应发送对此条 Discover 报文的 Offer 响应,其中包含所请求的参数(图 4)。 图 4:DHCP 服务器响应中包含我们所请求的设置

推断名称保护状态

在尝试滥用 DHCP DNS 动态更新时,还有一个重要的设置就是名称保护,该设置将决定是否可以实施某些覆盖攻击 。我们无法直接查询名称保护的状态,但可以通过四个简单的步骤来进行推断。

  1. 使用 DHCP DNS 动态更新创建 DNS 记录 

  2. 验证是否已创建 A 记录

  3. 向 DNS 服务器查询同名的 DHCID 记录

  4. 如果 DHCID 记录与 A 记录一起存在,则已启用名称保护

为了使用 dhclient调用 DHCP DNS 动态更新,我们需要将以下行添加到配置文件中:

  send fqdn.fqdn = “kali.aka.test”;
  send fqdn.server-update on;
  send dhcp-server-identifier 172.25.14.123;

前两行添加了 带服务器标记的 FQDN 选项,这是使 DHCP 服务器为我们注册 DNS 记录所需要的。第三行是可选行,它用于添加 服务器标识符 DHCP 选项,以便在有多个 DHCP 服务器的情况下将攻击目标对准特定的 DHCP 服务器。

运行 dhclient后,我们可以使用 nslookup 查询目标 DNS 服务器并查找 DHCID 记录(图 5)。

运行 dhclient 后,我们可以使用 nslookup 查询目标 DNS 服务器并查找 DHCID 记录(图 5)。 图 5:使用 nslookup 验证名称保护状态

在本例中,我们可以看到创建了一个 DHCID 记录,这表明名称保护已启用。

推断 DHCP DNS 动态更新配置

有三个选项决定了 DHCP 服务器会在什么情况下为客户端创建 DNS 记录(图 6)。攻击者如果知道所使用的是哪种设置,就可以嗅探 DHCP 请求,并识别引发 托管记录创建的请求。这样就可以识别 托管记录覆盖 (假冒 DHCP 服务器创建的记录)的潜在目标。

三种可能的设置如下:

  • 仅在客户端请求时进行动态更新。这是默认选项,仅在请求中存在 FQDN 选项并且设置了服务器标记时,才会创建 DNS 记录。

  • 始终进行动态更新。无论服务器标记的值如何,都会为任何带 FQDN 选项的 DHCP 请求创建 DNS 记录。

  • 为不请求更新的客户端进行动态更新。即使不存在 FQDN 选项,也为客户端创建 DNS 记录 — FQDN 基于主机名 DHCP 选项。这是为了支持不使用 FQDN 选项的旧版 DHCP 客户端。

有三个选项决定了 DHCP 服务器会在什么情况下为客户端创建 DNS 记录(图 6)。 图 6:DHCP DNS 动态更新设置

我们可以通过检查“副作用”来推断此设置:我们将在不同条件下触发 DHCP DNS 动态更新,并查询 DNS 服务器以检查是否创建了记录。这可以通过使用 dhclient 租用 IP 地址并使用 nslookup 查询 DNS 服务器来完成。

测试每项可能的设置所需要的 dhclient 配置如下:

为不请求更新的客户端创建记录

  # Only include the hostname option, without the FQDN option
  send host-name = “test.aka.test”;
  send dhcp-server-identifier 172.25.14.123;

始终创建记录(存在 FQDN 选项时)

  # Include the FQDN option, without the server update flag
  send fqdn.fqdn = “test.aka.test”;
  send dhcp-server-identifier 172.25.14.123;

仅在客户端请求时创建记录

  # Include the FQDN option and the server update flag
  send fqdn.fqdn = “test.aka.test”;
  send fqdn.server-update on;
  send dhcp-server-identifier 172.25.14.123;

欺骗性记录的地址限制

为了让攻击有效,我们需要让欺骗性 DNS 记录指向受控的计算机。就 DHCP DNS 欺骗而言,我们需要依靠 DHCP 服务器来创建这些 DNS 记录。遗憾的是,我们不能选择任意 IP 地址 — DHCP 服务器有已定义的内部 IP 地址范围,会拒绝租用任何在此范围之外的 IP 地址(因而也不会为其创建 DNS 记录)。

因此,我们的通信重定向地址有两个限制:

  • 该地址不能在网络外部:我们无法从 DHCP 服务器租用外部 IP 地址,所以在实施欺骗攻击时也无法使用外部 IP 地址。

  • 该地址不能是具有静态 IP 地址的计算机:如果计算机配置了静态 IP 地址,则该地址不太可能在 DHCP 服务器的租用池中,因而在实施欺骗攻击时无法使用。

由于我们可以访问可使用动态 IP 地址的内部计算机,因此我们可将 DHCP 服务器提供的任何地址用于欺骗性记录。

为确保我们在执行附加操作时使用相同的地址,我们可以使用 “请求的 IP 地址” 选项。通过将以下行添加到 dhclient的配置,我们可以做到这一点:

  send dhcp-requested-address 172.25.14.55;

写入多个 DNS 记录

在实施 DHCP DNS 欺骗时,我们很可能希望假冒多个 DNS 记录,而不是单个 DNS 记录,目的是对尽可能多的受害设备的流量进行重定向。但是,在尝试将多个 DNS 记录指向相同的目标 IP 时,我们遇到了问题。

DHCP 服务器将某个 IP 地址租给主机后,该地址就不能再被其他客户端租用。该行为意在防止不同客户端之间的 IP 冲突。在我们租用带特定 FQDN 的 IP 地址来实施 DDSpoof 时,该 IP 地址将从服务器的地址池中被删除。如果我们尝试租用带不同 FQDN 的相同 IP 地址,服务器将提供不同的地址(图 7)。

如果我们尝试租用带不同 FQDN 的相同 IP 地址,服务器将提供不同的地址(图 7)。 图 7:所请求的地址被占用时 DHCP 的租用过程

我们无法通过释放先前租用的地址来解决此问题,因为这样做会触发 DHCP 服务器进行 DNS 动态更新,从而删除刚刚释放的记录,并且会删除之前的欺骗性记录(图 8)。

我们无法通过释放先前租用的地址来解决此问题,因为这样做会触发 DHCP 服务器进行 DNS 动态更新,从而删除刚刚释放的记录,并且会删除之前的欺骗性记录(图 8)。 图 8:DHCP Release 引发关联 DNS 记录的删除

换句话说,我们的目标是:

  • 释放 IP 地址;也就是从 DHCP 服务器删除租用条目,使该地址重新回到地址池中(这样我们就可以用该地址注册新的 DNS 记录)

  • 防止已有的欺骗性 DNS 记录被删除

我们发现一个有趣的行为/错误,利用该行为/错误刚好能够达成我们的目的。

我们向当前租给我们 IP 地址的 DHCP 服务器发送一个 DHCP Request 数据包,其中包含以下参数:

  • 客户端 MAC 地址,用于向服务器请求现有的 DHCP 租用

  • 服务器标识符,用于标识 不同于 目标服务器的服务器

看到此广播报文,目标 DHCP 服务器会“认为”我们正在向另一台服务器请求新的 IP 地址,从而认为我们不再需要现有的(已租用)IP 地址。然后服务器会删除 IP 租用, 但不删除关联的 DNS 记录(图 9)。我们并不清楚为什么不删除 DNS 记录,也许有可能是一个逻辑错误。

然后服务器会删除 IP 租用,但不删除关联的 DNS 记录(图 9)。 图 9:删除租用条目而不删除其关联的 DNS 记录

看看实际操作结果

我们想要创建两个指向相同 IP 的 DNS 记录。我们按照前面所述的相同方式使用 dhclient 创建第一个记录。创建了记录后,查看 DHCP 服务器租用表就可以看到我们的租用情况(图 10)。

创建了记录后,查看 DHCP 服务器租用表就可以看到我们的租用情况(图 10)。 图 10:DHCP 租用表条目

我们现在将配置文件中的 dhcp-server-identifier dhclient 选项修改为任何其他 IP,再次运行 dhclient 就会看到租用已被删除!

现在,我们在请求相同 IP 地址时使用不同的 FQDN 再次运行 dhclient ,即可创建第二个记录(图 11)。

现在,我们在请求相同 IP 地址时使用不同的 FQDN 再次运行 dhclient,即可创建第二个记录(图 11)。 图 11:多个攻击者 DNS 记录指向相同 IP 地址

DDSpoof.py 简介

基于本系列博文中介绍的所有功能和技术,我们打造了 DDSpoof — 一种能够实现 DHCP DNS 攻击效果的工具包。此 Python 工具可执行 DHCP 服务器枚举、执行自定义 DHCP DNS 命令,并识别潜在的欺骗目标。DDSpoof 的功能 记载于此处的资源库中。

在接下来的部分中,我们将研究可以使用 DDSpoof 执行攻击的几种场景。

设置 DDSpoof

我们在没有任何域凭据的情况下,在目标网络内运行 Kali Linux 计算机。我们将首先运行 DDSpoof 以扫描网络并识别潜在目标(指定使用哪个接口发送和接收数据包;图 12)。

我们将首先运行 DDSpoof 以扫描网络并识别潜在目标(指定使用哪个接口发送和接收数据包;图 12)。 图 12:DDSpoof 初始枚举

我们可以看到 DDSpoof 执行以下操作:

  • 识别所有可访问的 DHCP 服务器及其配置

  • 确定名称保护状态

  • 验证我们当前的 IP 地址是否可在目标服务器上租用

在此示例中,我们的 IP 地址在目标服务器上不可租用,所以我们手动将其修改为服务器提供的地址(图 13)。

在此示例中,我们的 IP 地址在目标服务器上不可租用,所以我们手动将其修改为服务器提供的地址(图 13)。 图 13:将我们的 IP 地址修改为 DHCP 服务器上可用的地址

现在我们准备开始执行欺骗攻击。

DHCP DNS 欺骗

为了实施第一次 DHCP DNS 欺骗攻击,我们需要识别失败的名称解析尝试,并创建指向我们计算机的 DNS 记录。为此,我们将使用 start-llmnr DDSpoof 命令。此命令会启动 LLMNR 嗅探器,嗅探器就网络中的 LLMNR 查询发出通知信号,这可以引导我们找到潜在的欺骗目标(图 14)。

此命令会启动 LLMNR 嗅探器,嗅探器就网络中的 LLMNR 查询发出通知信号,这可以引导我们找到潜在的欺骗目标(图 14)。 图 14:使用 DDSpoof 的 LLMNR 嗅探器识别欺骗目标

在这里我们可以看到嗅探器能够识别名称 files.aka.test。现在,我们可以使用 write-record 命令尝试注册该 DNS 名称(图 15)。

现在,我们可以使用 write-record 命令尝试注册该 DNS 名称(图 15)。 图 15:使用 DDSpoof 假冒目标名称的 DNS 记录

正如我们所见,DDSpoof 成功创建了该 DNS 记录,它指向我们的 IP 地址!我们可以使用 nslookup 来验证这一点(图 16)。

正如我们所见,DDSpoof 成功创建了该 DNS 记录,它指向我们的 IP 地址!我们可以使用 nslookup 来验证这一点(图 16)。 图 16:使用 nslookup 确认记录创建成功

下一次网络中的主机尝试解析名称 files.aka.test时,将被定向到受控的计算机。

完成攻击后,我们可以使用 delete-record 命令删除欺骗性记录(图 17)。

完成攻击后,我们可以使用 delete-record 命令删除欺骗性记录(图 17)。 图 17:使用 DDSpoof 删除欺骗性记录

DHCP DNS 覆盖

我们的另一个选择是 DHCP DNS 覆盖。回头看图 12,我们可以看到目标 DHCP 服务器也是 DNS 服务器。这表明该服务器也可能是域控制器 (DC),因为 DNS 服务器通常安装在 Active Directory 环境中的 DC 上。我们可以使用以下 nmap 命令来验证这一点:

  Nmap -p389 -sV 172.25.14.123
结果证实了我们的怀疑(图 18)。 图 18:Nmap 输出确认服务器是域控制器

如果未配置 DNS 凭据,我们就可以覆盖 ADI 区域中的任何记录。假设我们识别到名为 file-server.aka.test 的主机(图 19)。

假设我们识别到名为 file-server.aka.test 的主机(图 19)。 图 19:使用 nslookup 查询 file-server.aka.test 的结果

我们可以尝试使用 write-record DDSpoof 命令覆盖其 DNS 记录。如果配置了弱 DNS 凭据,此操作应该会失败。但是,在本例中,未配置弱 DNS 凭据,因此我们覆盖成功(图 20)。

我们可以再次使用 nslookup 来验证覆盖是否成功(图 21)。 图 20:使用 DDSpoof 对 file-server 的 DNS 记录执行 DHCP DNS 覆盖
我们可以再次使用 nslookup 来验证覆盖是否成功(图 21)。 图 21:使用 nslookup 确认覆盖成功

绕过名称保护

在另一个场景中,我们运行 start-dhcp DDSpoof 命令来嗅探 DHCP 流量,识别 DHCP Request 报文(图 22)。

在另一个场景中,我们运行 start-dhcp DDSpoof 命令来嗅探 DHCP 流量,识别 DHCP Request 报文(图 22)。 图 22:使用 DDSpoof 的 DHCP 嗅探器识别潜在的托管记录

在此例中,我们识别到名为 ubuntu-server.aka.test 的计算机,该计算机发送了包含其 FQDN 的 DHCP 请求。这可以让 DHCP 服务器为其创建 DNS 记录,从而提供了 托管记录覆盖 的机会(我们回顾一下,托管记录是为非 Windows 主机创建的,因为这些主机不是域的一部分,无法直接与 DNS 服务器通信)。

但有一个问题,这次我们的目标 DHCP 服务器已启用名称保护(图 23)。

我们的目标 DHCP 服务器已启用名称保护(图 23)。 图 23:DDSpoof 对启用了名称保护的 DHCP 服务器进行枚举

如果我们查询目标 ubuntu-server.aka.test的所有 DNS 记录,会发现确实存在 DHCID 记录(图 24)。

如果查询目标 ubuntu-server.aka.test 的所有 DNS 记录,我们会发现确实存在 DHCID 记录(图 24)。 图 24:nslookup 输出中包含 DHCID 记录

但不用担心,因为我们 已经知道名称保护很容易被绕过!

我们只需发送一条 DHCP Release 报文并在其中添加与原始记录所有者匹配的客户端 ID (CID)(本质上是客户端 MAC 地址)即可。这会导致 DHCP 服务器删除前述记录。

为此,我们可以使用 set-cid 命令。我们向服务器提供之前获得的目标 CID,借此让 DDSpoof 冒充原始 DHCP 客户端。之后,我们可以运行 delete-record 命令来删除目标记录(图 25)。

之后,我们可以运行 delete-record 命令来删除目标记录(图 25)。 图 25:使用 DDSpoof 删除处于名称保护状态的 DNS 记录

现在,只需使用 write-record 命令就可以注册我们想要的名称(图 26)。

现在,只需使用 write-record 命令就可以注册我们想要的名称(图 26)。 图 26:使用 DDSpoof 在删除原始记录后创建新记录,绕过名称保护

总结

在这篇博文中,我们探讨了几种攻击场景,并演示了如何在未经身份验证的情形中假冒 Active Directory 域中的各种 DNS 记录。这种功能非常灵活,攻击者可以通过多种方式进行滥用,包括:

  • 以 Windows 计算机为目标,拦截 NTLM 或 Kerberos 身份验证,从而实现进一步的中继攻击或暴力破解攻击

  • 以运行不安全协议的应用程序为目标,拦截敏感数据

  • 以内部安全服务器(例如防病毒服务器或 SIEM)的 DNS 记录为目标,阻止对这些记录的访问

这些只是攻击者滥用这种功能的几个例子;还有很多其他的滥用方式。

给安全团队的建议

DHCP DNS 动态更新暴露的攻击面影响巨大,而且由于 Microsoft 不打算解决此问题,所以风险可能会持续存在。我们建议安全团队最好在攻击者开始行动之前,使用以下工具来识别和降低 DHCP DNS 欺骗的风险:

  • Invoke-DHCPCheckup:识别 Active Directory 中的 DHCP 和 DNS 配置

  • DDSpoof:明确风险并测试安全系统对 DHCP DNS 动态更新攻击面的抵御能力



Ori David

寫於

Ori David

December 21, 2023

Ori David

寫於

Ori David

Ori David is a Security Researcher at Akamai. His research is focused on offensive security, malware analysis, and threat hunting.