SAML Basics

支持 HackTricks

SAML 概述

安全断言标记语言 (SAML) 使身份提供者 (IdP) 能够用于向服务提供者 (SP) 发送授权凭证,从而促进单点登录 (SSO)。这种方法通过允许在多个网站上使用一组凭证来简化多个登录的管理。它利用 XML 在 IdP 和 SP 之间进行标准化通信,将用户身份的认证与服务授权联系起来。

SAML 与 OAuth 的比较

  • SAML 针对企业提供更大的 SSO 登录安全控制。

  • OAuth 旨在更适合移动设备,使用 JSON,并且是 Google 和 Twitter 等公司的协作成果。

SAML 认证流程

有关更多详细信息,请查看完整帖子 https://epi052.gitlab.io/notes-to-self/blog/2019-03-07-how-to-test-saml-a-methodology/。以下是摘要:

SAML 认证过程涉及多个步骤,如下图所示:

https://epi052.gitlab.io/notes-to-self/img/saml/saml-flow.jpg
  1. 资源访问尝试:用户尝试访问受保护的资源。

  2. SAML 请求生成:SP 不识别用户并生成 SAML 请求。

  3. 重定向到 IdP:用户被重定向到 IdP,SAML 请求通过用户的浏览器传递。

  4. IdP 接收请求:IdP 接收 SAML 请求。

  5. 在 IdP 进行身份验证:IdP 对用户进行身份验证。

  6. 用户验证:IdP 验证用户访问请求资源的合法性。

  7. SAML 响应创建:IdP 生成包含必要断言的 SAML 响应。

  8. 重定向到 SP 的 ACS URL:用户被重定向到 SP 的断言消费者服务 (ACS) URL。

  9. SAML 响应验证:ACS 验证 SAML 响应。

  10. 资源访问授权:授予对最初请求的资源的访问权限。

SAML 请求示例

考虑用户请求访问 https://shibdemo-sp1.test.edu/secure/ 上的安全资源的场景。SP 识别到缺乏身份验证并生成 SAML 请求:

GET /secure/ HTTP/1.1
Host: shibdemo-sp1.test.edu
...

原始 SAML 请求如下所示:

<?xml version="1.0"?>
<samlp:AuthnRequest ...
</samlp:AuthnRequest>

关键请求的主要元素包括:

  • AssertionConsumerServiceURL:指定 IdP 应该在身份验证后将 SAML 响应发送到的位置。

  • Destination:请求发送到的 IdP 地址。

  • ProtocolBinding:定义 SAML 协议消息的传输方法。

  • saml:Issuer:标识发起请求的实体。

在 SAML 请求生成后,SP 以 302 重定向 响应,指示浏览器将 SAML 请求编码在 HTTP 响应的 Location 头中发送到 IdP。RelayState 参数在整个事务中维护状态信息,确保 SP 在接收到 SAML 响应时识别初始资源请求。SAMLRequest 参数是原始 XML 片段的压缩和编码版本,使用 Deflate 压缩和 base64 编码。

SAML 响应示例

您可以在 这里找到完整的 SAML 响应。响应的关键组件包括:

  • ds:Signature:此部分是 XML 签名,确保断言发起者的完整性和真实性。示例中的 SAML 响应包含两个 ds:Signature 元素,一个用于消息,另一个用于断言。

  • saml:Assertion:此部分包含有关用户身份的信息以及可能的其他属性。

  • saml:Subject:指定断言中所有声明的主要主体。

  • saml:StatusCode:表示对相应请求的操作状态。

  • saml:Conditions:详细说明断言的有效时间和指定的服务提供者等条件。

  • saml:AuthnStatement:确认 IdP 已对断言的主体进行身份验证。

  • saml:AttributeStatement:包含描述断言主体的属性。

在 SAML 响应之后,过程包括来自 IdP 的 302 重定向。这导致对服务提供者的断言消费者服务(ACS)URL 的 POST 请求。POST 请求包括 RelayStateSAMLResponse 参数。ACS 负责处理和验证 SAML 响应。

在接收到 POST 请求并验证 SAML 响应后,用户最初请求的受保护资源将被授予访问权限。这通过对 /secure/ 端点的 GET 请求和 200 OK 响应来说明,表示成功访问该资源。

XML 签名

XML 签名是多功能的,可以对整个 XML 树或其中的特定元素进行签名。它们可以应用于任何 XML 对象,而不仅仅是响应元素。以下是 XML 签名的关键类型:

XML 签名的基本结构

XML 签名由基本元素组成,如下所示:

<Signature>
<SignedInfo>
<CanonicalizationMethod />
<SignatureMethod />
<Reference>
<Transforms />
<DigestMethod />
<DigestValue />
</Reference>
...
</SignedInfo>
<SignatureValue />
<KeyInfo />
<Object />
</Signature>

每个 Reference 元素表示一个特定的被签名资源,通过 URI 属性可以识别。

XML 签名的类型

  1. 封装签名:这种类型的签名是其签名资源的后代,意味着签名包含在与被签名内容相同的 XML 结构中。

示例:

<samlp:Response ... ID="..." ... >
...
<ds:Signature>
<ds:SignedInfo>
...
<ds:Reference URI="#...">
...
</ds:Reference>
</ds:SignedInfo>
</ds:Signature>
...
</samlp:Response>

在封装签名中,ds:Transform 元素指定它是通过 enveloped-signature 算法进行封装的。

  1. 封装资源签名:与封装签名相对,封装资源签名将被签名的资源包裹起来。

示例:

<ds:Signature>
<ds:SignedInfo>
...
<ds:Reference URI="#...">
...
</ds:Reference>
</ds:SignedInfo>
<samlp:Response ... ID="..." ... >
...
</samlp:Response>
</ds:Signature>
  1. 分离签名:这种类型的签名与其签名的内容是分开的。签名和内容独立存在,但两者之间保持链接。

示例:

<samlp:Response ... ID="..." ... >
...
</samlp:Response>
<ds:Signature>
<ds:SignedInfo>
...
<ds:Reference URI="#...">
...
</ds:Reference>
</ds:SignedInfo>
</ds:Signature>

总之,XML 签名提供了灵活的方式来保护 XML 文档,每种类型满足不同的结构和安全需求。

参考

支持 HackTricks

Last updated