漏洞分析与实践之基于SAML实现的单点登录系统
字数 1963 2025-08-29 08:32:00
基于SAML的单点登录系统漏洞分析与实践教学文档
1. SAML基础概念
1.1 SAML定义
SAML(Security Assertion Markup Language)是一种基于XML的开放标准,用于在各方(特别是身份提供者和服务提供者)之间交换认证和授权数据。
1.2 核心组件
- 身份提供者(IdP):负责用户身份识别和认证的系统
- 服务提供者(SP):用户需要访问的应用系统
- SAML声明(Assertion):包含用户身份和其他属性的XML消息
1.3 工作模式
- IdP-Initiated:用户首先访问IdP,认证后获得SAML Response,再访问SP
- SP-Initiated:用户首先访问SP,被重定向到IdP认证,再返回SP
2. SAML工作流程
2.1 基本流程
- 用户尝试访问SP资源
- 用户被重定向到IdP进行认证
- 认证成功后,IdP生成SAML Response(包含SAML Assertion)
- 用户浏览器将SAML Response转发给SP
- SP验证签名并提取用户身份信息
- 验证通过后授予访问权限
2.2 SAML Response结构
<SAMLResponse>
<Issuer>https://idp.com/</Issuer>
<Assertion ID="_id1234">
<Subject>
<NameID>user@user.com</NameID>
</Subject>
</Assertion>
<Signature>
<SignedInfo>
<CanonicalizationMethod Algorithm="xml-c14n11"/>
<Reference URI="#_id1234"/>
</SignedInfo>
<SignatureValue>签名数据</SignatureValue>
</Signature>
</SAMLResponse>
3. 漏洞原理分析
3.1 漏洞成因
-
XML标准化处理差异:
- 签名验证时使用的
CanonicalizationMethod会忽略XML注释 - 但某些XML解析库在处理NameID时不会忽略注释
- 签名验证时使用的
-
具体表现:
- 原始NameID:
user@user.com.evil.com - 修改后NameID:
user@user.com<!--注释-->.evil.com - 签名验证时两者被视为相同(忽略注释)
- 但某些解析器提取NameID时可能只获取注释前部分
- 原始NameID:
3.2 技术细节
- 标准化方法:
http://www.w3.org/2001/10/xml-exc-c14n# - 解析不一致:
- 签名验证:忽略注释,
test@example<!--注释-->.com→test@example.com - 某些解析器:
test@example<!--注释-->.com→test@example
- 签名验证:忽略注释,
4. 漏洞复现实践
4.1 环境准备
- 下载受影响版本的OneLogin Python-SAML Toolkit(v2.3.0)
- 搭建基于Flask的SAML Demo系统
- 在IdP上创建两个测试用户:
- 用户A:
test1@cnnt.com - 用户B:
test1@cnnt.com.cnnt.com
- 用户A:
4.2 攻击步骤
-
获取合法SAML Response:
- 以用户B身份登录,获取SAML Response
-
修改SAML Response:
- 将NameID改为:
test1@cnnt.com<!---->.cnnt.com - 对应Attribute中的email也做同样修改
- 将NameID改为:
-
重新编码:
- 对修改后的XML进行base64encode+urlencode
-
发送篡改后的Response:
- 将篡改后的SAML Response发送给SP
- 观察是否成功获取用户A的访问权限
4.3 关键代码示例
原始NameID:
<NameID>test1@cnnt.com.cnnt.com</NameID>
篡改后NameID:
<NameID>test1@cnnt.com<!---->.cnnt.com</NameID>
5. 漏洞影响范围
5.1 受影响实现
- OneLogin python-saml (CVE-2017-11427)
- OneLogin ruby-saml (CVE-2017-11428)
- Clever saml2-js (CVE-2017-11429)
- OmniAuth-SAML (CVE-2017-11430)
- Shibboleth (CVE-2018-0489)
- Duo Network Gateway (CVE-2018-7340)
5.2 利用限制
- 需要已认证用户的合法SAML Response
- 目标用户的NameID必须是攻击者用户NameID的前缀
- 例如:攻击者用户为
123456,目标用户为1234
- 例如:攻击者用户为
6. 防御措施
6.1 修复方案
-
升级到已修复版本:
- OneLogin python-saml v2.4.0+
- 其他库的相应修复版本
-
实施NameID格式检查:
- 禁止NameID中包含XML注释
- 严格验证NameID的格式和内容
6.2 最佳实践
- 使用一致的XML解析方法
- 实施严格的输入验证
- 监控异常的认证尝试
- 定期审计SAML实现
7. 总结
本漏洞利用SAML实现中XML处理不一致的问题,通过精心构造包含注释的NameID绕过签名验证,实现权限提升。虽然利用有一定限制,但对使用受影响SAML实现的系统构成严重威胁。及时更新库版本并实施严格的输入验证是防御此类漏洞的关键。
8. 参考资源
- Duo Labs SAML漏洞报告
- SAML 2.0核心规范
- XML签名规范