Understanding Primary Refresh Tokens and CVE-2021-33779: How "Pass-the-PRT" was eliminated

Recently, I delved into Primary Refresh Tokens (PRTs) used in Entra ID joined or hybrid joined devices to discover which attacks are currently effective on devices with TPM and up-to-date patches. After reviewing various blog posts and standards (see references below), I was left with the following questions:

  • What attack methods are effective on an up-to-date device with a TPM?
  • What impact did the patch for CVE-2021-33779 have on Primary Refresh Tokens?

Although there is a wealth of information in the linked resources, I found that these questions were not directly answered in a single post. This post aims to bridge that gap and provide an overview. Note: This is a synthesis of existing information (to the best of my knowledge) and does not include original research. For those well-versed in this topic, this post might be a bit boring. 😉

Key Terminology

  • PRT: An encrypted token issued by Entra ID to "token brokers" on clients, enabling Single Sign-On (SSO) across applications on those devices. According to Microsoft, this token is a JWT (JSON Web Token).
  • PRT Cookie: A JWT sent in the x-ms-RefreshTokenCredential header to the /authorize endpoint to facilitate SSO. It contains the PRT (claim "refresh_token") and nonce (claim "refresh_nonce") and is signed with a key derived from the session key. The PRT Cookie is sometimes referred to as the "PRT Token."
  • Token Broker: Software components on Windows that handle the issuance, renewal, and caching of PRTs and PRT Cookies. The definitive nomenclature and relationships among these components are unclear, but they include:
  • BrowserCore.exe: Used by Edge or a Chrome extension to issue PRT Cookies for SSO on supported domains, such as login.microsoftonline.com. It uses a COM object provided by MicrosoftAccountTokenProvider.dll to retrieve a PRT Cookie.
  • CloudAP.dll, aadcloudap.dll, and MicrosoftAccountCloudAP.dll: Loaded by LSASS, these implement the Token Broker on Windows.

Pass-the-PRT-Cookie vs. Pass-the-PRT

There are readily available tools that can generate PRT Cookies via the COM Object, such as RequestAADRefreshToken. Other tools can interact with BrowserCore.exe, like ROADtoken.exe. Here's a high-level overview:

  1. Input: A nonce is provided.
  2. Output: A PRT Cookie is returned, which can be used in the x-ms-RefreshTokenCredential header.

Before CVE-2021-33779, the key to sign the PRT Cookie was derived from the session key using a function that only required a client-chosen "ctx" value. Although the session key and derivation process were handled inside the TPM, the derived key was managed outside the TPM. Attackers could use tools like Mimikatz to extract the derived key and context from LSASS memory, allowing them to sign PRT Cookie requests off-device, a method most often called "Pass-the-PRT".

In October 2020, Microsoft enforced that a PRT Cookie must include a nonce. By July 2021, they fixed CVE-2021-33779. Initially, PRTs could be requested without a "refresh_nonce" claim. During the interim, attackers had to request a nonce from the /token endpoint and add it to the PRT Cookie, but since the derived key was independent of the nonce, this could be done off-device.

The patch for CVE-2021-33779 introduced a new Key Derivation Function (KDF), known as "KDFv2," on ADFS (Active Directory Federation Services). KDFv2 uses all values from the JWT (the PRT Cookie), including the request_nonce and the "ctx" value, to derive the key from the session key. This change ties the PRT to a specific login session on a specific device, ensuring that attackers must be on the device to create new PRT Cookies. This attack, referred to as "Pass-the-PRT-Cookie", still works today but requires presence on the targeted device.

Diagram explaining PRT Signing

Preventing Downgrade Attacks

What prevents an attacker from tricking the token broker into requesting a new PRT using the older KDFv1? Key measures include:

  • Initial Sign-In: During the first sign-in, a PRT is issued, which likely indicates it was created with KDFv2, preventing downgrades.
  • Subsequent Issuances: When issuing new PRTs, the old PRT is sent along. The server checks the KDF version of the old PRT, ensuring no downgrade attacks are possible.

This is currently only an assumption.

Another open question is whether one could delete the PRT cache, forge the Realm discovery so that the response excludes the "kdf_ver2" capability and consequently let the token broker use the old KDF? Time will tell.

Resources

By @dimi in
Tags : #PRT, #CVE-2021-33779, #Primary Refresh Tokens, #Entra ID,