FlawOpen

flawopen.com/Teardowns/cve-2026-76504-cisco-sdwan-api-authentication-bypass

● CVE-2026-76504 · CVSS 9.8[1] · 严重
安全研究 · FlawOpen

CVE-2026-76504:Cisco SD-WAN Manager 身份验证绕过

CVE-2026-76504 允许未认证的远程攻击者绕过 Cisco Catalyst SD-WAN Manager 中的 API 身份验证规则,并以管理员权限访问 API。Cisco 已确认该漏洞遭到主动利用;请升级到对应分支的修复版本,并在确认设备安全前调查管理器是否已被入侵。[1], [5]

CVSS 向量CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H[1]
💡 通俗易懂的原理解析 (ELI5)

想象一扇受保护的门,安检只识别地址的一种书写方式。攻击者通过 URI 编码改写地址,一部分系统仍把它识别为同一扇门,而安全规则却没有识别出来。Cisco 表示,这种差异使请求可以跳过身份验证并以管理员身份访问 API。修复必须统一处理地址并执行相同的访问规则;对运维人员而言,Cisco 支持的修复方式是升级软件。[1]

核心概念与专有名词

URI 编码
使用百分号编码字节表示 URL 路径中的字符。所有处理层都必须一致地解码和比较路径。[1], [7]
身份验证绕过
请求在系统未按要求确认调用者身份的情况下到达受保护功能。[1]
API 会话规则
管理器在请求到达端点前,用于确认 API 请求具有有效身份验证会话的规则。[1]
CWE-177
URL 编码处理不当:对编码 URL 数据的处理不一致可能破坏安全决策。Cisco 将此弱点类别分配给该 CVE。[1], [7]

框架映射

根本原因剖析 (Root Cause)

Cisco 将 CVE-2026-76504 归因于 Catalyst SD-WAN Manager API 会话身份验证中对 HTTP 请求 URI 编码处理不当。特制请求可绕过用于限制特定 API 端点的身份验证规则,并以管理员身份获得访问权限。Cisco 给出的评分为 CVSS 3.1 9.8(严重),称产品不论系统配置如何都会受影响,并表示 PSIRT 于 2026 年 9 月获悉该漏洞正在遭到主动利用。公告将 URI 编码的 j_security_check 请求列为 IOC 示例,并明确警告任何一个 URI 编码字符都可能被利用;不要把该示例当作完整检测特征。Cisco 没有公开易受攻击的源代码或补丁差异,因此下方代码对仅用于说明授权设计,不是 Cisco 代码或漏洞复现。Cisco 按软件分支列出了修复版本,并说明没有能够彻底解决该漏洞的临时方案。网络访问限制和 Live Protect 防护盾均为临时缓解措施;防护盾可能影响正常登录,不能替代升级。[1], [5]

CVE-2026-76504 按部署方式划分的修复版本

部署方式 / 版本线修复版本所需操作
早于 20.9 的本地部署版本迁移到已发布修复版本的受支持版本线。执行迁移;不要继续使用不受支持的旧版本线。
本地部署 20.9 版本线20.9.10.1将每个 Manager 升级到此版本或该受支持版本线中的更高版本。
本地部署 20.12 版本线20.12.8.2将每个 Manager 升级到此版本或该受支持版本线中的更高版本。
本地部署 20.15 版本线20.15.6.1将每个 Manager 升级到此版本或该受支持版本线中的更高版本。
本地部署 20.18 版本线20.18.4.1将每个 Manager 升级到此版本或该受支持版本线中的更高版本。
本地部署 26.1 版本线26.1.2.1将每个 Manager 升级到此版本或该受支持版本线中的更高版本。
本地部署 26.2 版本线26.2.1将每个 Manager 升级到此版本或该受支持版本线中的更高版本。
Cisco SD-WAN Cloud (Cisco Managed)20.15.605 或更高版本;Cisco 表示托管服务已修复。确认使用的是托管服务;此托管更新无需客户执行操作。

攻击执行流程分解

步骤 1

远程请求到达管理器 API

无需账户或用户交互。暴露在互联网会增加风险;供应商表示该漏洞不受配置影响。[1]

步骤 2

URI 编码路径绕过身份验证规则

Cisco 指出 API 会话身份验证中的 URI 编码处理不一致。公开资料没有披露易受攻击的源代码实现。[1]

步骤 3

API 将请求视为管理员请求

成功利用可获得管理员权限。Cisco 确认存在主动利用,但没有公开访问后的完整攻击链。[1], [5]

步骤 4

升级并调查

收集 admin-tech 文件,将所有管理器升级到对应修复版本,然后请 Cisco TAC 检查证据。不要等待 TAC 回复后再升级。[1], [2]

源代码对比:漏洞与安全实现

Cisco 未公开易受攻击的源代码或补丁差异。此 Python 示例说明的是通用设计规则,并非 Cisco 代码:路由和授权必须使用同一个经过验证的规范化请求目标,受保护端点必须要求经过身份验证的主体。遵循路由器/framework 文档规定的规范化语义;不要添加临时解码逻辑或对路径重复解码。CVE-2026-76504 的受支持修复方式是升级到 Cisco 为相应分支指定的修复版本。[1], [7]

源码摘录: URI 规范化与授权边界的 Python 示例;并非 Cisco 源码

存在漏洞的实现
from urllib.parse import unquote, urlsplit


def dispatch(raw_target, session, routes):
    # 一层检查尚未解码的路径。
    path_for_auth = urlsplit(raw_target).path
    if path_for_auth.startswith("/api/") and session is None:
        raise PermissionError("authentication required")

    # 后续层会在查找路由前解码。两处判断可能不一致。
    route_path = unquote(path_for_auth)
    return routes[route_path]()
加固后的安全修复
import re
from urllib.parse import unquote, urlsplit


def canonical_path(raw_target):
    raw_path = urlsplit(raw_target).path
    if re.search(r"%(?![0-9A-Fa-f]{2})", raw_path):
        raise ValueError("malformed URI encoding")

    path = unquote(raw_path, errors="strict")
    if "%" in path or "\\" in path:
        raise ValueError("ambiguous path encoding")
    if any(part in {".", ".."} for part in path.split("/")):
        raise ValueError("path traversal segment")
    return path


def dispatch(raw_target, session, routes):
    path = canonical_path(raw_target)  # Decode and validate exactly once.
    route = routes.get(path)
    if route is None:
        raise LookupError("route not found")

    requires_authentication, handler = route
    if requires_authentication and session is None:
        raise PermissionError("authentication required")
    return handler()

工程与系统安全加固清单

参考来源