🚨 CVE-2026-123158 幽默荒诞的认证穿透 · *SSHOLE

sshhole (*sshole) 深度图解:
输入大于 256 字符的任意密码,
竟能直接登入禁用密码的 Linux root 账户!

2026 年 11 月 5 日,OpenSSH 紧急发布 10.6p2 修复了一个潜伏整整十年的惊天逻辑漏洞 CVE-2026-123158(代号 *sshole)。在 Alpine Linux、OpenWrt 等基于 musl libc 的轻量 Linux 系统上,对于原本专门设置成【禁止密码登录(shadow 里是 * 号)】的 root 或密钥部署账户,黑客只要输入任何一段长度超过 256 字符的长密码,sshd 居然当场放行开门!

一文彻底拆解:2012 年 musl 限制密码防 DoS、2016 年 OpenSSH 防用户枚举借用 Salt、2022 年 Alpine 将 root 锁为星号的三方历史碰撞,以及为什么 "*" == "*" 酿成全网大灾难。

💥 荒诞破门现场:当防 DoS 错误码撞上了账户锁定码

系统在 /etc/shadow 里把 root 密码写成 *,本意是“该账户无密码,永远不可能匹配”。黑客输入超长 257 字节垃圾密码,musl 库为了防 DoS 拒绝哈希并返回 "*"。OpenSSH 拿 "*" 与 "*" 比对,发现两边一模一样,当场判定密码正确开门!

musl crypt(>256B) 超长报错返回 "*" shadow 密码字段 禁用密码标记也是 "*" strcmp("*", "*") == 0 ➔ 判定密码正确,直接 Root! CVSS 3.1 评分 8.1 高危 完全无须猜测真实凭证 Alpine / OpenWrt 容器全线波及

🛡️ OpenSSH 10.6p2 修复:拒绝任何过短的假哈希

修复手段极其冷静干脆:sshd 在做密码字符串比对前,强制检查目标 shadow 里的哈希长度是否太短!合法的 sha512crypt 哈希至少有几十个字符,若发现字段只是区区一个 * 号,直接认定为非法凭证拒绝登录,彻底终结星号巧合。

哈希合法性长度审查 验证是否为有效哈希 阻断单字符比对 星号一律当作无密码拦截 apk upgrade openssh ➔ 重新焊死安全大门 严格哈希长度校验 Alpine 全部分支紧急热更推送 临时加固:PasswordAuthentication no
💡 核心比喻:三个聪明人各出一计,合在一起变成了一个大笑话
• 第一幕(2012 年 musl 门卫防累死): 门卫发现如果有人塞进来的密码超过 256 个字,核对起来太慢会被累死(DoS),于是立下规矩:‘凡是超过 256 个字的,我就不验了,直接在纸上盖一个【*】章表示拒签’;
• 第二幕(2016 年 OpenSSH 防小偷探听): 门卫发现小偷会卡秒表计算查密码的时间来推测谁是真实用户。sshd 决定:哪怕遇到没密码的用户,也借用隔壁老王的加密盐算一遍,假装算得很辛苦;
• 第三幕(2022 年 Alpine 锁门): 运维为了禁止 root 账户密码登录,在档案库写下:【root 的密码是:*】;
• 大结局(悲剧发生): 黑客跑来登 root,随手粘贴了一段长达 300 个字的废话。musl 门卫觉得太长不想算,盖上一个 * 章;sshd 拿着盖好的 * 去翻档案库,惊喜地发现:‘天哪!档案库里写着 root 密码正好就是 *,两张纸一模一样,密码完全正确,快请进!’

十年未被发现的三个巧合:漏洞是如何拼装成型的?

📜

1. 为什么是 256 字符?musl 的防死锁机制

在 Linux 常用 C 库中,glibc 可以吃下几千字符的密码;但专注于嵌入式轻量的 musl libc 开发者发现,密码越长 sha512crypt 运算耗时越呈指数级飙升。为了防止单个大密码卡死 CPU,musl 硬编码了 256 字节上限,超长直接返回固定标记 *。

