GraphRunner:针对Microsoft 365的后渗透工具集

GraphRunner是一款专为Microsoft 365设计的后渗透工具集,利用Microsoft Graph API进行侦察、持久化和数据窃取,支持PowerShell和GUI操作,适用于红队和蓝队安全评估。

GraphRunner:针对Microsoft 365的后渗透工具集

简介

我们开发了一个名为GraphRunner的后渗透工具集,用于与Microsoft Graph API交互。该工具集提供多种功能,包括对Microsoft Entra ID(Azure AD)账户进行侦察、持久化和数据窃取。以下是主要功能概述。在博客文章末尾,我们还提供了一些潜在的攻击路径场景,这些场景对进攻和防御安全团队成员都可能很有价值。

主要功能

  • 搜索和导出电子邮件
  • 搜索和导出用户可访问的SharePoint和OneDrive文件
  • 搜索用户可见的所有Teams聊天和频道,并导出完整对话
  • 部署恶意应用
  • 发现配置错误且暴露的邮箱
  • 克隆安全组以实施水坑攻击
  • 查找可由当前用户直接修改的组,或滥用成员资格规则以获取访问权限的组
  • 在所有用户属性中搜索特定术语
  • 利用基于Graph API构建的GUI窃取用户账户数据
  • 转储条件访问策略
  • 转储应用注册和外部应用,包括同意和范围信息,以识别潜在恶意应用
  • 在同意授予攻击期间完成OAuth流的工具
  • 持续刷新令牌包
  • GraphRunner不依赖任何第三方库或模块
  • 支持Windows和Linux

GraphRunner可在以下地址找到:https://github.com/dafthack/GraphRunner/

Graph API

Microsoft Graph API无疑是支持Microsoft云服务运行的最重要基础设施之一。从Outlook到SharePoint、Teams再到Entra ID,一切都依赖此API。大多数情况下,当您与Microsoft服务交互时,您不会直观地看到Graph API,但在底层,它一直被使用。有PowerShell模块使用它,例如MSOnline或AzureAD模块。AZ命令行工具(az cli)也使用它。作为管理员,Graph API是在Azure中执行任务的非常强大的工具。

但作为普通用户呢?

在渗透测试、红队演练、云评估和其他进攻性安全评估期间,我们经常获得M365用户账户的访问权限。这可能是由于密码喷洒或网络钓鱼等攻击成功所致。通过Web浏览器,我们可能能够访问某些资源,如电子邮件和文件共享服务。但除了电子邮件和文件之外,还可以从Microsoft租户收集许多其他数据点。Azure(Entra)门户是一个很好的起点,但它可以轻松锁定,以便只有管理用户才能使用。

幸运的是,Microsoft 365的大部分功能都需要访问Graph API。即使Azure门户访问被阻止,大部分相同数据仍可通过API访问,并且在某些情况下可以进行交互。通过执行进攻性演练,我们多次遇到这种情况。在探索API提供的功能时,通过实际演练和研发会话,BHIS内部开始开发一个工具集。

在本博客文章中,您将找到我们发布的工具集每个部分的详细描述。此外,我们还提供了几种攻击路径场景,以演示您可能发现此工具集有用的情况。其中一些攻击路径可能很熟悉,而其他可能不熟悉。我们发布此工具集的主要目标是为进攻操作员提供快速识别Microsoft云环境中安全问题所需的工具。但防御者也可以利用此工具主动识别安全问题并加以缓解。

现在,让我们深入了解GraphRunner的全部内容。

GraphRunner的三个主要部分

  1. GraphRunner.ps1 – 一个PowerShell脚本,包含多个用于后渗透侦察、持久化和账户窃取的模块。
  2. GraphRunnerGUI.html – 一个HTML图形用户界面,与访问令牌一起使用。提供围绕枚举和从Outlook、SharePoint、OneDrive和Teams等服务窃取数据的各种模块。
  3. PHPRedirector – 一个基本的PHP脚本,可用于在OAuth同意流期间捕获OAuth授权代码,以及一个Python脚本来自动完成流以获取访问令牌。

