This blog is part of our Office 365 attack & defense series. We also maintain a Github page where we share our Office 365 tools and queries.
Many organizations are moving (partially) to the cloud. One of the main components is Azure Active Directory (AAD). This is the cloud version of the on-premise Active Directory that many organizations are using or have been using in the past years. The adoption mostly has grown because AAD is required and automatically tied to Office365. But besides basic identity and access functionality, Azure Active Directory offers a ton of functionality. Such as this interesting feature called “app registrations”. This new feature could potentially be abused by attackers. Therefore, it is important to understand the inner workings of such attacks and implement defensive measures.
The app registration feature of Azure AD is a way to grant permissions / authenticate against an Azure Active Directory tenant using an application. Within the app registration it is possible to configure the scope of the permissions that are granted to the application.
Delegated permissions
When creating an app registration, it is possible to assign delegated permissions to access specific resources in the Azure Active Directory tenant on behalf of another user. If a user authenticates through the application, access is granted to the specified resources on behalf of the user account stored in the app registration.
These kinds of features could for example be used to access someone’s email if a victim authenticates into a malicious application. Some proof of concept applications have been published to perform this attack scenario against Microsoft Azure, such as PwnAuth. Generally, an attack follows these steps:
- the attacker creates a malicious multi-tenant app registration with a callback to a webserver controlled by him. The application requests access to the resources he wants to obtain (e.g. reading mail through Microsoft Graph API)
- the victim authenticates in the application (and ignores any messages) and is redirected to the attacker’s webserver including a newly added code value
- the attacker uses the code to get an authorization token
- the attacker uses the authorization token to query the specific resources, for example the Microsoft Graph API to read the users e-mail
Monitoring for abuse
Azure Sentinel can be used to detect a user that consents to an application. The following KQL query can be used to monitor application consent to any application:
AuditLogs
| where OperationName == 'Consent to application'
| extend applicationDetails = parse_json(TargetResources)[0]
| extend appname = parse_json(applicationDetails)['displayName']
| extend scope = parse_json(applicationDetails)['modifiedProperties'][4]["newValue"]
This query can be used to detect more critical consents, with admin privileges:
AuditLogs
| where OperationName == 'Consent to application'
| extend applicationDetails = parse_json(TargetResources)[0]
| extend appname = parse_json(applicationDetails)['displayName']
| extend IsAdmin = parse_json(applicationDetails)['modifiedProperties'][0]["newValue"]
| where IsAdmin == '"True"'
If you want to review all consents that were granted to (external) applications in a tenant, this can be done manually through the Azure portal or through PowerShell. More information on this can be found in the Microsoft documentation here.
Reviewing all the applications manually through the Azure portal or PowerShell can be a time-consuming task. Therefor the author of PwnAuth created a script to hunt for potential malicious apps on multiple characteristics. This is a nice way to identify potentially malicious scripts and perform the further investigation manually for each application through the Azure portal or PowerShell.
Mitigation
Azure AD offers a configuration setting to disable the consent to all apps by users. Disabling this prevents a user granting access to company resources or information through applications.
If you prefer using PowerShell, the following one liner could be used to look up the current value of the setting:
Get-MsolCompanyInformation | select UsersPermissionToUserConsentToAppEnabled
The following PowerShell could be used to disable consent to applications for regular users:
Set-MsolCompanySettings -UsersPermissionToUserConsentToAppEnabled:$false
Application permissions
Another possibility is to assign application permissions to an app registration. These permissions can only be consented by an administrator. After those permissions have been consented, an attacker is able to access the Azure tenant through the application. This requires an attacker to have the application ID, tenant ID and application secret.
This method could be used by an attacker to keep access to an Azure tenant, for example when the admin accounts he obtained access to got locked out. By for example granting the Directory.ReadWrite.all permission to an application, he would be able to modify the directory data such as user and groups through the application. The following steps are required to perform this attack:
- the attacker compromised a tenant and obtained high privileges to the Azure tenant. Using the obtained access, he creates an app registration with applications permissions on the resources he wants persistence access to.
- the attacker grants admin consents to the application
- the attacker generates a certificate / client secret
- whenever the attacker wants to use the obtained access, he could use the certificate or client secret to perform his malicious actions.
Monitoring for abuse
The following Sentinel rule could be used to discover any application being added for further investigation:
AuditLogs
| where (OperationName == "Add application") or (OperationName == "Update application")
PwnAuth describes a default call path in its documentation. It is possible to hunt in sentinel for these kinds of applications being added, using the following query. This query would detect PwnAuth applications being created within the organizations tenant, using the default documentation information:
AuditLogs
| where (OperationName == "Add application") or (OperationName == "Update application")
| extend details = parse_json(TargetResources[0])
| extend properties = parse_json(details["modifiedProperties"][0])
| where properties["newValue"] contains "/oauth/api/microsoft/callback"
The same, earlier mentioned query, could be also used to detect whether an administrator within the tenant consents admin to an application within the tenant:
AuditLogs
| where OperationName == 'Consent to application'
| extend applicationDetails = parse_json(TargetResources)[0]
| extend appname = parse_json(applicationDetails)['displayName']
| extend IsAdmin = parse_json(applicationDetails)['modifiedProperties'][0]["newValue"]
| where IsAdmin == '"True"'
Mitigation
It is possible to disable the possibility to create app registrations by regular users. This prevents non-administrative users from creating apps to access resources through an app registration. It is possible to disable this settings through the Azure portal:
If you prefer using PowerShell, the following one liner could be used to look up the current value of the setting:
Get-MsolCompanyInformation | select UsersPermissionToCreateLOBAppsEnabled
The following PowerShell could be used to disable consent to applications for regular users:
Set-MsolCompanySettings -UsersPermissionToCreateLOBAppsEnabled:$false
Conclusion
Applications are a great way for attackers to obtain access to company resources. If they successfully phish a victim, they are able to obtain access to the organizations resources on their behalf. Also, applications can be used to gain persistent access in an already compromised tenant. If compromised accounts are locked out, but the malicious application is missed, it can still be used as an entry point into the tenant. Also, if registering of applications is allowed within a tenant (which is by default), a non-admin user could create a malicious app within the tenant of an organization, to phish others.
To minimize the chance of above attacks Zolder recommends:
- If you do not require the app functionality, disable the possibility for users to consents to application
- disable registration of apps by non-admin users
- monitor for users consents with suspicious characteristics
- monitor for admin consents, make sure to review every admin consents granted