CVE-2026-110109, CVE-2026-110110: JetLinks Community 允许只读用户覆盖产品透明消息编解码器,因为产品级保存处理程序缺少其保存操作检查(反应式授权绕过) 漏洞概述 JetLinks Community 的 REST 端点通过 hsweb 注解驱动的授权模型进行保护。控制器声明一个资源,每个处理程序声明它需要的操作(读取或写入)。授权拦截器仅在执行定义中携带的操作时才强制执行权限。 管理产品或设备的透明消息编解码器。设备级保存处理程序 携带 ,两个重置处理程序也携带 ,因此它们需要 保存操作。产品级保存处理程序 在 中省略了操作注解。 由于类仍然声明了 ,hsweb 构建了一个非空的授权定义,该定义命名了资源但持有零个操作。在请求时,拦截器仅要求调用者已认证并持有 资源的任何操作,因此授予只读(查询)访问权限的任何主体都可以调用产品级保存并覆盖编解码器。设备级兄弟和两个重置处理程序继续要求保存操作,这证明保存操作是预期的边界。 保存的编解码器由 和 持久化。对于内置的 提供程序, 是平台绑定并在服务器上运行的源代码,当解码或编码透明设备消息时。实际结果是,只读编解码器查看器可以替换产品下每个设备的消息解码逻辑,并向服务器端脚本引擎提供攻击者控制的脚本。同一根因的第二个实例允许只读 主体通过 和 启用或禁用任何警报配置。 影响范围 项目: JetLinks/jetlinks-community, reactive IoT platform (Spring WebFlux), device-manager transparent message codec configuration 受影响版本: 2.10.0 (pinned commit 60ecc9f65060ecfd3d8da8daec0b062f672834f3) 类: CWE-862 Missing Authorization, CWE-863 Incorrect Authorization 修复方案 修复状态: 已修复 修复分支: 2.11 和 master 分支上的相同处理程序未更改 根因 1. 产品级保存处理程序省略了其兄弟所需的保存操作 - 在类级别声明资源,但未添加类级 。 - 设备级保存处理程序需要保存操作。 - 产品级保存处理程序是写入同一表的单独重载。它携带 和 ,但缺少 。 - 同一类中的两个重置处理程序也携带 ,因此产品级保存中的缺失注解是孤立的遗漏,而不是类级设计选择。 2. hsweb 解析器保留类资源并返回非空定义 - hsweb 解析每个处理程序方法的授权定义。解析器收集 、 、 、 和 注解,从方法和类中。它仅在类和方法都携带它们时才返回空定义。 - 产品级保存方法没有授权注解,但类携带 。类注解集因此不为空,因此解析器跳过空定义分支并运行 ,这添加了无操作的资源(即 声明无操作)。 - 返回 ,因此拦截器将此处理程序视为受控端点。 2b. 操作注解是携带保存操作要求的 - 和 是组合资源操作注解。 声明保存操作, 声明查询操作。 - 当处理程序携带 时, 将保存操作附加到 资源,RBAC 检查然后要求 。产品级保存处理程序没有这样的操作,因此其资源保持无操作。 3. 反应式拦截器需要认证,然后运行 RBAC 检查 - 拦截每个控制器方法。它强制执行定义,除非定义不为空,并且对于反应式返回类型,它需要当前认证,除非定义允许匿名访问。 - 定义不允许匿名访问,因此未认证的请求被拒绝。已认证的请求继续到 。 4. 无操作资源满足该资源上持有的任何操作 - 询问资源集是否认证具有权限,并在没有时拒绝。 - 迭代其资源并询问认证每个资源 ID 及其操作 ID 集。对于产品级保存,资源是 ,其操作 ID 集为空。 - 在请求的操作集为空时返回 ,当持有权限时。文档注释说明状态为空的操作集意味着不检查操作,仅检查权限 ID。 - 产品级保存因此通过任何持有 资源权限的已认证主体,例如只读查询操作,以及任何持有通配符权限的主体。它不需要设备级兄弟和两个重置处理程序所需的保存操作。这是授权绕过。 5. 保存处理程序持久化攻击者提供的编解码器,脚本引擎运行 - 产品级保存委托给设备级主体,带有空设备 ID,持久化请求的 和 字段。对于内置的 提供程序, 是平台绑定并在服务器上运行的源代码,当解码或编码透明消息时。 POC 代码