ZooKeeper 未授权访问漏洞:你做的 ACL 加固可能只是“假动作”

在日常安全加固中,经常会收到基础架构或安全部门的反馈:ZooKeeper 存在未授权访问漏洞。很多同学拿到需求后的第一反应是"加个 ACL 就好了",于是动手操作一轮:添加超级用户、给某个节点设置 IP 白名单、然后觉得超级用户碍事把它删掉,顺便禁掉四字命令。这一套"组合拳"打下来,是不是就算修复完成了?

答案是:远没有。本文将以一个实际的操作过程为例,拆解其中的误区,并给出真正有效的修复方案。


一、常见的"加固"操作回顾

假设我们接到了漏洞修复任务,顺手完成了以下步骤:

  1. 添加超级用户

    zoo.cfg 中配置 superDigest,让 super 用户获得最高权限:

    ini 复制代码
    -Dzookeeper.DigestAuthenticationProvider.superDigest=super:cY+9eK20soteVC3fQ83SXDvwlP0=

    重启节点后,可以用 addauth digest super:cloudera 登录。

  2. 为特定 znode 设置 IP 白名单 ACL

    bash 复制代码
    create /znode1
    setAcl /znode1 ip:192.168.0.74,192.168.0.75:cdrwa

    意思是只有 192.168.0.74192.168.0.75 能读写 /znode1

  3. 验证权限

    • .75 访问 /znode1 成功;
    • .76 访问 /znode1 被拒绝(Authentication is not valid)。
      感觉"ACL 生效了"。
  4. 删除超级用户配置

    去掉 superDigest 行,重启节点,让超级用户失效。

  5. 禁用危险的四字命令

    限制白名单:

    bash 复制代码
    4lw.commands.whitelist=conf,cons,crst,dirs,dump,gtmk,ruok,stmk,srst,srvr,stat,wchs,mntr,isro

看上去有认证、有 ACL、有指令限制,但为什么漏洞报告依然存在?


二、问题究竟出在哪里?

1. ACL 没有递归性,根节点及其他节点仍然"裸奔"

ZooKeeper 的 ACL 模型不是树状继承 的。你对 /znode1 设置了 ip 限制,但对根节点 //zookeeper 以及无数其他业务节点,并没有做任何限制。这些节点的 ACL 仍然停留在默认值:

makefile 复制代码
world:anyone:cdrwa

这意味着任何一个能访问 ZooKeeper 2181 端口的客户端,都可以:

  • ls / 列出所有节点;
  • get /敏感数据 直接读取;
  • create /evil 创建非法节点;
  • delete /关键路径 进行破坏。

"只保护一个节点"在安全层面上等同于没保护

2. IP 白名单的认证强度不足

ip 模式的 ACL 完全依赖客户端来源 IP。它的缺点很明显

  • 同一网段的任何机器只要 IP 被列入白名单,就拥有完整权限,无法区分"谁来操作";
  • IP 可能被伪造,或者作为跳板机被攻陷后滥用;
  • 缺乏账号体系,无法审计、无法精准回收权限。

所以用 IP ACL 来兜底未授权访问,安全部门通常是不接受的,他们会要求采用 digest 或 SASL 认证

3. 删除了超级用户,阻塞了最后的应急通道

Super 用户是一种特殊的 digest 认证,可以无视所有 ACL 进行操作。它的设计初衷正是防止误配 ACL 把自己完全锁在外面,提供一条"超级后门"用于恢复。

你在没有建立完善的全局认证机制之前就把 super 用户删掉,一旦将来某个节点 ACL 配错导致所有业务账号都无法访问,集群将陷入不可管理的状态。安全加固不允许这种"玉石俱焚"的做法。

4. 四字命令限制是独立漏洞,不能替代访问控制

禁用危险的四字命令(如 wchcwchpdump 等)确实能阻止信息泄露和部分 DoS 攻击,但这是另一个漏洞。正常的 ZooKeeper 客户端 API 根本不需要四字命令就能读写数据,因此数据节点的未授权访问漏洞依然原封不动。