GraphRunner PowerShell

GraphRunner包括一组PowerShell工具,用于在Microsoft Entra ID(Azure AD)租户的后渗透期间协助执行各种攻击。大多数模块依赖于经过身份验证的访问令牌。为了协助这一点,有多个模块用于获取和处理用户和应用程序(服务主体)令牌。大多数模块不需要特权账户。

要开始使用,请将GraphRunner导入新的PowerShell会话。

1
Import-Module .\GraphRunner.ps1

以下是PowerShell脚本中包含的每个模块的高级摘要:

身份验证

  • Get-GraphTokens – 以用户身份向Microsoft Graph进行身份验证
  • Invoke-RefreshGraphTokens – 使用刷新令牌获取新的访问令牌
  • Get-AzureAppTokens – 以应用程序身份完成OAuth流以获取访问令牌
  • Invoke-RefreshAzureAppTokens – 使用刷新令牌和应用程序凭据刷新令牌
  • Invoke-AutoTokenRefresh – 按间隔刷新令牌

侦察和枚举模块

  • Invoke-GraphRecon – 执行一般侦察,获取组织信息、用户设置、目录同步设置等
  • Invoke-DumpCAPS – 获取条件访问策略
  • Invoke-DumpApps – 获取应用注册和外部企业应用,以及同意和范围信息
  • Get-AzureADUsers – 获取用户目录
  • Get-SecurityGroups – 获取安全组和成员
  • Get-UpdatableGroups – 获取可能由当前用户修改的组
  • Get-DynamicGroups – 查找动态组并显示成员资格规则
  • Get-SharePointSiteURLs – 获取当前用户可见的SharePoint站点URL列表
  • Invoke-GraphOpenInboxFinder – 检查列表中每个用户的收件箱是否可读
  • Get-TenantID – 从域名检索租户GUID

持久化模块

  • Invoke-InjectOAuthApp – 将应用注册注入租户
  • Invoke-SecurityGroupCloner – 克隆安全组,使用相同的名称和成员列表,但也可以注入其他用户
  • Invoke-InviteGuest – 邀请访客用户到租户
  • Invoke-AddGroupMember – 向组添加成员

窃取模块

  • Invoke-SearchSharePointAndOneDrive – 搜索用户可见的所有SharePoint站点和OneDrive驱动器
  • Invoke-ImmersiveFileReader – 使用沉浸式阅读器打开受限文件
  • Invoke-SearchMailbox – 能够对用户邮箱进行深度搜索,并可以导出消息
  • Invoke-SearchTeams – 可以搜索当前用户可读的所有频道中的所有Teams消息
  • Invoke-SearchUserAttributes – 在目录中的所有用户属性中搜索术语
  • Get-Inbox – 从邮箱获取最新的收件箱项目,可用于读取其他用户邮箱(共享)
  • Get-TeamsChat – 下载完整的Teams聊天对话

Invoke-GraphRunner模块

  • Invoke-GraphRunner – 运行Invoke-GraphRecon、Get-AzureADUsers、Get-SecurityGroups、Invoke-DumpCAPS、Invoke-DumpApps,然后使用default_detectors.json文件通过Invoke-SearchMailbox、Invoke-SearchSharePointAndOneDrive和Invoke-SearchTeams进行搜索。

补充模块

  • Invoke-AutoOAuthFlow – 自动化OAuth流完成,以在用户同意应用注册时获取访问和刷新密钥
  • Invoke-DeleteOAuthApp – 删除OAuth应用
  • Invoke-DeleteGroup – 删除组
  • Invoke-RemoveGroupMember – 从组中删除用户/成员的模块
  • Invoke-DriveFileDownload – 能够以当前用户身份从SharePoint和OneDrive下载单个文件
  • Invoke-CheckAccess – 检查令牌是否有效
  • Invoke-HTTPServer – 一个基本的Web服务器,用于访问从Invoke-SearchMailbox输出的emailviewer
  • Invoke-BruteClientIDAccess – 针对MSGraph测试不同的client_id以确定权限
  • Invoke-ImportTokens – 从其他工具导入令牌以在GraphRunner中使用
  • Get-UserObjectID – 检索用户的Object ID

