This blog post is the first part of a series. In this first part of three, I will explain how the Single Sign On (SSO) works and how an attacker might abuse this. In the second part I will demonstrate a second and more complex attack technique. Finally, in the third blog post, I will explain how you can protect yourself against those type of attacks.
Azure Active Directory
For more than a decade, many organizations have used the domain join to add their windows devices to the on-premises Active directory. In today’s IT landscape, many organizations are transforming their device identities from a traditional Active directory on premise environment to Azure Active Directory. Some opt for the hybrid setup, meaning their devices are joined both to the on-prem AD as well as Azure AD. This is what we call hybrid AD joined. Others choose for a setup where their devices are only Azure AD joined.
Joining devices to Azure AD allows organizations to benefit from the capabilities provided by Azure AD. One of those benefits is single-sign-on against Azure AD connected resources.
As is typical for all new technology, Azure AD comes with new features, but it might also introduce new weaknesses that you should be aware of.
Primary Refresh Tokens
SSO relies on special tokens. These tokens are in turn used to obtain access tokens for specific applications, like O365. In the case of Windows Integrated authentication,using Kerberos, this token is equivalent to a Kerberos Ticket-Granting Ticket. For Azure AD and ADFS-integrated applications we call this a Primary Refresh Token (PRT). This PRT is a requirement for SSO. It makes sure theuser can access applications without being prompted for credentials. To do this, the device sends a cookie to Azure AD called ‘x-ms-RefreshTokenCredential’, which we will call the PRT cookie. This is an encoded JSON Web Token (JWT) containing the PRT. A typical PRT cookie contains the following header and payload.
Figure 1: A PRT cookie.
In the payload, there are 3 important pieces of data. The request_nonce is passed from the login.microsoft.com page to make sure the cookie can only be used for that login session. The is_primary indicates that this cookie is a primary refresh token. The refresh_token contains the actual PRT, which is an encrypted blob by a key which is managed by Azure AD. This JWT token is signed by a special key, which I will discuss later in this article.
A PRT can also get a multi-factor authentication (MFA) claim in specific scenarios. When an MFA-based PRT is used to request tokens for applications, the MFA claim is transferred to those access tokens. This functionality provides a seamless experience to users by preventing MFA challenge for every app that requires it. A PRT is valid for 14 days and is continuously renewed as long as the user actively uses the device.
A PRT is issued to users only on registered devices. A registered device can either be an Azure AD joined, Hybrid AD joined or Azure AD registered.
During device registration two cryptographic key pairs are generated.
- Device key: this is a key-pair that consists of a public part (dkpub) and a private part (dkpriv)
- Transport key: this is also public/private key-pair (tkpub/tkpriv)
The private keys are bound to the devices Trusted Platform Module (TPM) if the device has a valid and functioning TPM, while the public keys are sent to Azure AD during the device registration process. The device key is used to authenticate the device to Azure AD. The transport key is used to transport the session key in a secure way to the device.
The session key is the “Proof of Possession” key for any PRT cookie request sent to Azure AD. Azure AD will invalidate any PRT cookie from the device that is not signed by a key derived from the corresponding session key. It is important to understand that the session key is also stored in the TPM and encrypted by the Data Protection API (DPAPI). (The DPAPI is a built-in windows component to perform encryption of keys. In other words, no other OS component can access the session key.)
For Azure AD joined or Hybrid Azure AD joined devices, A PRT is issued when a user signs in with his organization credentials on Windows . Azure AD CloudAP plugin on your operating system is the primary authority for the PRT. CloudAP plugin is an Azure AD specific plugin built on the CloudAP framework, that verifies user credentials with Azure AD during Windows sign in. The CloudAP plugin caches the PRT during processing in the LSASS memory. The PRT on its own isn’t protected but can only be used when signed by the correct key.
For an Azure AD registered device, A PRT is issued when a user adds a secondary work account to their Windows 10 device.
Users can add an account to Windows 10 in different ways. For example, when adding an account via the ‘Use this account everywhere on this device’ prompt after signing in to an app (for example, Outlook). This is allowed by default in Azure AD and isn’t blocked in a lot of organizations.
How to hack the PRT
Now that we know what the PRT (cookie) is and how it is issued, we’ll have a look at how an attacker can take advantage of the PRT to fetch an access token from Azure AD and bypass MFA and/or Conditional access.
We will describe two types of attacks:
- Type 1: Pass the cookie. By stealing a newly attacker generated PRT cookie from the victim’s computer and use this PRT cookie to fetch access token from Azure AD
- Type 2: Pass the PRT. By stealing the PRT and session/derived key from LSASS on victim’s computer and generate a PRT cookie on attacker computer. Use this cookie to fetch an access token from Azure AD.
I would like to emphasize thatfor both attacks, the perpetrator needs to have the ability to execute code on the victims pc. How they gain access to a victim’s computer is out of the scope for this blog, but typically an attacker can achieve this through phishing techniques or might get on a victim’s device after initiating another attack.
The tools used in a pass-the-cookie attack
Before explaining this technique, I’ll talk about the tools I will use for a pass-the-cookie attack. In this blog we use the terms ‘ROADtools’ and ‘ROADtoken’ created by Dirk-jan Mollema. Dirk-jan is a redteam researcher specialized in topics like Windows, AD en Azure AD. Dirk-jan also reverse engineered the Windows 10 accounts extension for Chrome created by Microsoft. During his investigation he found out which windows binaries are being used by the extension to obtain a signed PRT cookie that can be used with SSO and Azure AD. He created a tool that uses the same binaries called ‘ROADtoken’. We will use this tool to generate a signed PRT cookie on the victim’s computer. This PRT cookie can be used together with the ‘ROADtools’ to authenticate and obtain a persistent access/refresh token.
Let’s start from our victim’s personal device. The victim has configured his corporate credentials into Outlook to read his work mail on his personal device, but he unknowingly also registered this device to the corporate Azure AD tenant. Tthis is a default question, see the picture below. Users receive this when they first configure their corporate e-mail account.
Figure 2: Default question to register your device
Figure 3: Coporate account added on personal device
Figure 4: Corporate account added in Outlook client
Our attacker pc uses a Kali Linux device with the tools we listed earlier.
The attacker is going to abuse the SSO on the victim’s pc. In this example a remote shell is used but there are other techniques that work too. First, the attacker creates a nonce. The nonce acts as liveness check to make sure it’s not going to be a replay. It’s a short randomly generated value. The nonce must be included into the PRT cookie token, like we saw earlier. This can be obtained with the road recon tool from the ROADTOOLS framework. This first step can be done on the attacker’s pc.
Figure 5 The attacker creates a nonce
Now we have a nonce, it’s time to request a PRT cookie on the victim’s computer. We will use ROADtoken explained earlier to create a signed PRT token.
Figure 6 ROADtoken to request a PRT cookie
Now we’ve got a PRT cookie, it is time to inject this into a browser session. We do this on the attacker’s PC. We do not need the victim’s device anymore. We open a browser in incognito mode and go to portal.office.com. Then we will see the login page.
Figure 7 A browser in incognito mode shows the Microsoft login page
We open the bowser developer tools and delete all the active cookies and enter a new cookie with the name ‘x-ms-RefreshTokenCredential’. The value will be the PRT cookie we created earlier. We also set the ‘http only’ to true.
Figure 8 Inserting the PRT cookie in the browser
We refresh the page and we are in! We can also go to other Azure resources like the Azure AD portal.
Figure 9 The Azure AD portal
This PRT token that we obtained can also be used to authenticate with powersehell modules like ADconect and MS-Graph.
For example, here I’m using the Azure AD PowerShell module on a completely different PC (not joined to the same AD or Azure AD) and authenticate using the access token requested.
Figure 10 The Azure AD PowerShell module