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

GraphRunner是一款专为Microsoft 365设计的后渗透工具集,通过Microsoft Graph API实现侦察、持久化和数据窃取功能,支持PowerShell和GUI操作,适用于红蓝队评估云环境安全。

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

作者:Beau Bullock & Steve Borosh

摘要

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

主要功能

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

工具下载地址:https://github.com/dafthack/GraphRunner/

Graph API

Microsoft Graph API是支持Microsoft云服务运行的核心基础设施之一。从Outlook到SharePoint、Teams再到Entra ID,都依赖此API。尽管用户通常不会直接看到Graph API,但它一直在后台运行。PowerShell模块(如MSOnline或AzureAD模块)和AZ命令行工具(az cli)都使用它。对管理员而言,Graph API是在Azure中执行任务的强大工具。

普通用户的视角

在渗透测试、红队演练、云评估和其他攻击性安全评估中,我们经常获得M365用户账户的访问权限,这可能源于密码喷洒或钓鱼攻击的成功。通过浏览器,我们可以访问电子邮件和文件共享服务等资源,但除了邮件和文件,Microsoft租户中还有许多其他数据点可供收集。Azure(Entra)门户是一个起点,但它可能被锁定,仅允许管理用户使用。

幸运的是,Microsoft 365的大部分功能都需要访问Graph API。即使Azure门户被封锁,通过API仍可访问大部分相同数据,有时还能进行交互。在实际攻防演练中,我们多次遇到这种情况。通过实战演练和研发会议,BHIS内部开始开发这套工具集。

本文详细介绍了工具集的每个部分,并提供了多个攻击路径场景,以展示其应用价值。其中一些路径可能为人熟知,另一些则可能较为新颖。发布此工具集的主要目的是为攻击操作员提供快速识别Microsoft云环境中安全问题的工具,但防御者也可利用它主动识别和缓解安全问题。

GraphRunner的三大组件

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

GraphRunner PowerShell

GraphRunner包含一套PowerShell工具,协助在Microsoft Entra ID(Azure AD)租户后渗透阶段执行各种攻击。大多数模块需要已认证的访问令牌。为此,提供了多个模块来获取和处理用户及应用程序(服务主体)令牌。大多数模块不需要特权账户。

入门指南

将GraphRunner导入新的PowerShell会话:

1
Import-Module .\GraphRunner.ps1

模块概述

认证模块

  • 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-GraphReconGet-AzureADUsersGet-SecurityGroupsInvoke-DumpCAPSInvoke-DumpApps,然后使用default_detectors.json文件通过Invoke-SearchMailboxInvoke-SearchSharePointAndOneDriveInvoke-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 设计