SAML 为什么被称为坏设计的分形

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 的话,可以采取以下加固措施。

  1. 严格限制接受的 SAML 消息格式,只处理与主流身份提供商输出结构一致的消息。
  2. 禁用 XML 外部实体解析,关闭 DTD 处理,限制实体扩展。
  3. 使用经过充分审计的 SAML 库,避免直接调用底层的 libxmlsec。
  4. 实施解析器一致性检查,确认签名验证前后的 XML 表示完全一致。
  5. 监控异常登录模式,关注签名验证失败的重复尝试。

留在 SAML 的边界和风险在哪里

OIDC 不能替代所有场景。某些遗留系统深度绑定 SAML 的断连假设,迁移成本可能超过安全收益。迁移决策需要评估集成数量、业务关键性和身份提供商的 OIDC 支持程度。Fly.io 和 Tailscale 等公司坚持只支持 OIDC,避开了整套攻击面。无法立刻迁移的组织可以走分阶段下线,先停止接入新的 SAML 集成,再提供等效的 OIDC 配置,最后设定日落日期。

FAQ

问,现有 SAML 集成需要立即停用吗

不需要立即停用,但应停止接入新的集成,同时启动迁移评估。优先处理暴露在外部网络、承载敏感数据的集成。

问,simpleSAMLphp 还算安全吗

它在签名包装攻击上表现较好,但依赖 PHP 生态,评估要覆盖整个依赖链,不能只看单一库的历史表现。

问,libxmlsec 的主要风险是什么

它是一个复杂的 C 语言代码库,审计覆盖不足。多数 SAML 库封装它做签名验证,底层漏洞会影响所有依赖方。

问,怎么检测现有集成是否被攻击

关注签名验证失败日志、异常时段的登录尝试和异常地理位置的访问。定期跑自动化签名包装测试,有助于发现配置缺陷。