Microsoft 一直试图让客户远离 ADFS,这已经不是什么秘密了。除了给它贴上“已弃用”的标签之外,我遇到的每一点文档最终都解释了为什么现在应该使用 Entra ID 来代替 ADFS。
而。。。我们仍然到处都能遇到它!即使在采用 Entra ID 的组织中,我们也有 Hybrid Joined 环境,这些环境通常将联合身份验证与云管理混合在一起。因此,虽然追逐闪亮的新事物很好,但围绕 ADFS 构建知识仍然是一种值得度过一个夜晚的方式。
因此,在这篇文章中,我们将重点介绍一些 ADFS 内部结构。我们将远离已被打得死去活来的 SAML 区域,而是要看看 OAuth2,以及它如何支持类似 Entra ID 安全功能(如设备注册和主刷新令牌)的功能。
老实说,我不确定这篇文章在实际意义上有多大用处。我试图在面向 Internet 的 ADFS 服务器上收集数据,看看有哪些配置可以帮助磨练我的研究,但我发现这个领域太有趣了,不能留在我的 Notion 笔记本上腐烂。
因此,如果一个人能够利用这些内容来实现他们在未来的评估中的目标,或者只是为了了解该对象存在的原因,那么值得发布。msDS-Device
ADFS 和 OAuth2
如果您认为 ADFS 是主要的 SAML 令牌生成器,那也是可以理解的。毕竟,大多数事后技术都集中在 Golden SAML 等领域,多年来已在无数项目中获得成功。
但 ADFS 的另一面是 OAuth2。当然,Microsoft使用的术语也带有一层“Microsoft Stank”(我的同事 @hotnops 喜欢这样称呼它,在介绍一些疯狂的 Entra ID 研究时),但它在很大程度上是一个 OAuth2 提供商。
首先,我将对 ADFS 上的 OAuth2 进行非常快速的概述,以便为我们稍后将要讨论的内容奠定基础。
让我们从如何设置简单的 OAuth2 集成开始。在 ADFS 管理控制台中,我们有 “Application Groups”:
这是 ADFS 允许配置 OAuth2 客户端和服务器的地方。我们将设置一个新的应用程序组,并将其命名为 “Test App Group(测试应用程序组)”,其中将提供许多模板:
Microsoft 通过“更多信息”按钮提供了每个模板的概述,但文档中的下表提供了一组有用的翻译来理解 Microsoft 的 OAuth2 术语:
现在,让我们选择 “Web browser accessing a web application” 模板。我们将使用 ClaimsXRay.net Web 应用程序作为目标,这是一个用于测试 IdP 集成的不错应用程序(以 Microsoft 自己已弃用的 ClaimsXRay 服务为模型)。
在下一个屏幕上,我们需要分配 URI 并重定向 URI,我们将将其设置为 :Client Identifier
https://claimsxray.net/token
记下 which 稍后将用于识别我们的客户端配置。Client Identifier
下一个对话框确定谁可以访问 OAuth2 资源提供程序。同样,我们在此处只使用“允许所有人”,以允许所有经过身份验证的 ADFS 用户访问应用程序,但有多个选项可以限制允许访问哪些帐户:
我们需要做的另一件事是配置 CORS。这允许 ClaimsXRay 在将代码交换为访问令牌时向 ADFS 发出 XHR 请求。
与 ADFS 通常的情况一样,没有管理控制台选项来执行此操作,而是我们需要使用 PowerShell:
Set-AdfsResponseHeaders -EnableCORS $true
Set-AdfsResponseHeaders -CORSTrustedOrigins https://claimsxray.net
同样,如果我们想从头开始使用 PowerShell 创建此集成,我们可以使用:
New-AdfsApplicationGroup -Name ClaimsXRayGroup
Add-AdfsNativeClientApplication -Name ClaimsXRayClient -ApplicationGroupIdentifier ClaimsXRayGroup -Identifier https://claimsxray.net/ -RedirectUri https://claimsxray.net/token
Add-AdfsWebApiApplication -Name ClaimsXRayServer -Identifier https://claimsxray.net/ -AllowedClientTypes Public -ApplicationGroupIdentifier ClaimsXRayGroup
Grant-AdfsApplicationPermission -ClientRoleIdentifier https://claimsxray.net/ -ServerRoleIdentifier https://claimsxray.net/ -ScopeNames @('email', 'openid')
# Enable CORS support
Set-AdfsResponseHeaders -EnableCORS $true
Set-AdfsResponseHeaders -CORSTrustedOrigins https://claimsxray.net
这样,我们就完成了。我们可以通过在 ClaimsXRay.net 上启动流程来测试一切是否有效,提供上面生成的客户端 ID,以及指向我们实验室 ADFS 实例的 URL:
如果单击 Login(登录),您应该会看到返回访问令牌。由于请求的范围,我们还将获得身份令牌:openid
现在,我们对 ADFS 如何在非常高的级别处理 OAuth2 注册有了一定的了解,让我们开始看一下一些记录较少的功能。
设备注册服务
在反转 ADFS 时,我遇到了许多嵌入在二进制文件中的“隐藏”OAuth2 客户端 ID:
引起我注意的是 。如果 DRS 术语看起来很熟悉,那可能是因为您在 Entra ID 世界中遇到过它作为设备注册。但对于那些喜欢自己管理设备注册的组织,DRS 也以各种形式在本地得到支持。现在,当我说“支持”时,要让 DRS 真正独立工作需要做很多事情,所以我认为它已经被 Microsoft 遗弃了。如果组织之前在 Entra ID 之前启用了 DRS,或者作为我们稍后将介绍的 Entra ID 混合加入方案的一部分,您更有可能遇到这种情况。DrsClientIdentitier
要在 ADFS 上启用 DRS,请使用“设备注册”功能,该功能将部署在 Active Directory 中支持此功能所需的先决条件:
如果我们通过路径查询 ADFS,我们会得到一个 DRS 描述符列表:/EnrollmentServer/contract?api-version=1.2
这些指向我们稍后将探讨的各种 DRS API 服务,但在我们过于超前之前,让我们快速了解 ADFS 身份验证方法,以便我们稍后可以为设备身份验证设置场景。
身份验证方法
ADFS 具有“Extranet”和“Intranet”的概念。对于大多数组织来说,ADFS 通过 Web 代理暴露在外围,内部网络用户通常直接与 ADFS 服务交互。
您可以看到,此拆分已填充到 ADFS 的配置中,端点被明确列出(在本例中为“Enabled”和“Proxy Enabled”,因为在 Microsoft 世界中很难保持一致的术语):
这种区别也通过 ADFS 支持的身份验证方法显现出来,允许使用不同的方法按“Extranet”和“Intranet”验证凭据(告诉您 Microsoft 一致的术语很难):
在参与过程中,您可能会遇到其中一些选择。例如,“Forms Authentication” 是 ADFS 登录表单的表示形式:
“Windows 身份验证”是您过去无疑尝试过中继的 NTLM/Kerberos WIA 方法,并且仅在 Intranet 上受支持。
要使 DRS 正常运行,需要启用“设备身份验证”选项,并可通过您有权访问的 Extranet/Intranet 区域进行访问。
设备身份验证需要启用 DRS,不幸的是,对于我们攻击者来说,默认情况下没有启用 DRS。因此,您更有可能在旧环境或使用 Hybrid Join 的环境中看到这一点。
Device Authentication 有多种运行方式,具体取决于配置。在 ADFS ≥ 2016 中,我们有:
客户端TLS PRT PKeyAuth
Device Authentication 的方法在一定程度上由 PowerShell commandlet 控制:Set-AdfsGlobalAuthenticationPolicy
Set-AdfsGlobalAuthenticationPolicy –DeviceAuthenticationMethod All
开箱即用,ADFS 2012 仅支持 .但是,ADFS ≥ 2016 使用ClientTLS
SignedToken
那么,我们如何枚举租户以确定已启用的设备身份验证方法呢?嗯,这主要是一场淘汰赛。如果我们想查看是否为ADFS启用了设备身份验证,但无权访问配置,则带有参数的终端节点请求将显示以下内容:ClientTLS
curl
trace
curl -k 'https://adfs.lab.local/adfs/ls/idpinitiatedsignon.aspx?client-request-id=77de249e-f9b5-4921-c301-0080000000b9' -v -X POST -d 'SignInIdpSite=SignInIdpSite&SignInSubmit=Sign+in&SingleSignOut=SingleSignOut' --trace out.txt
我们正在客户端证书请求 (13) 中查找 CA。如果您看到此消息,则表示已为您请求的网络终端节点启用了 Device Authentication。这意味着,如果我们拥有适当的设备身份验证证书,就可以向 ADFS 进行身份验证。MS-Organization-Access
ClientTLS
如果我们想检查是否启用,我们需要在字符串中使用字符串发出请求:PKeyAuth
;PKeyAuth/1.0
User-Agent
curl -k 'https://adfs.lab.local/adfs/ls/idpinitiatedsignon.aspx?client-request-id=77de249e-f9b5-4921-c301-0080000000b1' -v -X POST -d 'SignInIdpSite=SignInIdpSite&SignInSubmit=Sign+in&SingleSignOut=SingleSignOut'--user-agent "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0);PKeyAuth/1.0
如果响应返回 to ,则我们知道使用了 PKeyAuth:302
urn:http-auth:PKeyAuth
< HTTP/1.1302 Found
< Content-Length: 0
< Content-Type: text/html; charset=utf-8
< Location: urn:http-auth:PKeyAuth?SubmitUrl=https%3a%2f%2fadfs.lab.local%3a443%2fadfs%2fls%2fidpinitiatedsignon.aspx%3fclient-request-id%3d77de249e-f9b5-4921-c301-0080000000b1&nonce=P5180krdKaElqhmYzkkNYw&Version=1.0&Context=4e5a62d9-12f7-4898-9a4e-f3cd11c65a1a&CertAutho
rities=OU%253d82dbaca4-3e81-46ca-9c73-0950c1eaca97%252cCN%253dMS-Organization-Access%2b%252cDC%253dwindows%2b%252cDC%253dnet%2b&client-request-id=77de249e-f9b5-4921-c301-0080000000b1
如果以上两种情况都不正确,则 PRT 身份验证正在使用中。我们将在帖子中进一步审查此选项。
现在我们已经了解了设备身份验证的工作原理,下一个问题是...所有这些密钥、证书、身份验证信息都存储在哪里?
msDS 设备
您可能遇到过 LDAP 类,它位于容器中:msDS-Device
CN=RegisteredDevices,DC=domain,DC=com
该对象是已注册设备的表示形式。与对象不同,它不是安全主体,但它确实包含许多熟悉的属性,例如:msDS-Device
Computer
altSecurityIdentities
msDS-KeyCredentialLink
由于 不是安全主体,因此“影子凭证”之类的内容将不起作用,因为没有与设备关联的身份。那么这里存储了什么呢?msDS-Device
对于 ,该字段用于存储我们在设备注册期间生成的设备身份验证证书的公钥。msDS-Device
altSecurityIdentities
还有另一个重要字段,它与用于创建设备注册的用户帐户的 SID 关联,以及 :msDS-RegisteredOwner
msDS-RegisteredUsers
这就是根据我们上面评论的身份验证方法略有不同的地方。如果 正在使用中,并且我们使用设备注册期间使用的证书进行身份验证,则您向 ADFS 进行身份验证的用户帐户将成为这些字段的 SID。如果使用,则情况并非如此,因此我相信这是在 PRT 成为常态之前旧版本的 ADFS 设备注册的示例。ClientTLS
SignedToken
这也意味着,如果在评估期间,您发现自己对某个对象具有写入权限(并且启用了设备身份验证),则可以通过更新 and 字段以指向任何用户的 SID,以任何主体身份向 ADFS 进行身份验证。msDS-Device
ClientTLS
msDS-RegisteredOwner
msDS-RegisteredUsers
如上所述,在设备注册期间创建并填充字段。让我们看一下设备实际如何注册的身份验证过程。msDS-Device
创建 DRS 访问令牌
要对 DRS 进行身份验证,我们需要 OAuth2 访问令牌。我们在博文开头的反汇编中观察到的 DRS 客户端 ID 是“public”,这意味着在发出请求时无需了解任何 OAuth2 密钥。
我们可以使用 commandlet 来验证这一点:Get-AdfsClient
我们还可以看到 supported required for authentication。RedirectUri
因此,如果我们在 ADFS 上拥有帐户的有效凭据,我们可以使用以下命令启动 DRS 客户端 OAuth2 流程:
GET /adfs/oauth2/authorize?response_type=code&
client_id=dd762716-544d-4aeb-a526-687b73838a22&
resource=urn:ms-drs:434DF4A9-3CF2-4C1D-917E-2CD2B72F515A&
redirect_uri=ms-app://windows.immersivecontrolpanel/ HTTP/1.1
Host: adfs.lab.local
这将启动授权代码流,根据启用的身份验证方法,我们可以使用凭证登录以创建 OAuth2 授权码。如果我们成功进行身份验证,我们将看到传递回重定向 URI 的参数:code
然后,使用以下方法将此代码交换为访问令牌:
POST /adfs/oauth2/token HTTP/1.1
Host: adfs.lab.local
User-Agent: Windows NT 1
Content-Type: application/x-www-form-urlencoded
Content-Length: 536
grant_type=authorization_code&
code=eNSvPCotu0yaI4ttVB1WXA.Dn...&
client_id=dd762716-544d-4aeb-a526-687b73838a22&
redirect_uri=ms-app%3A%2F%2Fwindows.immersivecontrolpanel%2F
希望我们能找回我们的 Access Token:
但是,这里需要注意的一个重要问题是,DRS 服务分配了以下身份验证策略:
这意味着,如果我们以用户帐户身份向 ADFS 进行身份验证,则需要 MFA(或者我们可以以计算机帐户身份进行身份验证并绕过此操作,但这目前不是很有用)。
那么,如果我们命中这个 ACL 会发生什么呢?在身份验证期间,我们将看到以下错误:
不幸的是,如果此访问控制策略已到位,这将阻止我们尝试使用被盗凭据创建,除非......msDS-Device
DRS OAuth2 客户端支持设备代码流
老实说,ADFS 中甚至存在设备代码流这一事实对我来说是新闻,但它确实如此。默认情况下,它为 DRS 客户端启用。事实上,默认情况下,ADFS 上的每个 OAuth2 客户端都启用了它,这在评估其他 OAuth2 集成时应该会很有趣。
那么这是如何运作的呢?要为 DRS 启动此流程,您首先需要使用我们的客户端 ID 和资源进行调用:/adfs/oauth2/devicecode
POST /adfs/oauth2/devicecode HTTP/1.1
Host: adfs.lab.local
Content-Type: application/x-www-form-urlencoded
Content-Length: 103
client_id=dd762716-544d-4aeb-a526-687b73838a22&
resource=urn:ms-drs:434DF4A9-3CF2-4C1D-917E-2CD2B72F515A
这将返回您常用的 OAuth2 设备代码信息:
HTTP/1.1 200 OK
...
{
"device_code":"8uODMKe4OEGu4[...]8fG640TTMxOQ",
"expires_in":899,
"interval":5,
"message":"To sign in, use a web browser to open the page https:\/\/adfs.lab.local\/adfs\/oauth2\/deviceauth and enter the code SYGTLXSGB to authenticate.",
"user_code":"SYGTLXSGB",
"verification_uri":"https:\/\/adfs.lab.local\/adfs\/oauth2\/deviceauth",
"verification_uri_complete":"https:\/\/adfs.lab.local\/adfs\/oauth2\/deviceauth?user_code=SYGTLXSGB&client-request-id=b08b3ca6-6a56-4cf3-1b00-0080000000e3",
"verification_url":"https:\/\/adfs.lab.local\/adfs\/oauth2\/deviceauth"
}
然后,您将受害者定向到指示的 URL(您也可以使用参数预先填充代码)user_code
New-AdfsApplicationGroup -Name ClaimsXRayGroup
Add-AdfsNativeClientApplication -Name ClaimsXRayClient -ApplicationGroupIdentifier ClaimsXRayGroup -Identifier https://claimsxray.net/ -RedirectUri https://claimsxray.net/token
Add-AdfsWebApiApplication -Name ClaimsXRayServer -Identifier https://claimsxray.net/ -AllowedClientTypes Public -ApplicationGroupIdentifier ClaimsXRayGroup
Grant-AdfsApplicationPermission -ClientRoleIdentifier https://claimsxray.net/ -ServerRoleIdentifier https://claimsxray.net/ -ScopeNames @('email', 'openid')
# Enable CORS support
Set-AdfsResponseHeaders -EnableCORS $true
Set-AdfsResponseHeaders -CORSTrustedOrigins https://claimsxray.net0
当用户进行身份验证(并希望完成验证上述 ACL 所需的 MFA 步骤)时,您可以通过对以下调用来检索:access_token
/adfs/oauth2/token
New-AdfsApplicationGroup -Name ClaimsXRayGroup
Add-AdfsNativeClientApplication -Name ClaimsXRayClient -ApplicationGroupIdentifier ClaimsXRayGroup -Identifier https://claimsxray.net/ -RedirectUri https://claimsxray.net/token
Add-AdfsWebApiApplication -Name ClaimsXRayServer -Identifier https://claimsxray.net/ -AllowedClientTypes Public -ApplicationGroupIdentifier ClaimsXRayGroup
Grant-AdfsApplicationPermission -ClientRoleIdentifier https://claimsxray.net/ -ServerRoleIdentifier https://claimsxray.net/ -ScopeNames @('email', 'openid')
# Enable CORS support
Set-AdfsResponseHeaders -EnableCORS $true
Set-AdfsResponseHeaders -CORSTrustedOrigins https://claimsxray.net1
返回的 (以及我们稍后需要的) ,我们有一个范围限定为 DRS 服务的身份验证令牌。access_token
refresh_token
那么,一旦我们有了 Access Token,我们如何将其转换为设备注册呢?
DeviceEnrollmentWebService.svc 文件
您之前可能已经在端点的 XML 中看到过:DeviceEnrollmentWebService.svc
/EnrollmentServer/contract
此 Web 服务可以与资源的访问令牌一起使用,以注册新资源。urn:ms-drs:434DF4A9-3CF2-4C1D-917E-2CD2B72F515A
msDS-Device
我们用于使用此终端节点注册设备的 SOAP 请求的格式为:
New-AdfsApplicationGroup -Name ClaimsXRayGroup
Add-AdfsNativeClientApplication -Name ClaimsXRayClient -ApplicationGroupIdentifier ClaimsXRayGroup -Identifier https://claimsxray.net/ -RedirectUri https://claimsxray.net/token
Add-AdfsWebApiApplication -Name ClaimsXRayServer -Identifier https://claimsxray.net/ -AllowedClientTypes Public -ApplicationGroupIdentifier ClaimsXRayGroup
Grant-AdfsApplicationPermission -ClientRoleIdentifier https://claimsxray.net/ -ServerRoleIdentifier https://claimsxray.net/ -ScopeNames @('email', 'openid')
# Enable CORS support
Set-AdfsResponseHeaders -EnableCORS $true
Set-AdfsResponseHeaders -CORSTrustedOrigins https://claimsxray.net2
此处的重要字段包括:
- 标头 - 这是我们在身份验证期间检索到的 base64 编码
BinarySecurityToken
access_token
- 正文 - 我们生成的用于签名的 PKCS#10 编码的 CSR
BinarySecurityToken
当我们发出此请求时,我们会收到带有签名证书的响应:
New-AdfsApplicationGroup -Name ClaimsXRayGroup
Add-AdfsNativeClientApplication -Name ClaimsXRayClient -ApplicationGroupIdentifier ClaimsXRayGroup -Identifier https://claimsxray.net/ -RedirectUri https://claimsxray.net/token
Add-AdfsWebApiApplication -Name ClaimsXRayServer -Identifier https://claimsxray.net/ -AllowedClientTypes Public -ApplicationGroupIdentifier ClaimsXRayGroup
Grant-AdfsApplicationPermission -ClientRoleIdentifier https://claimsxray.net/ -ServerRoleIdentifier https://claimsxray.net/ -ScopeNames @('email', 'openid')
# Enable CORS support
Set-AdfsResponseHeaders -EnableCORS $true
Set-AdfsResponseHeaders -CORSTrustedOrigins https://claimsxray.net3
不幸的是,这不会是另一种 ESC99 风格的攻击,因为用于对令牌进行签名的 CA 是 ADFS 内部 CA,而不是 ADCS(我可以读懂您的想法)。但是,我们稍后使用 Device Authentication 时需要此 ID。
如果我们获取这个 base64 编码的证书并对其进行解码,我们会得到如下结果:
New-AdfsApplicationGroup -Name ClaimsXRayGroup
Add-AdfsNativeClientApplication -Name ClaimsXRayClient -ApplicationGroupIdentifier ClaimsXRayGroup -Identifier https://claimsxray.net/ -RedirectUri https://claimsxray.net/token
Add-AdfsWebApiApplication -Name ClaimsXRayServer -Identifier https://claimsxray.net/ -AllowedClientTypes Public -ApplicationGroupIdentifier ClaimsXRayGroup
Grant-AdfsApplicationPermission -ClientRoleIdentifier https://claimsxray.net/ -ServerRoleIdentifier https://claimsxray.net/ -ScopeNames @('email', 'openid')
# Enable CORS support
Set-AdfsResponseHeaders -EnableCORS $true
Set-AdfsResponseHeaders -CORSTrustedOrigins https://claimsxray.net4
我们获取该值,然后 base64 对其进行解码以生成我们的签名公钥证书。通常,最好将其与私钥组合成一个 PFX,如下所示:EncodedCertificate
New-AdfsApplicationGroup -Name ClaimsXRayGroup
Add-AdfsNativeClientApplication -Name ClaimsXRayClient -ApplicationGroupIdentifier ClaimsXRayGroup -Identifier https://claimsxray.net/ -RedirectUri https://claimsxray.net/token
Add-AdfsWebApiApplication -Name ClaimsXRayServer -Identifier https://claimsxray.net/ -AllowedClientTypes Public -ApplicationGroupIdentifier ClaimsXRayGroup
Grant-AdfsApplicationPermission -ClientRoleIdentifier https://claimsxray.net/ -ServerRoleIdentifier https://claimsxray.net/ -ScopeNames @('email', 'openid')
# Enable CORS support
Set-AdfsResponseHeaders -EnableCORS $true
Set-AdfsResponseHeaders -CORSTrustedOrigins https://claimsxray.net5
因此,一旦我们完成了这个 SOAP 请求并获得了签名的证书,我们将在 Active Directory 中找到我们的新对象:msDS-Device
如果我们准备使用 访问 ADFS,这应该就足够了。但是,正如我们稍后在查看时将看到的那样,这种创建新的 .对我们来说,最大的问题是该属性未填充到 AD 中(对于以前探索过 Entra ID 的任何人,您可能知道这是 PRT 配置过程中使用的会话传输密钥所必需的)。ClientTLS
SignedToken
msDS-Device
msDS-KeyCredentialLink
顺便说一句,我“认为”在 Entra ID 与 Windows 如此紧密集成之前,此 Web 服务实际上用于支持 DRS 的早期迭代。在 Windows 8 天里,DRS 是一种更简单的方法,用于生成用于设备身份验证的证书,并使用 ,这解释了为什么从未使用过该参数...但这只是一个猜测。ClientTLS
msDS-KeyCredentialLink
EnrollmentServer REST API
终端节点中引用的第二个终端节点是服务:/EnrollmentServer/contract
/EnrollmentServer/device/
同样,这可能看起来很熟悉,因为它是 Entra 设备注册期间使用的服务的克隆。https://enterpriseregistration.windows.net/EnrollmentServer/device/
此 REST API 是创建新 API 的更完整方法,因为它允许我们为 (非常感谢 @DrAzureAD 和帖子“深入了解 Azure AD 设备加入”,该帖子节省了大量时间和精力来揭示此请求的结构,您对信息安全场景的贡献始终不胜感激!msDS-Device
msDS-KeyCredentialLink
New-AdfsApplicationGroup -Name ClaimsXRayGroup
Add-AdfsNativeClientApplication -Name ClaimsXRayClient -ApplicationGroupIdentifier ClaimsXRayGroup -Identifier https://claimsxray.net/ -RedirectUri https://claimsxray.net/token
Add-AdfsWebApiApplication -Name ClaimsXRayServer -Identifier https://claimsxray.net/ -AllowedClientTypes Public -ApplicationGroupIdentifier ClaimsXRayGroup
Grant-AdfsApplicationPermission -ClientRoleIdentifier https://claimsxray.net/ -ServerRoleIdentifier https://claimsxray.net/ -ScopeNames @('email', 'openid')
# Enable CORS support
Set-AdfsResponseHeaders -EnableCORS $true
Set-AdfsResponseHeaders -CORSTrustedOrigins https://claimsxray.net6
我们使用更传统的标头对此服务进行身份验证,提供我们的 DRS 访问令牌作为不记名。Authorization
同样,此请求的正文中还需要注意一些其他事项。第一个是 .这可以设置为以下值之一(不幸的是,并非所有值实际上都受支持):JoinType
New-AdfsApplicationGroup -Name ClaimsXRayGroup
Add-AdfsNativeClientApplication -Name ClaimsXRayClient -ApplicationGroupIdentifier ClaimsXRayGroup -Identifier https://claimsxray.net/ -RedirectUri https://claimsxray.net/token
Add-AdfsWebApiApplication -Name ClaimsXRayServer -Identifier https://claimsxray.net/ -AllowedClientTypes Public -ApplicationGroupIdentifier ClaimsXRayGroup
Grant-AdfsApplicationPermission -ClientRoleIdentifier https://claimsxray.net/ -ServerRoleIdentifier https://claimsxray.net/ -ScopeNames @('email', 'openid')
# Enable CORS support
Set-AdfsResponseHeaders -EnableCORS $true
Set-AdfsResponseHeaders -CORSTrustedOrigins https://claimsxray.net7
现在还有之前 service 调用中缺少的值。TransportKey
对此的响应再次是签名证书:
New-AdfsApplicationGroup -Name ClaimsXRayGroup
Add-AdfsNativeClientApplication -Name ClaimsXRayClient -ApplicationGroupIdentifier ClaimsXRayGroup -Identifier https://claimsxray.net/ -RedirectUri https://claimsxray.net/token
Add-AdfsWebApiApplication -Name ClaimsXRayServer -Identifier https://claimsxray.net/ -AllowedClientTypes Public -ApplicationGroupIdentifier ClaimsXRayGroup
Grant-AdfsApplicationPermission -ClientRoleIdentifier https://claimsxray.net/ -ServerRoleIdentifier https://claimsxray.net/ -ScopeNames @('email', 'openid')
# Enable CORS support
Set-AdfsResponseHeaders -EnableCORS $true
Set-AdfsResponseHeaders -CORSTrustedOrigins https://claimsxray.net8
同样,这会生成一个新对象,但现在将属性填充到我们的值中:msDS-Device
msDS-KeyCredentialLink
TransportKey
那么,现在我们可以注册我们的设备,我们实际上是如何使用前面介绍的设备身份验证方法对自己进行身份验证的呢?
好吧,我们已经在这篇文章中讨论了很多,这是您的基本证书身份验证(我通常只使用 Burp Suite 来实现此目的):ClientTLS
但是如果 is not in use 呢?ClientTLS
企业主刷新令牌
我的另一个新发现是 ADFS 支持主刷新令牌。正如我们之前看到的,这是 ADFS 2016 之后支持的默认设备身份验证方法。SignedToken
其工作方式与 Entra ID 大致相同,因此我必须通过 ROADTools、博客文章和培训向 @_dirkjan 和他在该领域的史诗般的工作大声疾呼。他的工作和知识共享提供了很大一部分示例和代码,以便在 ADFS 上查看这些内容时可供使用。
所以首先我们需要一个 nonce 值,该值是从 中请求的:/adfs/oauth2/token
New-AdfsApplicationGroup -Name ClaimsXRayGroup
Add-AdfsNativeClientApplication -Name ClaimsXRayClient -ApplicationGroupIdentifier ClaimsXRayGroup -Identifier https://claimsxray.net/ -RedirectUri https://claimsxray.net/token
Add-AdfsWebApiApplication -Name ClaimsXRayServer -Identifier https://claimsxray.net/ -AllowedClientTypes Public -ApplicationGroupIdentifier ClaimsXRayGroup
Grant-AdfsApplicationPermission -ClientRoleIdentifier https://claimsxray.net/ -ServerRoleIdentifier https://claimsxray.net/ -ScopeNames @('email', 'openid')
# Enable CORS support
Set-AdfsResponseHeaders -EnableCORS $true
Set-AdfsResponseHeaders -CORSTrustedOrigins https://claimsxray.net9
此调用的响应返回 nonce 值:
Set-AdfsGlobalAuthenticationPolicy –DeviceAuthenticationMethod All0
接下来,我们需要请求 PRT。这是通过创建一个 JWT 不记名令牌来完成的,该令牌使用我们生成的设备证书进行签名:
Set-AdfsGlobalAuthenticationPolicy –DeviceAuthenticationMethod All1
此 JWT 的所需内容记录在 MS-OAPXBC 中。与 Entra ID 一样,我们可以使用以下三种方法之一在 JWT 中对用户进行身份验证:
用户名 / 密码 刷新令牌 签名的 JWT
出于我们的目的,我们将使用 Refresh Token,因为我们已经从之前的 Device Code 身份验证流程中获得了此令牌:
Set-AdfsGlobalAuthenticationPolicy –DeviceAuthenticationMethod All2
如果一切顺利,我们将在响应中得到一个 PRT:
Set-AdfsGlobalAuthenticationPolicy –DeviceAuthenticationMethod All3
该字段是将 PRT 交换为访问令牌所必需的,而访问令牌又使用我们之前在设备注册期间添加的值进行加密。session_key_jwe
msDS-KeyCredentialLink
要解密这些值,我们可以使用 from ROADTools 代码,它看起来像:decrypt_jwe_with_transport_key
Set-AdfsGlobalAuthenticationPolicy –DeviceAuthenticationMethod All4
一旦我们有了 PRT 和会话密钥,我们就有几个选项可以使用它。第一个是通常的 PRT 来访问资源的 Token。这需要生成使用会话令牌签名的 JWT:
Set-AdfsGlobalAuthenticationPolicy –DeviceAuthenticationMethod All5
对此的响应是使用 JWE 加密的(与它们的 Entra ID 对应项完全相同),并且需要解密。ROADTools 函数中已经存在代码,因此我们可以使用它来拼凑:decrypt_auth_response_derivedkey
Set-AdfsGlobalAuthenticationPolicy –DeviceAuthenticationMethod All6
第二个用例是熟悉的标头,可用于直接登录到 ADFS(对于访问 等操作很有用):x-ms-RefreshTokenCredential
/adfs/ls/idpinitiatedsignon.aspx
Set-AdfsGlobalAuthenticationPolicy –DeviceAuthenticationMethod All7
如果我们将此令牌注入到请求的标头中,我们将看到我们可以登录:/adfs/ls/idpinitiatedsignon.aspx
为了在操作时更轻松地完成此操作,我创建了一些 Python 脚本,这些脚本可以在 https://github.com/xpn/adfstoolkit 中找到:
register_device.py
- 执行 DRS 注册以创建msDS-Device
access_token.py
- 从 PRT 请求访问令牌eprt.py
- 生成新的企业 PRT
然后出现了 Azure 混合加入
所以我们拥有所有这些DRS功能..如果我们正在评估的环境使用混合联接到 Entra ID,会发生什么情况?在这种情况下,我们实际上发现 DRS 会自行关闭,正如我们在 ADFS 的反汇编中看到的那样:
但是,虽然这会关闭 DRS HTTP 服务,但它仍然允许设备身份验证。但是为什么?禁用所有设备注册功能不是很有意义吗?嗯,不完全是,因为 Entra ID 仍然支持以设备写回的形式进行 ADFS 设备身份验证。
Entra Connect 设备写回
如果在 Entra Connect 推出期间启用了设备写回,则对象将与其 Entra ID 设备对象对应项同步。msDS-Device
在 Entra Connect 中,我们会看到启用设备写回的选项:
在 Entra ID 中注册新设备时,我们会看到该 ID 写入容器的写入方式与我们之前的 DRS 注册示例完全相同,不同之处在于该帐户将是对象的所有者,而不是 ADFS 服务帐户:CN=RegisteredDevices
MSOL_
由于可能针对 Entra ID 的攻击很多,这可以提供一种途径,可以使用博文中概述的方法将访问权限迁移到 ADFS。
话虽如此,让我们快速回顾一下我们走到这一步的攻击路径:
如果组织启用了 DRS,并且在服务连接点 LDAP 条目中没有混合加入,则可能会使用设备代码 OAuth2 流进行网络钓鱼以访问 ADFS。 如果组织启用了 DRS,但在服务连接点 LDAP 条目中启用了混合加入,则 DRS Web 服务将被禁用,但如果执行新的 Entra ID 设备注册,设备写回可以提供访问 ADFS 的方法。 无论如何,如果 ADFS 使用 OAuth2,则可能启用了设备代码身份验证,因此,网络钓鱼可用于针对其他应用程序集成。 - 如果我们可以控制并启用设备身份验证,则我们可以通过修改和使用设备证书,以任何用户的身份向 ADFS 进行身份验证
msDS-Device
msDS-RegisteredOwner
msDS-RegisteredUsers
最后,让我们看看黄金 JWT 的概念。
黄金 JWT
这与黄金 SAML 类似,因为如果我们拥有正确的签名密钥,我们可以为第三方集成伪造适当的 JWT。
让我们使用之前设置的目标 ClaimsXRay 实验室:
正如我们在 happy 流中看到的那样,令牌中的声明会反映回给我们:
现在让我们看看我们是否可以欺骗 JWT 中的声明!如果我们分析现有访问令牌的内容,我们会得到关于用于签署 JWT 的内容的提示:
Set-AdfsGlobalAuthenticationPolicy –DeviceAuthenticationMethod All8
标头值是用于签名的证书的指纹。解码这一点,我们看到:x5t
如果我们查看 ADFS 实例的签名证书:
这意味着我们为黄金 SAML 转储的相同证书也用于 JWT 签名,这让我们的工作更轻松,因为转储此证书的工具和技术已经在此处可用。
如果我们使用私钥,我们可以编写一个简单的 Python 脚本来生成一个新的 JWT,其中包含我们想要的任何声明:
Set-AdfsGlobalAuthenticationPolicy –DeviceAuthenticationMethod All9
同样,我们可以替换传递给 ClaimsXRay 的生成的访问令牌,并查看我们可以添加所需的任何声明或范围:
结论
所以我们有了它,ADFS OAuth2、DRS、设备身份验证、设备写回和一些黄金 JWT 的大脑转储。一些有用的位,以及一些不太有用(但同样有趣)的位。
如果您是刚刚偶然发现客户端 ADFS 部署后在 Google 上搜索 UUID 的人,希望这篇文章能提供一些东西来让您的生活更轻松一些。
如果是这样的话,请给我大喊大叫并分享这个故事!
参考资料和感谢
深入了解 Azure AD 设备加入 - https://aadinternals.com/post/devices/ RoadTools — https://github.com/dirkjanm/ROADtools 进一步深入研究 Primary Refresh Token — https://dirkjanm.io/digging-further-into-the-primary-refresh-token/
其它相关课程
新课
详细目录
mac/ios安全视频
QT开发底层原理与安全逆向视频教程
linux文件系统存储与文件过滤安全开发视频教程(2024最新)
linux高级usb安全开发与源码分析视频教程
linux程序设计与安全开发
rust语言全栈开发视频教程
更多详细内容添加作者微信
windows网络安全防火墙与虚拟网卡(更新完成)
windows文件过滤(更新完成)
USB过滤(更新完成)
游戏安全(更新中)
ios逆向
windbg
还有很多免费教程(限学员)
windows恶意软件开发与对抗视频教程
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
还没有评论,来说两句吧...