安全断言标记语言(SAML)是一种开放标准,用于在联合身份系统中的各方之间交换身份验证和授权数据。它支持跨域的单点登录(SSO)。关键组件包括:
在典型的SAML流程中,SP将用户重定向到IdP进行身份验证。IdP返回包含关于用户(例如,电子邮件、姓名)的断言的已签名SAML响应。SP验证签名并配置或登录用户。
CVE-2021-21239是pysaml2库(版本<6.5.0)中的一个签名验证绕过漏洞,该库被Redash <=10.1.0用于SAML SSO。从高层次看,它允许攻击者伪造一个带有任意嵌入公钥的SAML响应,从而通过即时(JIT)配置实现用户模拟和权限提升。
该漏洞源于pysaml2调用xmlsec1验证SAML签名的方式。Xmlsec1默认优先使用SAML响应中<ds:KeyInfo>内嵌入的公钥,而不是已配置的IdP证书。攻击者可以构造一个带有自生成RSA密钥对的SAML响应,将公钥嵌入<ds:RSAKeyValue>,并使用私钥对断言进行签名。由于pysaml2没有限制xmlsec1只使用受信任的IdP证书,伪造的签名被认为是有效的,从而允许攻击者以任何用户(例如admin)身份登录并获得最高权限。
在代码层面,漏洞存在于pysaml2的sigver.py(check_signature函数)中。xmlsec1命令列表缺少--enabled-key-data raw-x509-cert选项,允许xmlsec1使用不受信任的嵌入密钥:
com_list = [
self.xmlsec, '--verify', '--enabled-reference-uris', 'empty,same-doc',
'--pubkey-cert-pem', cert_file_name,
'--id-attr:%s' % id_attr, node_name,
'--node-id', nodeid, '--output', output_file_name, xml_file_name
]
这使得攻击者可以修改<saml:NameID>中的电子邮件来模拟任何用户,并利用JIT配置。
要测试该漏洞,使用Docker Compose搭建本地Redash实例(v10.1.0或更早版本)。该设置涉及使用Google的IdP配置SAML SSO:
REDASH_SAML_LOGIN_ENABLED=true,REDASH_SAML_METADATA_URL=...来自Google的IdP)。此设置允许通过Python脚本或Burp Suite发送伪造的SAML响应进行测试,验证权限提升。
该漏洞的产生是因为pysaml2的xmlsec1调用允许使用嵌入密钥进行验证,绕过了受信任的IdP证书。攻击者生成一个RSA密钥对,构造一个带有公钥(位于<ds:RSAKeyValue>)的SAML响应,修改属性(例如将电子邮件改为admin的),并对断言进行签名。Xmlsec1使用嵌入密钥进行验证,认为其有效。
修复程序在pysaml2 v6.5.0中实现(初始提交于2021年1月17日),位于src/saml2/sigver.py。xmlsec1命令列表更新为包含--enabled-key-data raw-x509-cert,将验证限制为仅使用已配置的IdP证书:
com_list = [
self.xmlsec, '--verify', '--enabled-reference-uris', 'empty,same-doc',
'--pubkey-cert-pem', cert_file_name,
'--enabled-key-data', 'raw-x509-cert',
'--id-attr:%s' % id_attr, node_name,
'--node-id', nodeid, '--output', output_file_name, xml_file_name
]
这强制执行信任链验证,防止使用嵌入密钥。Redash通过升级后续版本(例如v11+)中的pysaml2来修复此问题。易受攻击的版本没有使用--insecure;该错误是缺少限制选项。
利用代码在cve-2021-21239.py中实现。此Python脚本自动化了伪造SAML响应的过程,以利用Redash <=10.1.0中的CVE-2021-21239漏洞,通过JIT配置实现用户模拟和权限提升。该利用针对Google Workspace SAML IdP,但该攻击已在其他IdP(keycloak)上测试过。脚本执行以下步骤:
email="[email protected]")。idpid,确保与目标配置兼容。SAMLResponseTempalte.xml),其中包含用于电子邮件、姓名、时间戳和断言ID的占位符。生成动态的UTC时间戳,具有5分钟的有效期窗口,以通过Redash的验证。xmlsec Python库对<saml:Assertion>元素进行RSA-SHA256签名,并将公钥嵌入<ds:RSAKeyValue>以利用该漏洞。/saml/callback?org_slug=default)。利用CVE-2021-21239需要构造一个Redash通过JIT配置接受的伪造SAML响应。关键困难及绕过方法:
<ds:RSAKeyValue>,使用私钥签名来绕过。xmlsec1二进制文件可行,但Python xmlsec库由于空白/规范化问题导致摘要不匹配。通过在签名前将XML序列化为单行(etree.tostring(..., pretty_print=False))来绕过。NotOnOrAfter导致拒绝;通过使用具有5分钟有效期的动态UTC时间戳来绕过。SAMLResponse进行了双重编码,导致解析失败;通过发送原始表单数据来绕过。这些挑战凸显了精确的XML操作和环境设置对于有效利用该漏洞的必要性。提供的利用代码成功演示了这一点,伪造SAML响应以模拟用户并获得访问权限。