Nacos 3.1.1 升级 3.2.4 修复权限绕过漏洞记录
记录时间:2026-08-28 至 2026-08-30
环境:公司测试 / 生产xc / 生产xc-kj 三套 Nacos,nacos-server v3.1.1 升 v3.2.4,K8s StatefulSet 2 副本 + 外置 MySQL,Harbor 内网仓库(信创 ARM64)
一、事情的由头
2026-08-28 长亭发了通告:Nacos 3.0.0 至 3.2.3 管理接口权限绕过。3.x 对不同类型接口做了分层鉴权,部分管理接口的鉴权范围配置不一致,特定默认配置下没进预期的管理权限校验流程,不带凭证就能创建账户、调整角色、授资源权限,能做持久化后门。高危、远程、无需认证、无需交互,修复版 3.2.4 已发布,修复复杂度低。
我先盘家底。三套环境的镜像配置都在仓库里,grep 一把:
| 环境 | 镜像 tag | 暴露面 |
|---|---|---|
| 公司测试(xc/test) | v3.1.1 | NodePort 30848 + Ingress 控制台 |
| 生产xc(xc/xc-prod) | v3.1.1 | Ingress 控制台 |
| 生产xc-kj(kj/kj-prod) | v3.1.1 | Ingress 控制台 |
全部落在受影响区间。结论没有悬念:升级。
二、升级前先搞清楚鉴权开没开,这里我判断错了一回
我盯着三套环境 application.properties 里那行 nacos.core.auth.enabled=false,第一反应是:StatefulSet 里的 NACOS_AUTH_ENABLE=true 这个 env 没被 properties 引用,鉴权实际是关的,紧急度要上调。
把镜像里的启动脚本翻出来一看,当场打脸:
if [[ ! -z "${NACOS_AUTH_ENABLE}" ]]; then
JAVA_OPT="${JAVA_OPT} -Dnacos.core.auth.enabled=${NACOS_AUTH_ENABLE}"
fi
启动脚本把 env 转成 JVM 系统属性,而 Spring 的属性源里系统属性高于 application.properties,properties 里那行 false 是被覆盖的死配置。三套环境的实际生效状态:
| 配置项 | 文件里写的 | 实际生效 | 生效方式 |
|---|---|---|---|
| nacos.core.auth.enabled | false | true | env NACOS_AUTH_ENABLE 经启动脚本转 -D 覆盖 |
| nacos.core.auth.admin.enabled | true | true | properties 直配 |
| nacos.core.auth.console.enabled | true | true | properties 直配 |
三个开关全开。那缓解在位,还升不升?升。通告里的绕过本体就是”鉴权开启状态下管理接口没进预期校验流程”,缺陷在代码里,官方也明说临时措施不能替代升级,auth.enabled=true 只是把 Open API 这层收窄,admin 接口的绕过挡不住。
这条给我记死了:查 nacos 容器化的配置生效值,conf 文件和 env 两个来路都要看,-D 覆盖这条最容易漏。
三、升级窗口的一盆冷水:2 副本 Raft
三套都是 2 副本,Raft 多数派是 2。滚动替换任何一台,集群就失去多数派,配置发布中断,等节点起来重新同步(一般 1 到 3 分钟一台)。运行中的业务不怕:客户端有配置本地快照和服务发现缓存兜底,短暂重连自动恢复。所以升级窗口冻结配置发布就行,影响面是”窗口内改不了配置”,不是”窗口内业务挂”。
四、test 环境升级,apply 先吃了个 Forbidden
先查 Harbor 有没有现成的 v3.2.4,curl 一把 tags:v3.1.0、v3.1.1、v3.2.4 都在,镜像这关免了。改 tag,apply,API 直接拒了:
The StatefulSet "nacos" is invalid: spec: Forbidden: updates to statefulset spec
for fields other than 'replicas', 'ordinals', 'template', 'updateStrategy',
'persistentVolumeClaimRetentionPolicy' and 'minReadySeconds' are forbidden
我盯着报错看:镜像在 template 里,template 明明在允许清单里,那就是别的锁死字段跟线上对不上。把线上 sts 拉下来对比,翻到真凶:
kubectl get sts nacos -n tools -o jsonpath='{.spec.volumeClaimTemplates[0].spec.resources.requests.storage}'
# 线上实际 5Gi,仓库文件写的 10Gi
这条漂移怎么来的:历史上有过扩容意图,10Gi 写进了文件,但 volumeClaimTemplates 创建后不可变,那次 apply 压根没生效,10Gi 一直躺在文件里当摆设,这次连带把 tag 升级也拦了。仓库改成 5Gi,一把过。
注意:sts 的 volumeClaimTemplates 创建后不可变。仓库和线上漂移时 apply 是原子拒绝,不会半套生效,失败是安全的;想扩容的正确路径是单独 patch PVC,改 sts 文件没有用。
滚动 2/2 完成,两 Pod Running 零重启。功能模式也验了:
kubectl exec nacos-0 -n tools -- ps aux | grep -o 'nacos.functionMode=[a-z]*'
# 输出:nacos.functionMode=microservice
五、顺手关掉 AI 模块和旧版控制台
AI 模块用不上,升级时顺手关掉,改动如下:
| 参数 | 值 | 说明 |
|---|---|---|
| FUNCTION_MODE(StatefulSet env) | microservice | 运行时不加载 AI 模块,Config+Naming 组合模式 |
| nacos.extension.ai.enabled | false | AI 模块总开关,console 隐藏 AI 条目、AI console API 禁用 |
| nacos.plugin.ai-pipeline.enabled | false | AI 发布管线(skill-scanner),docker 版 conf 默认 true,一并关 |
| nacos.console.ui.default | legacy | 控制台默认用旧版 UI(new/legacy 二选一,默认 new),旧版也可走 /legacy/ 路径 |
env 和 properties 两个开关互为兜底,谁失效另一个兜着。逐项的官方文档佐证如下。
官方文档佐证
AI 模块总开关的定义(插件概览:状态、模块开关和选择配置):
层次:模块或能力总开关。职责:决定核心流程是否进入某类插件能力,也可用于延迟加载整个类型。示例:nacos.extension.ai.enabled、nacos.plugin.visibility.enabled、nacos.plugin.ai-pipeline.enabled
关闭写法与版本支持(控制台手册 FAQ 9.2:如何关闭控制台的AI功能相关页面):
在 application.properties 中添加:
### 是否开启AI功能,默认开启 nacos.extension.ai.enabled=false ### 是否开启AI功能中MCP相关页面/功能,默认关闭 nacos.ai.mcp.registry.enabled=false修改后需要重启 Nacos 实例方可生效。该配置在 3.2.x 版本中支持,3.1.x 及以下版本不支持。
注意:AI功能页面关闭后,不影响配置中心和服务发现模块的功能。
FUNCTION_MODE=microservice 的语义(部署概览:按功能模式选择模块):
功能模式只控制运行时加载的模块,仍然使用标准 Nacos 发行包,不会从发行包中移除 AI 相关 JAR。使用 -f microservice 后,无需再设置 nacos.extension.ai.enabled=false。
Nacos 3.2.0、3.2.1,或无法传递 -f 参数的部署方式,可以在 ${nacos.home}/conf/application.properties 中设置 nacos.extension.ai.enabled=false,关闭 AI 模块并保留 Config 和 Naming 模块。
旧版控制台默认入口(控制台手册:旧版控制台兼容说明):
旧控制台仍可通过配置 nacos.console.ui.default=legacy 作为默认入口,也可以直接访问 /legacy/。
### 设置控制台默认UI为旧版,可选值: new/legacy,默认 new nacos.console.ui.default=legacy
ConfigMap 是启动读取,改完要重启 Pod 才生效,别指望热加载。
六、验证清单
kubectl exec nacos-0 -n tools -- ps aux | grep -o 'nacos.functionMode=[a-z]*'
# 期望输出:nacos.functionMode=microservice
- console 版本号 3.2.4,AI 相关页面消失(extension.ai.enabled 生效的直观标志)
- 默认落在旧版控制台界面(ui.default=legacy 生效)
- 发一个测试配置,确认 Raft 写入和推送恢复
- 挑一个业务应用看日志,无配置拉取和注册报错
七、遇到的问题速查表
| 现象 | 根因 | 解法 |
|---|---|---|
| apply sts 报 spec Forbidden | volumeClaimTemplates 10Gi 与线上 5Gi 漂移 | 仓库改成跟线上一致 |
| properties 写 false 实际是 true | env 经启动脚本转 -D,系统属性优先级更高 | 查生效值要把 -D 覆盖一起看 |
| AI 关闭 key 在镜像 conf 里找不到 | docker 版 conf 与源码 distribution 版是两份文件,前者没跟上 | 以官方文档为准,ConfigMap 自带覆盖 |
| 3.1.1 上配 extension.ai.enabled 无效 | 该配置 3.2.x 才支持 | 与升级同批生效 |
| ConfigMap 改了配置没变化 | properties 是启动读取,无热加载 | rollout restart sts |
| 单加 FUNCTION_MODE 怕静默失败 | env 方式失败时 AI 回退默认开启 | 与 properties 开关两边一起加 |
八、注意事项
- 升级窗口冻结配置发布。2 副本 Raft 少一台就失多数派,业务有本地快照兜底不挂,但窗口内发不了配置。
- sts 模板字段漂移要自查。手动维护 sts 文件的,apply 前先对一遍 volumeClaimTemplates 和线上实际值,历史扩容意图最容易变成这种”躺在文件里的死配置”。
- properties 里那行 auth.enabled=false 是死配置。实际被 -D 覆盖成 true,建议改成
${NACOS_AUTH_ENABLE:false}占位符写法,不然下一个读文件的人还会栽一遍。 - AI 关闭的验证在 console 不在文档。写上无害,生效与否升级后一眼便知。
- 升级后复核账户和密钥是通告要求的动作。查 users、roles、permissions 表有无异常账户,轮换管理员密码,漏洞暴露窗口从部署 3.1.1 起算;identity 还是公开默认值(
nacos_docker/nacos_docker@123),token 三套环境同一个串,轮换挂账。
九、参考资料
- 长亭安全应急响应中心:Nacos 管理接口权限绕过漏洞通告(2026-08-28)
- Nacos 3.2.4 Release Notes
- 修复 PR #15563
- Nacos 插件概览:状态、模块开关和选择配置
- Nacos 控制台手册(FAQ 9.2 关闭 AI 页面、旧版控制台兼容)
- Nacos 部署概览:按功能模式选择模块
- nacos-docker v3.2.4 README