乐于分享
好东西不私藏

OpenClaw CVE-2026-25593漏洞分析

OpenClaw CVE-2026-25593漏洞分析

最近有同学问了我这样一个问题:

协议设计和代码实现,哪个更重要?

名词解释:【协议设计(Protocol Design)】定义系统允许发生什么,而代码实现(Implementation)决定这些规则具体如何被执行。前者是安全边界的抽象定义,后者是安全机制的具体落地。

通俗理解:协议像规矩,代码像执行规矩的人。规矩错了,执行再好也没用;规矩对了但没人认真执行,也一样出问题。

这个问题有点像是问:公司里算法团队和软开团队谁更重要。其实是个伪命题,真正危险的从来不是单点失误,而是同时出错。当协议层的信任假设本身就有问题,代码实现又没有兜底,甚至把这种错误信任进一步放大时,漏洞的破坏力往往不是叠加,而是跃迁。

名词解释:【信任假设(Trust Assumption)】是安全模型中的基础前提,一旦这个前提错误,所有基于它构建的安全机制都会失效;而“跃迁”指的是系统风险从局部缺陷升级为整体失控。

这篇文章就来通俗的分析下OpenClaw 的一个很火的漏洞(CVE-2026-25593),以及攻击路径。别担心,所有抽象名词都附上通俗的解释,不是网络工程专业的同学也完全能看懂。

一、只是点了一个网页,攻击链已经形成

先不谈漏洞,我们先从一个非常日常的场景开始。

你在本地运行着 OpenClaw,一个可以帮你自动化操作的 AI Agent,本质上是一个可以调用接口的程序,它通过系统调用(system call)、网络请求(API call)或命令执行来完成任务,比如读取文件、执行系统命令等。因为这个程序只监听在 localhost:18789,所以你一直觉得它是安全的——毕竟当程序绑定到localhost(127.0.0.1)时,它只允许同一台计算机上的其他程序发起连接,外部设备(包括局域网内的其他电脑或互联网)无法直接访问。

名词解释:【监听(listen)】是指程序在指定的IP地址和端口上启动一个等待机制,准备接收来自其他程序的网络连接请求。它就像一家商店在特定门口挂出“欢迎光临”的牌子,随时准备迎接顾客上门。

