Moving laterally between Azure AD joined machines

This post was co-authored by Nirit Tyomkin (@NiritTyomkin), Microsoft Security researcher

In the last few years we have been dealing with lateral movement in the on-premise domain environment — Bloodhound for example, collects and visualize the possible lateral movements by mapping on-premise Windows machines, local admins and logged on domain users.

I was curious whether moving laterally between Azure AD machines is still possible with similar approach, the short answer is YES! it is possible.

The relations of local admin, that can harvest credentials of other users on a Windows machine and impersonate them, is also happening in Azure AD environment where machines and users are both managed in a cloud environment.

Although dumping credentials is not the only option to impersonate a user, the release of Mimikatz 2.2.0–20190720 is dealing with lsass.exe memory space on Windows 10 (build 17763.615) including Azure AD join machine.

In Azure AD joined machine, the user enters its credentials which are used to authenticate the user in front of Azure AD. To support that, the RC4 credentials are stored in the lsass.exe and Mimikatz 2.2.0 can dump them.

Mimikatz running on Azure AD joined machine

At first, I thought — “great”, Lateral movement is possible with Pass-the-hash or Over-pass-the-hash. However, there is no on-premise domain controller in the Azure AD environment, Kerberos and NTLM are not supported in this environment. Thus, the RC4 has no value without performing BruteForce to get clear credentials.

Before we get to the lateral movement open issue, I’d like to discuss some differences of the Azure AD join machine compare to the on-prem domain joined machine.

First, the Kerberos realm (Domain name) for logged-on user in Azure AD machine is a constant value of “AzureAD” and the username is a FQDN representation of the user and the directory name ’’user@directoryname.onmicrosoft.com’’. For example, using runas.exe from CMD would look as the following on Azure Ad user

Runas /user:AzureAd\User@DirectoryName.onmicrosoft.com cmd

Compared to the same process on AD joined use

Runas /user:DomainName\UserName cmd

Another change is the user account identification — in Active Directory environment, an account is represented with a security identification (SID) both on the DC and in the local SAM on the endpoint. However, in AAD an account is represented with a GUID (AKA “AAD Id”) which is different than the original SID which still represents the account on the endpoint. To overcome this discrepancy and allow AAD accounts to be members of the local groups on a Windows machine, their AAD identification needs to be translated into SID representation.

Apparently, the user’s AAD id is translated to SID by concatenating “S-1–12–1-” to the decimal representation of each section of the AAD Id

[base16(a1)]-[base16(a2)]-[ base16(a3)]-[base16(a4)]S-1–12–1-[base10(a1)]-[ base10(a2)]-[ base10(a3)]-[ base10(a4)]

For example, the representation of

6aa89ecb-1f8f-4d92–810d-b0dce30b6c82 

is

S-1–12–1–1789435595–1301421967–3702525313–2188119011
ID of Azure AD user
Convert the hex ID to Dec to build the users SID

The translated AAD id of both users and groups are used by the local machine SAM database. By default, two AAD administrative roles Global administrator role and Device administrator role and the machine’s owner, the account which performed the AAD join process, are members of the local Administrators groups.

The translated ID as SID representation on Azure AD machine

A short recap on the differences mentioned so far

  • Kerberos and NTLM are not the primer authentication protocol in AAD environment
  • There are new local group admins set by default on AAD joined machine
  • The representation of an AAD user in AAD joined machine’s local SAM is not a valid SID in the directory but a representation of the cloud user ID

Getting back to the lateral movement open question — members of the AAD groups mentioned and the machine’s owner are local administrators by default and therefore can impersonate to system account, dump lsass.exe memory and find other logged on users credentials.

Dumping credentials with Mimikatz on AAD joined machine

The open question is how to impersonate a logged-on user with local admin permissions on AAD joined machine — Token manipulation is probably an option but it is not supported on Windows 10; Pass-The-Ticket, Pass-The-Hash require Kerberos or NTLM negotiation which both are not supported in the Azure AD environment.

Then, I wondered how the authentication between two Windows AAD joined machines works. Apparently, there is a Security-Service-Provider (SSP) supported since Windows Server 2008 R2 and Windows 7 that deals with authentication between two AAD joined machines like in an AAD environment — NEGOEX PKU2U (Public Key Cryptography Based User-to-User)

For those of us who like to see authentication over the network, the SMB2 authentication negotiation is based on the GSS-API extensions challenge response mechanism NEGOEX PKU2U as in the picture below and also in the Network Packets Analysis.

NEGOEX PKU2U is based on Kerberos PKINIT messages, which also used for smart-card authentication in the on-prem directory environment. Upon request to authenticate with a remote AAD joined machine, a user certificate is obtained by the online ID provider (AKA Azure AD), the certificate is issued for a specific user for a timeframe of an hour and is signed with the online ID provider’s CA private key.

To allow the certificate validation, the peer computer obtains the public pair of the online ID certificate during the machine’s joining process. Upon Kerberos application request for validating a user’s authenticity, the remote Windows machine, validates the sign timestamp and random data (aka “authenticator”) using the CA paired public key will be used to validate the user’s certificate authenticity.

CA authority on the server
Client certificate with private key

Because Mimikatz is able to dump the client’s certificate and it’s private key using local admin rights, once you obtain these credentials it would be trivial to impersonate the user over NEGOEX PKU2U. Impersonating a computer account from another computer seem to be more feasible as computer account’s certificate is valid for longer time of one year, but I’m not sure what would it let you do in the domain

Mimikatz dumping certificates on Azure AD Joined machine

To sum up, the Azure AD environment has tremendously changed from the on-premise AD. It is no longer based on Kerberos KDC, and NTLM. The user representation on the machine has changed and there are default local admins on every Azure AD joined machine. However, Azure AD joined machine can still be challenged by adversaries who want to impersonate Azure AD users and move laterally between Azure joined machines. The adversaries will need address a new challenge for them and harvest the credentials every hour to obtain a valid user’s certificate.

#MicrosoftEmplyoee, blogs are my own personal opinion

#MicrosoftEmplyoee, blogs are my own personal opinion