三、真正的修复方案

要彻底关闭"ZooKeeper 未授权访问漏洞",必须做到:任何未经认证的客户端连 ls / 都执行不了。具体步骤如下:

1. 启用 Digest 或 SASL 认证

推荐使用 digest 认证,并让所有业务客户端在连接时主动提供账号密码。在 zoo.cfg 中添加:

properties 复制代码
authProvider.1=org.apache.zookeeper.server.auth.DigestAuthenticationProvider

如果你有 Kerberos 环境,也可以切换到 SASL,这里不展开。

2. 移除根节点的 world 可访问权限

选择一个或几个管理员账号,用 digest 模式对根节点 / 重新设置 ACL,并移除默认的 world:anyone。例如:

bash 复制代码
# 先登录管理员账号
addauth digest admin:secure_password
# 设置根节点仅允许 admin 操作
setAcl / auth:admin:cdrwa

执行后,未认证的客户端再连接进来执行 ls / 时,会直接返回 Authentication is not valid。新创建的子节点也会默认继承 ACL(注意是"创建时指定 ACL 或连接会话的默认 ACL",所以还需在客户端侧设置好默认 ACL)。

更好的做法是:创建节点时显式指定 ACL,或在连接上通过 setAuthInfo 让所有新建节点都使用认证用户的 ACL。

3. 保留超级用户作为应急入口

zoo.cfg 中保留一条 superDigest 配置,密码强度要足够,并且只有核心管理员掌握。

properties 复制代码
-Dzookeeper.DigestAuthenticationProvider.superDigest=super:<加密后密码>

不要删除它,这是你最后的救命稻草。

4. 结合网络访问控制与四字命令限制

  • 在防火墙或安全组层面,将 ZooKeeper 的 2181 端口仅对受信 IP 段(如本集群机器)开放,杜绝外网探测;
  • 继续使用四字命令白名单,只保留运维必须的少量指令。

5. 验证效果

使用一个未认证的客户端尝试连接:

bash 复制代码
zookeeper-client -server <ip>:2181
ls /
# 预期结果:Authentication is not valid

而正常业务客户端配置了相同的 digest 凭据后,应该能正常读写。


四、总结

你认为的修复 实际情况
为测试节点加 ip ACL 根路径、其他节点仍然 world:anyone,漏洞依然存在
删除超级用户 失去紧急管理通道,加固反而降低了可用性
禁用部分四字命令 修复的是另一个漏洞,未授权数据访问依然不受限

ZooKeeper 的未授权访问漏洞,核心在于默认的 world:anyone:cdrwa 权限。除非你显式地将根节点 ACL 改为仅认证用户可访问,并以全局视角要求所有连接必须提供凭据,否则漏洞就等于没有修。

相关推荐
开开心心_Every9 小时前
安卓免费证件照制作软件,无广告弹窗
linux·运维·服务器·安全·elasticsearch·zookeeper·pdf
深蓝轨迹10 小时前
Kafka入门教程--帮你理清所有概念和细节
分布式·zookeeper·kafka
czlczl200209251 天前
Zookeeper
分布式·zookeeper·云原生
咸鱼2.04 天前
【java入门到放弃】Zookeeper
java·zookeeper
AIMath~5 天前
雪花算法+ZooKeeper解决方案+RPC是什么
分布式·zookeeper·云原生
白晨并不是很能熬夜7 天前
【RPC】第 4 篇:服务发现 — Zookeeper + 缓存容错
java·后端·程序人生·缓存·zookeeper·rpc·服务发现
星筏7 天前
深入理解分布式锁:ZooKeeper vs Redis
redis·分布式·zookeeper
Thanks_ks9 天前
分布式系统中的并发控制与分布式锁机制深度剖析
redis·zookeeper·高并发·分布式锁·架构设计·并发控制·分布式系统
千百元9 天前
zookeeper启不来了
linux·zookeeper·debian