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 就相对安全;但对于尚未更新的云镜像,只要其中存在带哈希密码的账号,就应将其视为可能已受影响,因为这为攻击者利用该绕过提供了必要条件。通过应用补丁并核对配置项,用户可以有效关闭这一安全缺口,防止基础设施遭受潜在的未经授权访问。
Alpine Linux has issued a critical security advisory regarding a password authentication bypass vulnerability affecting systems running the openssh-server package. This flaw allows an attacker with network access to the SSH port to log into an account without knowing the password, provided certain conditions are met. Specifically, the vulnerability requires the target account to have its password field set to an asterisk, which is typical for key-only accounts, and necessitates that the machine contains at least one other account protected by a SHA-256 or SHA-512 password hash. When a specially crafted, long password is sent by the attacker, the authentication process incorrectly validates the connection.
Systems are considered affected if they run the standard openssh-server package, which is compiled without PAM support, or if they use openssh-server-pam with the UsePAM configuration option disabled. Furthermore, the risk applies if PasswordAuthentication is enabled, which is the default setting for OpenSSH. Users are particularly vulnerable if they maintain accounts with no password, such as the root user in certain configurations, key-only users created without passwords, or accounts managed through directory services. Official tiny-cloud images released between versions 3.18.11 and 3.24.3 are also flagged as potential targets.
The technical root of the issue lies in how the system handles password hashing when PAM is absent. When an account lacks a password, the system attempts to compare the login attempt against a null field. Due to a behavioral quirk in the C library function used for password hashing, input exceeding a specific length causes an error that returns a string matching the placeholder used for passwordless accounts. This leads to a successful authentication bypass. The OpenSSH project has addressed this in version 10.6p2, and Alpine Linux has backported the necessary patches to all supported releases, as well as older, end-of-life versions dating back to 3.16.
To remediate this vulnerability, administrators should immediately update their systems using the package manager and restart the sshd service to ensure the updated daemon takes effect. For environments where an immediate update is not feasible, the most effective mitigation is to disable password authentication entirely by setting PasswordAuthentication no in the sshd configuration and restarting the service. Users are also advised to check their system logs for any signs of unauthorized logins, specifically looking for accepted password attempts on accounts that are intended to be key-only.
Finally, those managing cloud instances or containerized environments should take note of their specific configurations. While containers that do not run sshd remain safe, cloud images that are not yet updated should be treated as potentially compromised if they contain any account with a hashed password, as this provides the necessary prerequisite for an attacker to exploit the bypass. By applying the patches and verifying configuration settings, users can effectively close this security hole and protect their infrastructure from potential unauthorized access.
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 接口。 • The `crypt()` function in the musl C library returns an asterisk (``) as an error indicator when a key exceeds 256 bytes, which creates a critical security flaw because `` is also the standard sentinel used for disabled passwords. This overlap allows a long password to match the hash of a disabled account, effectively bypassing authentication.
• Musl's decision to return a sentinel value rather than `NULL` appears to be a design choice intended to prevent crashes in legacy applications that fail to check return pointers, effectively prioritizing backward compatibility and application stability over POSIX compliance and API correctness.
• This behavior is notable because it deviates from the POSIX standard, which mandates that `crypt()` should return a `NULL` pointer and set `errno` upon failure. While musl is generally lauded for its strict adherence to specifications, this instance highlights a pragmatic, albeit dangerous, departure from established standards to mitigate poor programming practices elsewhere in the ecosystem.
• Modern language design, particularly in Rust, fundamentally discourages the use of sentinel values like `*` for error handling by utilizing `Result<T, E>` types and `#[must_use]` attributes. By forcing developers to explicitly handle potential failures, these languages make it significantly more difficult to ignore errors or introduce ambiguous sentinel-based logic.
• Critics argue that C's lack of expressive, type-safe error handling is a "crusty" limitation that makes such logic bugs inevitable, suggesting that the industry should accelerate its transition to memory-safe, higher-level languages to eliminate entire categories of structural errors.
• Proponents of C and the status quo argue that this is fundamentally a logic bug rather than a memory-safety issue, asserting that developers can write poor or dangerous code in any language, including Rust. They contend that if a developer feels compelled to maintain backward compatibility, they could just as easily return a problematic string in a safer language.
• The reliance on an `80s-era API for modern security needs is widely questioned, as the standard `crypt(3)` function is based on antiquated, broken hashing algorithms. Using legacy C interfaces for sensitive security operations is described by some as inherently negligent.
• Some observers suggest that the reluctance to move away from C is driven by cultural resistance and a preference for established patterns, noting that change in large-scale systems software is notoriously slow and often resisted by those entrenched in traditional workflows.
• The potential for this bug to impact the Docker ecosystem is significant due to the widespread use of Alpine Linux, which relies on musl. While many argue that SSH should not be exposed in containers, the prevalence of this configuration makes it a genuine operational risk.
• There is a philosophical debate regarding whether the "spec" is determined by official documentation or by the most widely used implementation, with some noting that even standards-compliant projects eventually adopt behaviors that mirror existing, dominant implementation patterns to ensure interoperability.
The discussion centers on the dangerous intersection of legacy API design and security-critical logic. While the specific vulnerability in musl stems from a deliberate, albeit flawed, attempt to prevent crashes in poorly written software, it serves as a focal point for a broader debate over language safety and architectural hygiene. There is clear disagreement on whether the responsibility for such failures lies with the language itself—specifically the lack of type-safe error handling in C—or with the culture of developers who prioritize backward compatibility and convenience over robust error checking. Ultimately, the thread reflects a growing, if polarized, impatience with the continued reliance on legacy C interfaces for modern security-sensitive infrastructure.