名词解释:【端口(port)】是计算机网络中的一个逻辑编号(范围通常为0–65535),用于区分同一台设备上同时运行的多个网络服务。例如,网页服务常用80或443端口,而OpenClaw的Gateway服务默认使用18789端口。端口就像大楼里的不同房间号,帮助系统准确地将数据送达正确的应用程序。

    名词解释:【网络连接】是指两个程序之间通过网络协议(如WebSocket、TCP)建立的通信通道。一端发送请求,另一端接收并响应。连接可以发生在同一台计算机内部,也可以跨越不同设备。

    通俗理解:就像您在自己家里开了一扇只允许家里人进出的卷帘门(OpenClaw 监听在 localhost:18789)。您以为只有自己和信任的家人能进来(localhost限制只允许同一台计算机上的其他程序发起连接),但实际上,家里任何正在运行的“访客”(例如浏览器中加载的网页里的JavaScript代码,陌生人只要能进到你家,就能卷帘门)也可以通过这扇卷帘门与服务对话。这正是OpenClaw在本地部署时看似安全,却仍存在被浏览器恶意页面利用风险的根本原因。

    某天,你点开了一个朋友发来的链接。页面很普通,甚至可以说什么都没发生。你关掉它,继续工作。

    但就在那短短几秒钟里,浏览器中的一段 JavaScript,已经完成了一整条攻击链:

    名词解释:【JavaScript】是在浏览器中执行的脚本语言,具备发起 HTTP/WebSocket 请求的能力,可以与本地或远程服务通信。

    通俗理解:网页不是静态页面,而是会在你电脑里运行代码的小程序。

    它悄悄连接上了你本机的 OpenClaw 服务,通过 WebSocket 调用了其内部的 config.apply 接口,修改了一项名为 cliPath 的配置参数,并在这个参数里埋入了一段精心构造的恶意命令。接下来,只需等待 OpenClaw 的某个常规流程被触发导致cliPath 的配置项被解析,其中的恶意命令就会以 Gateway 进程的权限在你的机器上被执行,做攻击者想要做的事情。

    整个过程没有下载文件、没有弹出任何提示或警告窗口。你唯一做过的动作,就是点开了一个看似普通的网页。

    名词解释:【WebSocket】是一种全双工通信协议,允许客户端与服务器建立持续、双向的连接并实时交换数据。WebSocket不像普通网页请求那样一问一答(发送请求后立即得到响应然后结束),更像建立了一条一直开着的聊天通道,一旦连接成功,浏览器里的 JavaScript 可以随时向 OpenClaw 服务发送指令,OpenClaw 也可以随时回复,而不需要每次都重新建立连接。这条通道让攻击变得更加隐蔽和高效。

    名词解释:【config.apply】接口是 OpenClaw Gateway 提供的一个 WebSocket接口,用于让客户端(包括浏览器中的 JavaScript)动态修改系统的配置信息。 通俗理解: 它就像 OpenClaw 的设置修改按钮。正常情况下,用户或前端界面可以通过它来更改一些运行参数,例如指定某些工具的路径。但在这个漏洞中,该接口没有要求身份验证,任何本机上的 JavaScript 都可以直接调用它来改配置。

    名词解释:【cliPath 参数】攻击者通过 config.apply 接口,将一个名为 cliPath 的配置项修改为恶意内容。cliPath 本来用于指定 OpenClaw 查找和运行命令行工具的路径(例如某个可执行文件的地址),攻击者在这里把 cliPath 的值改成类似 "; rm -rf /; #" 这样的内容,意为:强制递归删除根目录(/)下的所有文件和子目录,原本单纯的路径就变成了“路径 + 恶意命令”的组合。

    这并不是一个假设场景。安全研究人员已经在真实环境中复现了类似攻击:用户只需访问一个恶意网站,本地运行的 AI Agent 就可能被直接接管,过程中不需要下载任何程序,也不会触发明显提示。

    更关键的是,这类问题往往不是单个漏洞,而是多个环节叠加形成的攻击链。一旦链条被打通,攻击者就可以从一个看似无害的入口,一路走到系统执行层。

    二、程序员不背这个锅

    如果只从实现层面看,这个漏洞很好理解:未认证接口 + 命令注入,这是教科书级别的组合。

    名词解释:【未认证接口(Missing Authentication)】意味着敏感操作未受访问控制;【命令注入(Command Injection, CWE-78)】指用户输入被拼接进系统命令执行。

    但如果只关注了实现层面,你会错过问题最关键的一层:为什么浏览器里的网页,能触达一个本应只允许本地访问的服务?

    答案在协议设计里。

    OpenClaw 在设计 Gateway 时,做了一个非常常见、也非常危险的假设:只要请求来自 localhost,就可以认为是用户自己发起的,因此是可信的。

    名词解释:【基于网络位置的信任模型(Network-based Trust Model)】即用 IP来源替代身份认证。

    通俗理解:只要你在我家地址范围内,我就默认你是自己人。

    这个假设在十几年前或许还能成立,但在今天已经完全不适用了。因为现代浏览器本身就是一个强大的执行环境,网页里的 JavaScript 同样可以发起网络请求,而这些请求在操作系统看来,的确就是从 127.0.0.1 发出的,系统并不能区分:这是你在终端里手动发起的请求,还是某个网页替你发起的请求!“本地”这个属性,只描述了网络路径位置,却被错误地当成了身份凭证。

    这就是第一个问题:协议的信任边界建立错误。

    三、代码本可以兜底,但却把风险放大了

    实现层(代码)本应是最后一道防线,但在这个案例里,代码不仅没有收敛风险,反而把它彻底放开了。

    在 OpenClaw 的 WebSocket API 中,用于修改配置的接口 config.apply本应是敏感操作,但实际实现中,它既不需要认证,也没有任何来源校验,只要能建立连接,就可以调用。

    名词解释:【未授权敏感操作(Unauthorized Sensitive Action)】违反最小权限原则(Least Privilege)。

    通俗理解:谁都能改系统配置,相当于把管理员权限公开了。

    更关键的是,配置中的字段 cliPath 值未进行输入验证、转义或白名单限制,在后续流程中直接被拼接进 shell 命令执行...这里其实还是我们前期公众号分析的“不要把不可信的数据,当成代码执行”为什么 OpenClaw 能把你账号里的钱转走?

    也就是,协议层让网页可以连进来,实现层让连进来之后可以直接执行命令。

    四、双重缺陷的放大效应

    攻击链完整还原如下:

    用户点击恶意链接     ↓ 网页JS发起WebSocket连接(ws://localhost:18789)     ↓ [协议层] 无认证 → config.apply调用成功     ↓ [实现层] 写入恶意cliPath(含shell注入)     ↓ OpenClaw触发命令发现     ↓ [协议+实现] shell拼接执行恶意命令     ↓ Gateway权限下任意代码执行

    若仅存在协议缺陷,攻击者虽能连接,但输入验证可阻断注入;若仅存在实现错误,协议层认证要求将阻止未授权访问。两者叠加,使得本地连接从安全假设变为高危入口。

    五、把这个案例讲给学生时,我更关心什么

    我在课堂上使用此案例,会建立这样一套系统性分析框架:

      1、识别信任假设协议/代码默认相信了什么?(本例:localhost连接即为可信本地客户端)2、评估假设合理性在当前威胁模型下是否成立?(本例:不成立,浏览器JS可模拟本地请求)3、检查协议防御条款是否要求认证、校验来源或参数约束?(本例:无)4、审查实现防御措施代码是否在协议基础上添加额外保护?(本例:无,反而强化缺陷)5、量化叠加效应双重缺陷如何改变攻击门槛与危害程度?(本例:从需本地程序变为:一点击即RCE)
      安全编程的核心原则:
      1、绝不以来源位置替代身份验
      身份认证必须基于凭证(token/密码/证书),而非网络属性。无论请求来自何处,均需完整认证流程。错误写法:
      if (remoteAddress === '127.0.0.1') {     skipAuth(); };
      2、把所有可配置的数据都当作不可信输入
      配置文件、数据库字段、环境变量,这些东西一旦进入执行路径,就必须经过严格的校验和约束。同时,尽量避免把数据直接拼接进解释型执行环境,比如 shell。
      3、限流、输入验证等底线防护适用于所有连接,调试功能需隔离独立通道。

      回首页,搜索你想要的文档

      在首页搜索框输入关键词,快速定位资料

      文库首页搜索指引 立即搜索

      相关学习资料