按照传统安全常识,被系统锁死的账号无法登录。输入任何密码都应被拒之门外。2026 年 11 月 5 日,轻量级操作系统 Alpine Linux 发布的安全公告打破了这个常识。
攻击者只要输入一段超过 256 字节的长密码,封禁的管理员账号就会敞开大门。整个过程没有破坏内存,也没有暴力破解哈希。防御系统在核对完密码与锁死标记后,主动放行了连接。
这种反常的穿透现象,源于三道独立防御机制的意外碰撞。当代表「计算失败」的错误信号与代表「禁止登录」的账户状态共用同一个字符,整套认证逻辑在交叉点上当场失效。
防守方设下三道机关,黑客塞进257位密码过了闸
在 Unix 操作系统的密码阴影文件 /etc/shadow 中,星号 * 已经存在数十年。只要某个账号的密码字段写着单个星号,系统就将其视为锁死状态。正常密码算出的哈希值包含几十个字符,绝不可能与单个星号相同。
为了防范黑客探测用户名,OpenSSH 的工程师设计了防计时分析机制。如果一个账号没有有效密码,认证服务不会直接报错。它会借用系统里另一个合法账号的哈希盐,强行算一次耗时相近的虚假哈希。这样一来,无论账号是否存在,服务器响应耗时都被抹平。
轻量级 C 语言库 musl 也有自己的防护边界。为了防止恶意长文本撑爆内存,musl 的 crypt() 函数划定了长度上限。输入密码一旦超过 256 字节,函数直接拒绝计算。此时底层会返回单个星号 *,以此作为出错标记。
三道机关单独拿出来看,每一处都符合严密的防御哲学。然而,当它们在同一个系统里同时运转时,攻击通道被悄然拼齐。
攻击者只需要满足四个先决条件:
其一,能够连上目标主机的 SSH 端口;
其二,目标系统内存在密码字段为 * 的账号,例如 Alpine 从 3.16 版本起默认的 root 账号;
其三,系统里至少还有一个设置了 $5$ 或 $6$ 格式哈希的正常账号;
其四,提交一段长度在 257 到 1024 字节之间的超长密码。
当这四个条件同时凑齐,OpenSSH 拿着超长密码去借盐计算。底层库因为超长限制退回了错误标记 *。OpenSSH 随后将这个返回值与 shadow 文件里的密码字段比对,两边都是单个星号。匹配结果宣告一致,锁死的大门应声而开。
图:Alpine Linux 官方安全公告,披露无 PAM 模式下的身份验证绕过。来源:alpinelinux.org。
星号既代表账号锁死,又代表底层算不出来
这个漏洞的核心冲突,在于不同软件层对同一个特殊符号赋予了截然相反的语义。上层软件把它当成了守门的铁锁,底层库却把它当成了抛出异常的白旗。
在传统实现中,密码加密函数处理无效输入时通常返回空指针。调用方只要检查返回值是否为空,就能区分计算成功与计算失败。但返回空指针容易导致老旧代码发生内存解引用崩溃。musl 选择遵循特定标准,在出错时返回一个指向静态字符 * 的指针。
这一设计假定调用方会意识到星号属于非法哈希。在通常情况下,这个假定确实没有问题。哪怕用户提交的密码被算成了星号,只要目标账号设置了真实的密码哈希,两者依然不会匹配。
偏偏 OpenSSH 内部的假盐逻辑补上了致命的一环。在未启用 PAM 模块的精简环境里,服务进程负责直接校验密码。为了不让黑客根据响应时间猜出账号状态,OpenSSH 决定对锁死账号同样执行一次加密运算。
这导致验证流程陷入困境。OpenSSH 以为自己在验证一段提交的密码,底层库实际上退出了计算。契约理解的偏差,让原本用于封锁的静态标记,变成了通关凭证。
云镜像预留隐形入口,多存一个密码就触发险情
漏洞暴露后,技术社区迅速排查了受波及的实际场景。并非所有 Alpine 环境都会受波及。实际风险取决于具体配置。
单纯用于运行独立微服务的轻量容器,通常不需要开放 SSH 远程连接。这类服务天然阻断了攻击路径。将配置设置为禁用密码认证的主机,同样对长密码免疫。采用 PAM 认证扩展的系统,由于校验流程交由独立模块接管,也不会触发两套星号的碰头。
真正危险的陷阱隐藏在云服务模板中。Alpine 官方推出的 tiny-cloud 镜像在 3.18.11 至 3.24.3 版本之间,预置了一个名为 alpine 的初始账号。该账号在 shadow 中的密码字段正是星号,并且配置了免密码提权权限。
在刚刚初始化的全新系统上,这个账号是安全的。因为整台机器里没有任何包含哈希盐的常规账号,OpenSSH 借不到盐,也就无法启动虚假计算逻辑。很多运维人员因此误以为默认模板坚不可摧。
风险在管理员添加第一个常规用户时瞬间爆发。一旦管理员为其他业务创建了带密码的普通账号,shadow 文件里写入了哈希记录,沉睡的 alpine 账号立刻变成远程提权的开门通道。黑客拿这个账号配合超长密码登录,就能直接获取最高权限。
升级软件包必须重启进程,关闭密码认证可紧急止血
官方在此次漏洞公开时并未申请专有 CVE 编号。研究员 Özgün Kültekin 最先发现了这一异常。OpenSSH 与 Alpine 团队随后完成了修复推进。修复细节记录在 OpenSSH 10.6p2 的发布说明中,补丁覆盖了 Alpine 3.16 到 3.24 以及边缘开发分支。
受影响的系统需要立即同步软件源并执行更新。在 Alpine 终端内运行 apk upgrade -U -a 命令后,软件包会将 OpenSSH 替换为修复版本。在修复后的代码中,OpenSSH 严格过滤了底层返回的异常字符,杜绝了符号混淆的可能。
图:OpenSSH 10.6p2 发布说明,详细记录针对超长密码与假盐匹配逻辑的修复。来源:openssh.com。
需要重点提醒的是,替换磁盘上的二进制文件并不能立即消除风险。旧版服务常驻内存运行,攻击者依然可以发起穿透。管理员在完成软件包升级后,必须执行 rc-service sshd restart 重启服务进程,确保新代码在内存中生效。
对于无法立刻安排重启维护的生产服务器,可以通过调整配置进行紧急止血。管理员可以在 /etc/ssh/sshd_config.d/00-no-passwords.conf 中写入 PasswordAuthentication no。测试配置无误后重载服务,并用 sshd -T 确认密码认证已经关闭。排查历史日志时,如果发现 /var/log/messages 中记录了无密码账号的登录成功条目,往往意味着系统已经遭遇攻击。
软件安全常常倒在系统边界的交界处。当每个组件各自遵循防御最佳实践,却在接口符号的定义上出现微小分歧时,精心构筑的防线就会从内部瓦解。保持符号语义的单一与确定,是比堆砌防御策略更为根本的工程戒律。
参考链接:
- Alpine Linux 安全公告
- OpenSSH 10.6p2 发布说明
- Lobsters 社区技术讨论