bigywater.tech
ZooKeeper · 67

四字命令的安全风险

把四字命令白名单设成 * 很方便,但代价是什么?这篇站在防御者的角度,看一个没有认证的连接最多能通过四字命令拿到什么,以及怎么用白名单与网络隔离把暴露面压到最小。

不能读数据,但泄漏很多
路径、会话、客户端地址、运行环境都能看到
srst 会改监控数据
统计类命令是唯一会改变状态的
默认只开 srvr
不要为了方便设成 *

通过四字命令能看到什么

实测 · 本机执行输出
  conf  暴露:服务端配置(数据目录路径等)
         dataDir=<实验目录>
         dataDirSize=67109358
  envi  暴露:运行环境(Java 版本、用户名、工作目录、classpath)
         java.version=17.0.20.1
         os.name=Mac OS X
         user.name=w
  cons  暴露:所有客户端连接(来源地址、会话 id)
         /127.0.0.1:59141[1](queued=0,recved=5,sent=5,sid=0x1000c594b820000,lop=GETD,est=1790827418302,to=10000,lcxid=0
  dump  暴露:所有会话与它们持有的临时节点路径
         /svc/payments-prod
  wchp  暴露:被监听的路径与监听者
         /secret-config
  注意:四字命令读不到 znode 的数据内容(上面 /secret-config 的 password 没有出现),但路径名、会话、客户端地址、环境信息都能看到。

这是在我自己的本机实例上、用自己造的假数据测的。重点是对照默认配置:这些信息平时是被白名单挡住的。

读不到数据,也改不了数据

实测 · 本机执行输出
  srst(重置统计)前后 zk_packets_received:13 → 1(监控数据被清零)
  znode 数据没有被任何四字命令改变:/secret-config = b'db.password=hunter2'

收紧白名单

实测 · 本机执行输出
  ruok  → imok
  srvr  → Zookeeper version: 3.9.6-${mvngit.commit.id}, built on 2026-09-14 21:34 UTC
  envi  → envi is not executed because it is not in the whitelist.
  cons  → cons is not executed because it is not in the whitelist.
  dump  → dump is not executed because it is not in the whitelist.
  conf  → conf is not executed because it is not in the whitelist.
  默认可用的命令(上面五个里): ['srvr']
  被禁止时的提示: envi is not executed because it is not in the whitelist.

建议的做法

(1)保持默认白名单,或只放监控必需的命令;(2)客户端端口只绑定内网地址(clientPortAddress)并用防火墙限制来源;(3)指标监控改用只监听本机或内网的 Prometheus 端点(第 63 篇);(4)需要认证的访问用 SASL / TLS(第 75–77 篇)。这些是防御建议,其中白名单的行为是本文实测的。

分步演示

四字命令的暴露面
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / ZooKeeper 3.9.6(brew 安装的 jar,用 java -cp 直接启动自己的实例,OpenJDK 17 Temurin,JVM 堆 128 MiB)/ 本机回环端口 7300+,数据在临时目录;默认 tickTime=2000;计时用 time.perf_counter,数字每次运行会有小幅抖动。单机,仅 127.0.0.1;用自己造的假数据(/secret-config、/svc/payments-prod);没有做任何针对他人系统的测试
    • 没有验证:通过网络从另一台机器访问、四字命令对 TLS 端口的行为、AdminServer 的暴露面(第 68 篇)、DoS 类风险
    京ICP备2026067502号-1京公网安备11010502063487号