Alpine Linux Security Advisory: OpenSSH-server password authentication bypass
627 points • 7 days ago • Article Link

Alpine Linux 发布了一项关于密码身份验证绕过漏洞的关键安全公告。该漏洞影响运行 openssh-server 软件包的系统:攻击者只要能访问 SSH 端口网络,即可在满足特定条件时在不知晓密码的情况下登录到目标账号。具体来说,该漏洞要求目标账号的密码字段被设置为星号(这在仅限密钥的账号中很常见),并且机器上至少还存在一个其他账号,该账号使用 SHA-256 或 SHA-512 密码哈希进行保护。当攻击者发送经过特殊构造的长密码时,身份验证流程会错误地校验连接,从而触发绕过。

如果系统运行的是未启用 PAM 支持编译的标准 openssh-server 软件包,或使用 openssh-server-pam 且禁用了 UsePAM 配置选项,则该系统被视为受影响。此外,只要启用了 PasswordAuthentication(OpenSSH 的默认设置),就存在风险。对于那些保留无密码账号的用户而言尤其危险,例如某些配置下的 root 用户、创建时未设置密码的仅限密钥用户,或通过目录服务管理的账号。 3.18.11 到 3.24.3 之间发布的官方 tiny-cloud 镜像也被列为潜在目标。

问题的技术根源在于:在没有 PAM 的情况下,系统处理密码哈希的方式不正确。当账号没有密码时,系统会尝试把登录尝试与空字段进行比较。由于用于密码哈希的 C 库函数存在行为差异,超过特定长度的输入会触发错误,并返回一个与无密码账号使用的占位符相匹配的字符串,进而导致身份验证绕过成功。 OpenSSH 项目已在 10.6p2 版本中修复该问题,Alpine Linux 也已将必要补丁反向移植到所有受支持版本,并修补了追溯到 3.16 的更旧、不再维护的版本。

为修复该漏洞,管理员应立即通过软件包管理器更新系统,并重启 sshd 服务,确保更新后的守护进程生效。若暂时无法立刻更新,最有效的缓解措施是彻底禁用密码身份验证:在 sshd 配置中将 PasswordAuthentication 设置为 no,然后重启服务。同时建议用户检查系统日志,寻找任何未经授权登录的迹象,重点关注本应仅支持密钥登录的账号是否出现了"密码验证通过 / 接受"的记录。

此外,负责管理云实例或容器化环境的用户需要特别注意自身配置。只要容器不运行 sshd 就相对安全;但对于尚未更新的云镜像,只要其中存在带哈希密码的账号,就应将其视为可能已受影响,因为这为攻击者利用该绕过提供了必要条件。通过应用补丁并核对配置项,用户可以有效关闭这一安全缺口,防止基础设施遭受潜在的未经授权访问。

2 comments • Comments Link

• musl C 库里的 `crypt()` 函数在密钥超过 256 字节时会返回一个星号(``)作为错误指示符。这造成了关键的安全漏洞,因为 `` 也是用于禁用密码的标准标记。两者的重叠使得长密码能够匹配被禁用账户的哈希值,从而绕过身份验证。

• musl 选择返回标记值而不是 `NULL`,这看起来像是为了避免遗留应用程序崩溃而做出的设计取舍——这类程序常常无法检查返回指针。结果是,向后兼容性和应用稳定性被置于 POSIX 合规性与 API 正确性之上。

• 这种行为之所以值得关注,是因为它偏离了 POSIX 标准:标准要求 `crypt()` 在失败时返回 `NULL` 指针并设置 `errno` 。虽然 musl 通常因严格遵循规范而备受称赞,但这一案例凸显了某种务实却危险的妥协:为缓解生态里其他地方糟糕的编程实践而背离既定标准。

• 现代语言设计,尤其是 Rust,通过 `Result<T, E>` 类型和 `#[must_use]` 属性,从机制上不鼓励用 `*` 这类标记值来处理错误。通过迫使开发者明确应对潜在失败,这些语言让忽略错误或引入含糊的基于标记的逻辑变得异常困难。

• 批评者认为,C 语言在富有表现力、类型安全的错误处理方面的不足是一种"陈旧"的限制,因此此类逻辑漏洞几乎不可避免。他们建议行业加速向内存安全、更高级的语言迁移,以消除这类结构性错误。

• C 语言及现状的支持者则认为,这本质上是一个逻辑漏洞,而不是内存安全问题。他们断言,不论使用什么语言(包括 Rust),开发者都可能编写出糟糕或危险的代码。并且,如果确实需要保留向后兼容性,那么在更安全的语言里同样可以返回一个有问题的字符串。

• 在现代安全需求下,越来越多人质疑使用带有"80 年代气息"的 API:因为标准的 `crypt(3)` 函数依赖陈旧且已被破坏的哈希算法。一些人认为,把遗留的 C 接口用于敏感的安全场景,归根结底是疏忽大意。

• 也有人指出,拒绝放弃 C 语言,往往源于文化上的抵触和对既有模式的偏好。他们同时强调,大型系统软件的变革极其缓慢,并常常遭到那些深陷传统工作流程的人强烈抵制。

• 由于 Alpine Linux 广泛使用 `musl`,该漏洞对 Docker 生态系统带来影响的可能性很高。虽然很多人认为 SSH 不应在容器中暴露,但这种配置的普遍存在使其成为真正的运维风险。

• 关于"规范"究竟由官方文档决定,还是由最广泛使用的实现来决定,这是一个哲学层面的争论。有观点认为,即使是严格符合标准的项目,最终也会选择与主导实现模式相一致的行为,以确保互操作性。

讨论的核心在于:遗留 API 的设计与安全关键逻辑之间存在危险交叉。尽管 musl 中的这类特定漏洞源于一种看似深思熟虑但仍然有缺陷的尝试——试图避免编写糟糕的软件导致崩溃——它却成为了关于语言安全与架构规范更广泛辩论的引爆点。至于此类失败应由语言本身承担责任(尤其是 C 语言缺乏类型安全的错误处理),还是应由那些把向后兼容性和便利性置于稳健错误检查之上的开发者文化承担责任,双方观点都很明确但难以调和。最终,这场争论也反映出一种日益增长、且愈发两极分化的不耐情绪:人们不再愿意在现代、对安全要求极高的基础设施中继续依赖遗留的 C 接口。