SAML 单点登录协议把 XML 签名、规范化转换和信封式签名揉在一起,缺陷层层嵌套,被安全研究者称为坏设计的分形。这个诞生于 2002 年的协议至今仍在企业环境大量部署,XML 签名包装攻击、解析器差异攻击和规范化绕过不断在新产品里出现,GitHub Enterprise 也中招过。维护 SSO 集成的团队需要重新评估它的使用范围,并规划向 OpenID Connect 迁移。
这篇文章面向正在维护企业级 SSO 的开发者、安全工程师和架构决策者。无论你是在选型身份提供商,还是在排查现有集成漏洞,这里的设计分析和加固建议都能用上。
SAML 的复杂性从哪里来
SAML 由 OASIS 安全服务技术委员会在 2002 年制定,合并了四个早期协议。设计委员会把各家功能全部保留,规范体积庞大。实际部署约九成场景只用一小部分功能,实现方仍要处理完整规范。协议还假设身份提供商和服务提供商断连,强制走携带大量签名数据的前端信道,与零信任架构和移动应用存在根本冲突。
XML 带来了哪些遗留问题
SAML 选择 XML 作为编码格式,继承了 XML 的全部漏洞类别。外部实体注入、实体扩展攻击、DTD 检索、XPath 和 XSLT 注入都成为部署中的潜在风险。更关键的是规范化转换。签名者和验证者必须对同一份 XML 产生一致的字节表示,否则签名验证失败。这个转换极易出错,2018 年的 XML 注释绕过漏洞就来自规范化缺陷。JSON 只有键、值、对象和数组,攻击面小得多。
签名包装攻击为什么屡禁不止
XML 签名包装攻击被视作 SAML 的阿喀琉斯之踵。2012 年的研究首次系统展示了这类攻击,随后出现的自动化测试工具帮助厂商修掉一批漏洞。攻击原理是修改已签名的断言内容,同时让签名验证通过。SAML 使用信封式签名,把 Signature 元素放在被签名的 Assertion 内部,不像 JWT 那样分离签名。这种设计让篡改签名数据变得容易。simpleSAMLphp 早期对这类攻击表现出韧性,多数其他实现都存在问题。2025 年曝光的多个漏洞表明,签名包装和解析器差异攻击仍在活跃出现。
工程团队应该怎么应对
新的 SSO 集成优先选择 OpenID Connect。OIDC 基于 JSON 和 JWT,设计更简洁,后端信道交换 token 也更符合现代安全实践。现有系统必须保留 SAML 的话,可以采取以下加固措施。
- 严格限制接受的 SAML 消息格式,只处理与主流身份提供商输出结构一致的消息。
- 禁用 XML 外部实体解析,关闭 DTD 处理,限制实体扩展。
- 使用经过充分审计的 SAML 库,避免直接调用底层的 libxmlsec。
- 实施解析器一致性检查,确认签名验证前后的 XML 表示完全一致。
- 监控异常登录模式,关注签名验证失败的重复尝试。
留在 SAML 的边界和风险在哪里
OIDC 不能替代所有场景。某些遗留系统深度绑定 SAML 的断连假设,迁移成本可能超过安全收益。迁移决策需要评估集成数量、业务关键性和身份提供商的 OIDC 支持程度。Fly.io 和 Tailscale 等公司坚持只支持 OIDC,避开了整套攻击面。无法立刻迁移的组织可以走分阶段下线,先停止接入新的 SAML 集成,再提供等效的 OIDC 配置,最后设定日落日期。
FAQ
问,现有 SAML 集成需要立即停用吗
不需要立即停用,但应停止接入新的集成,同时启动迁移评估。优先处理暴露在外部网络、承载敏感数据的集成。
问,simpleSAMLphp 还算安全吗
它在签名包装攻击上表现较好,但依赖 PHP 生态,评估要覆盖整个依赖链,不能只看单一库的历史表现。
问,libxmlsec 的主要风险是什么
它是一个复杂的 C 语言代码库,审计覆盖不足。多数 SAML 库封装它做签名验证,底层漏洞会影响所有依赖方。
问,怎么检测现有集成是否被攻击
关注签名验证失败日志、异常时段的登录尝试和异常地理位置的访问。定期跑自动化签名包装测试,有助于发现配置缺陷。