偏偏 * 在 Unix 历史上刚好代表“被禁用的空密码”。

⏱️

2. CVE-2016-6210:防计时攻击的借盐乌龙

如果目标用户在 /etc/shadow 里没有密码哈希,原本根本不应该去调 crypt()。但 OpenSSH 为了防御针对用户名的侧信道枚举攻击(Timing Attack),刻意从系统里抓取另一个已有密码用户的 Salt 假装算一遍,无意间把超长密码喂给了 musl!

原本用于保护隐私的安全特性,反向把钥匙递到了黑客手里。

🏔️

3. Alpine 3.16 的感叹号 vs 星号之争

2019 年 Alpine 曾因 root 密码为空(CVE-2019-5021)用 ! 锁死账户。但运维发现没有 PAM 的环境下,! 会连带干掉公钥登录!为了让 AWS/Azure 云镜像能正常用 SSH Key 登入,Alpine 在 3.16 把 root 换成了 *。

由此,全部多米诺骨牌彻底就位。

🧪 交互漏洞攻防探针

点一点:透视黑客如何用 257 个字符直接撞开 root 大门

点击下方步骤,看认证流程如何在每一步逻辑中阴差阳错完美放行:

注:本探针严格按照 sshhole.com 披露记录与 OpenSSH 10.6p2 源码修复逻辑构建。

深度拆解:谁在危险射程之内?你中招了吗?

🎯

1. 触发漏洞的“全中条件”

必须同时满足以下所有条件才会被破门:
• 系统基于 musl libc(Alpine Linux、OpenWrt、Buildroot);
• 没有使用 PAM 模块(Alpine 默认未启用 PAM);
• 开启了密码登录(PasswordAuthentication yes 默认开启);
• 目标账户密码字段是 *(root 或仅公钥部署用户);
• 系统中至少有另外一个用户设置了正常密码(供 sshd 借 Salt)。

☁️

2. 云上 Alpine 用户的灭顶之灾

在 AWS、Azure 官方 Alpine 镜像中,默认用户 alpine 密码就是 *,而且它拥有免密码执行 doas(Alpine 的 sudo)的最高权限!黑客一旦随手敲入 257 字符登入 alpine 账户,1 秒内直接跃迁为系统最高 root!

🛡️

3. 谁是绝对安全的?

Ubuntu、Debian、CentOS、RHEL 等绝大多数使用 glibc 的发行版安全;开启了 PasswordAuthentication no 的服务器安全;密码字段为 ! 的账户安全;仅使用 Dropbear 的小型路由器安全。

CVE-2026-123158 (*sshole) 应急排查与修复速查表(Cheat Sheet)

操作项目 标准执行命令 / 建议 通俗原理解释
第一步:升级软件包 apk upgrade -U openssh 安装已经合并修复断言的 OpenSSH 10.6p2 或对应 LTS 回移植补丁
第二步:必须重启服务 rc-service sshd restart 切记!仅升级 apk 不会替换内存中跑着的旧守护进程,必须重启生效
应急缓和:关掉密码 echo "PasswordAuthentication no" > /etc/ssh/sshd_config.d/00-no-pwd.conf 如果由于生产环境无法立即重启机器,强制关闭密码通道仅留密钥
排查是否已被入侵 grep "Accepted password" /var/log/messages 检查日志里是否有原本没有密码的账户(root、alpine)居然通过密码成功登录
重构容器基座镜像 重新拉取最新的 alpine:latest 构建 Docker 防止新发布的无状态容器依然继承老旧带洞的 Base 镜像

一句话带走

“三个各自合理的设计:一个为了防死机限制长度输出星号,一个为了防窃听假装借用盐算星号,一个为了禁密码在档案里记录星号——十年前埋下的三颗无辜齿轮,在时光长河中严丝合缝地咬合,最终在推开 root 大门的一瞬间,成了全人类安全史上最荒诞的一记回形镖。”

安全往往不取决于高深莫测的数学加密算法,而往往失陷在那些最无聊、最不起眼、没人愿意深究的系统胶水缝隙之中。