身份验证

一个好的起点是使用Get-GraphTokens模块进行身份验证。此模块将启动设备代码登录,允许您从浏览器会话对PowerShell会话进行身份验证。访问和刷新令牌将写入全局$tokens变量,您的租户ID将写入$tenantid变量。要与其他GraphRunner模块一起使用它们,请使用Tokens标志(示例:Invoke-DumpApps -Tokens $tokens)。

访问令牌通常有一小时的过期时间,因此偶尔需要刷新它们。如果您已经运行了Get-GraphTokens命令,当您运行Invoke-RefreshGraphTokens以获取新的一组令牌时,您的刷新令牌将自动从$tokens变量中使用。

GraphRunner还包括用于以服务主体身份进行身份验证的模块。这对于利用应用注册(如本博客文章后面持久化部分所述)非常有用。Get-AzureAppTokens模块可以协助完成OAuth流以获取Azure应用注册的访问令牌。获取授权代码后,可以将其与一组应用注册凭据(客户端ID和机密)一起使用以完成流。

侦察和枚举

GraphRunner包括许多侦察模块,用于确定配置设置、列出对象和识别租户中的攻击路径。Invoke-GraphRecon模块收集有关租户的一般信息,包括主要联系信息、目录同步设置和用户设置,例如用户是否有能力创建应用、创建组或同意应用。显示租户的主要联系信息以及目录同步设置和用户设置。

授权策略部分包括配置设置,例如用户是否可以读取自己的Bitlocker密钥、谁可以邀请外部用户、是否阻止MSOL PowerShell等。

Invoke-GraphRecon模块还有一个名为“PermissionEnum”的开关。如果设置此开关,它将使用未记录的“Estimate Access”API暴力破解近400个操作列表(权限参考:https://learn.microsoft.com/en-us/azure/active-directory/roles/permissions-reference)以确定当前用户允许执行哪些操作。这对于发现您的用户能够在租户中执行的独特操作非常有用。此外,当我们在博客文章后面进入组编辑部分时,此方法有助于确定可能已更改的访问权限。

Invoke-DumpCAPS模块从租户转储条件访问策略。此模块使用旧的Azure Active Directory Graph API(graph.windows.net)来拉取策略。

本博客文章后面详细介绍了围绕注入应用注册的模块(Invoke-InjectOAuthApp),这促使创建了Invoke-DumpApps模块。此模块可以协助识别恶意应用注册。它将从租户转储Azure应用注册列表,包括权限范围和已同意应用的用户。此外,它将列出不由当前租户或Microsoft主应用租户拥有的外部应用。这是一种找到用户可能已同意的第三方外部应用的方法。

Get-AzureADUsersGet-SecurityGroups模块可用于从租户转储用户和组。

基于组的攻击是GraphRunner功能中更值得关注的领域之一。我们攻击M365组的第一个用例涉及更改某些组的成员资格,即使作为非管理用户。例如,GraphRunner有模块帮助利用Microsoft 365组的默认行为是组织中的任何人都可以加入它们的事实。每当创建团队时,也会创建Microsoft 365组。随之而来的是自动创建SharePoint站点、邮箱、Teams频道等。

如Microsoft文档中所述(下图),Microsoft 365组的默认行为使它们对所有人开放。此外,请注意,在某些情况下,安全组也可以配置为可加入。

这就是Get-UpdatableGroups模块的用武之地。此模块还利用“Estimate Access”API来确定您的当前用户是否有能力更新租户中的组。它将收集租户中的所有组并逐一检查以确定它们是否可修改。

如果您找到可修改的组,这意味着您的当前用户有能力向该组添加成员,包括您自己、其他租户成员甚至访客。这可能导致权限提升场景,如我们在文章后面的攻击路径部分所示。

类似地,“动态组”是Microsoft 365中另一个有趣的攻击路径。动态组是使用动态组成员资格规则创建的组。创建时,动态组配置有一组规则,自动将具有某些属性的对象处理到组中。这些组可以包括各种参数,例如用户的电子邮件、位置、职位、设备等。它们可以帮助自动将用户添加到组中,但配置错误时可能被攻击者滥用。

在上面的示例中,此动态组配置为添加其用户主体名称包含“admin”一词的任何用户。可以通过简单地邀请具有包含“admin”的电子邮件地址的访客用户到租户来利用此场景。在作为访客添加到租户后,名称中包含“admin”的账户将自动添加到动态组。

GraphRunner通过Get-DynamicGroups模块帮助查找动态组。在列出租户中的动态组后,需要分析成员资格规则以确定可利用的潜力。

Get-SharePointSiteURLs模块与前面提到的组模块齐头并进。它使用Graph Search API尝试定位用户有权访问的所有唯一站点。在执行任何基于组的滥用之前和之后运行它可能有用,以确定您获得了哪些新站点的访问权限。

2017年,我(Beau)写了一篇关于滥用Exchange邮箱权限的文章。当时,我为MailSniper编写了一个名为Invoke-OpenInboxFinder的模块,协助查找配置为组织中的其他用户可以访问的邮箱。该模块利用Exchange Web Services和Outlook Web Access。事实证明,可以通过Microsoft Graph API执行相同类型的邮箱枚举。GraphRunner有Invoke-GraphOpenInboxFinder模块来执行此任务。

为了使此工作,您需要一个范围限定为Mail.Read.Shared权限或Mail.ReadWrite.Shared权限的令牌。这可以通过同意具有此范围权限的应用程序来实现。一种快速简便的方法是利用Graph Explorer。它是一个众所周知的用于测试Graph API调用的应用程序,您可以在此处同意特定权限:https://developer.microsoft.com/en-us/graph/graph-explorer。同意后,您可以单击“Access token”选项卡查看您的令牌,然后将其设置为GraphRunner会话中的$tokens.access_token变量。

现在对用户列表运行Invoke-GraphOpenInboxFinder模块将尝试访问提供的列表中的每个收件箱。如果用户将其收件箱权限设置得太宽,您的当前用户可能能够读取其收件箱中的消息。

持久化

在维护访问方面,GraphRunner有一些模块可以帮助在租户中建立各种级别的持久化。将应用程序部署到租户在多种场景中都很有趣。默认情况下,用户可以创建应用程序。但默认情况下,他们不能添加管理权限,例如Directory.ReadWrite.All。然而,他们可以添加许多默认不需要管理员同意的委托权限。大多数这些不需要管理员同意的权限用于执行常见任务,例如读取电子邮件(Mail.Read)、列出目录中的用户(User.ReadBasic.All)、导航SharePoint和OneDrive(Files.ReadWrite.All和Sites.ReadWrite.All)等。

通过部署具有这些权限的应用,然后作为我们已入侵的用户同意它,我们可以利用与应用程序绑定的服务主体凭据来访问用户的账户。如果被入侵的用户更改其密码,应用仍然保留对其账户的访问权限。如果被入侵用户的所有会话都被终止,我们仍然有访问权限,直到访问令牌过期(默认为1小时)以操作用户。

Invoke-InjectOAuthApp模块是一个用于自动化将应用注册部署到Microsoft租户的工具。如果Azure门户被锁定,这可能提供额外的应用部署机制,前提是允许用户在租户中注册应用。

此模块有一些硬编码的范围设置,用于快速部署某些类型的应用,但也可以输入自定义值。例如,当将-scope参数设置为“op backdoor”时,该工具将创建一个应用并向其添加大量常见权限,包括对Mail、Files、Teams等的访问。这些权限都不需要管理员同意。

应用部署后,同意URL会自动生成并显示在终端中(上面绿色显示)。此URL是自定义的,并与特定应用注册绑定,包括所有请求的范围项目。当用户访问此URL时,他们将

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计