SSHole:OpenSSH 在 musl Linux 上存在密码认证绕过漏洞,可导致未授权登录
SSHole:OpenSSH 在 musl Linux 上存在密码认证绕过漏洞,可导致未授权登录
漏洞类型: SSH 身份认证绕过
影响组件: OpenSSH、musl libc
主要影响系统: Alpine Linux、OpenWrt、Buildroot、Yocto 等基于 musl 的 Linux 系统
核心问题: 特定配置下,原本禁止密码登录的 SSH 账户,可能接受任意超长密码,导致攻击者绕过身份认证。
1. 项目概述
SSHole 是一个用于展示和解释 OpenSSH 在 musl Linux 环境中存在的身份认证绕过问题的安全研究项目。
该问题与 musl libc 的 crypt() 函数处理异常密码的方式有关。由于 OpenSSH 在特定情况下未能正确处理 crypt() 的返回值,导致原本被锁定的账户可能通过超长密码完成认证。
该问题的特殊之处在于:
- 受影响账户原本不应该允许密码登录。
- 攻击者不需要知道账户的真实密码。
- 使用超过 256 字节的密码可能触发认证绕过。
- 在特定 Alpine Linux 云镜像中,甚至可能进一步获得 root 权限。
2. 漏洞产生原因
漏洞与 Unix 密码认证机制以及 musl libc 的历史实现有关。
2.1 Unix 锁定账户机制
在 Linux 系统中,用户密码通常保存在 /etc/shadow 文件中。
如果账户密码字段设置为 *,表示该账户无法通过常规密码认证。
例如:
root:*
正常情况下,* 并不是有效的密码哈希,因此无论输入什么密码,都不应该通过认证。
2.2 musl libc 的异常处理方式
问题出现在 musl libc 的 crypt() 函数。
当密码哈希计算失败时,传统实现通常返回 NULL。
但 musl 为避免部分程序因处理 NULL 而崩溃,将失败结果调整为一个特殊字符:
*
与此同时,musl 对 SHA-512 密码哈希计算设置了 256 字节的长度限制。
当输入密码超过该限制时,哈希计算失败,并返回 *。
这就导致一个严重问题:
- 用户账户的密码字段为
*。 - 输入超长密码。
- crypt()计算失败并返回 *。
- 返回值与账户中存储的密码字段相同。
- 在受影响的认证流程中,密码比较结果被判定为匹配。
最终,原本应该被锁定的账户可能通过密码认证。
3. 漏洞攻击原理
整个问题涉及 musl libc、OpenSSH 和账户密码字段之间的交互。
攻击流程如下:
攻击者连接 SSH 服务
|
v
选择一个被锁定的用户账户
|
v
提交超过 256 字节的密码
|
v
OpenSSH 调用 musl 的 crypt()
|
v
密码长度超过 SHA-512 crypt 限制
|
v
crypt() 返回特殊字符 "*"
|
v
与账户存储的 "*" 进行比较
|
v
认证结果错误地匹配
|
v
绕过 SSH 密码认证
这不是所有 OpenSSH 或 Linux 系统都存在的问题,而是特定 libc、PAM 配置及账户条件共同作用的结果。
4. 影响范围与受影响条件
根据项目作者的测试结果,漏洞并非只要安装 OpenSSH 就会受到影响,需要同时满足以下条件:
| 检查条件 | 具体要求 |
|---|---|
| 操作系统 | Linux |
| C 标准库 | musl libc |
| SSH 服务 | OpenSSH sshd |
| PAM | 未启用 PAM |
| 密码认证 | PasswordAuthentication yes |
| 用户账户 | 存在密码字段为 * 的锁定账户 |
| 其他条件 | 系统中还存在使用有效密码哈希的其他账户 |
在满足这些条件时,攻击者可以使用 257~1024 字节的超长密码尝试登录被锁定的账户。
主要受影响系统
- Alpine Linux:重点关注,默认 OpenSSH 配置可能符合漏洞条件。
- OpenWrt:使用 musl libc 的相关构建环境。
- Buildroot:基于 musl libc 的嵌入式 Linux 系统。
- Yocto:采用 musl libc 且满足相关 SSH 配置的设备。
- Alpine AWS / Azure 官方镜像:项目特别指出,默认
alpine用户可能受到影响,该账户还具有免密码doas权限,存在进一步获得 root 权限的风险。
不受影响的主要环境
- Debian、Ubuntu、Fedora 等使用 glibc 的常规系统。
- 使用 PAM 进行密码认证的 Linux 系统。
- OpenBSD 等非 Linux 系统。
- 使用 Dropbear 而非 OpenSSH 的 SSH 服务。
发行版名称本身不能作为唯一判断依据,应检查实际使用的 libc、PAM 和 sshd 配置。
5. 漏洞发现过程
SSHole 项目作者 Özgün Kültekin 通过分析 OpenSSH 与底层 libc 的交互逻辑发现了这一问题。
作者对不同环境进行了对比测试,包括:
- glibc 与 musl libc。
- 启用 PAM 与禁用 PAM。
- 使用
/etc/shadow与不使用 shadow 的环境。 - 正常密码、异常密码及超长密码。
测试过程中,作者进行了约 17,600 次异常登录测试。
最终发现,只有使用 musl libc 且未启用 PAM 的特定 OpenSSH 构建环境出现了异常认证结果。
该问题实际上与多个历史实现细节有关:
- 1980 年 Unix 使用
*锁定账户。 - 2012 年 musl 修改
crypt()失败时的返回方式。 - 2012 年 musl 为 SHA-512 crypt 增加 256 字节长度限制。
- 2016 年 OpenSSH 为防止用户名枚举,引入借用其他账户盐值进行密码计算的处理逻辑。
- 2022 年 Alpine Linux 将 root 账户锁定标记调整为
*。 - 2026 年研究人员通过系统性测试发现这些历史实现之间产生了认证绕过问题。
这也是该漏洞长期未被发现的原因之一:单独看每个组件的设计似乎都合理,但组合起来却产生了安全问题。
6. 修复方案与缓解措施
对符合受影响条件的系统,应优先关闭 SSH 密码认证。
方案一:升级 OpenSSH
OpenSSH 已发布 10.6p2,其中包含针对该问题的安全缓解措施。
Alpine Linux 用户可以执行:
apk upgrade openssh
升级后重启 SSH 服务:
rc-service sshd restart
也可以按照 Alpine 官方更新方式升级相关软件包:
apk upgrade -U -a
rc-service sshd restart
仅完成软件包升级而没有重启 sshd,正在运行的旧进程仍可能继续提供存在风险的服务。
方案二:禁用 SSH 密码认证
如果暂时无法升级,建议立即关闭密码认证。
创建配置文件:
echo "PasswordAuthentication no" > \
/etc/ssh/sshd_config.d/00-no-passwords.conf
重启 SSH:
rc-service sshd restart
注意事项:
- 确保已经配置并验证 SSH 公钥登录。
- 保留当前 SSH 管理会话,避免配置错误导致无法远程连接。
- 确认配置文件被 sshd 正确加载。
- 对无法及时修复的设备,可以暂时关闭 SSH 服务或限制管理端口的访问来源。
方案三:检查系统环境
可以通过以下命令检查系统使用的 libc:
ldd --version
查看 SSH 服务配置:
sshd -T | grep -i passwordauthentication
检查 PAM 配置:
sshd -T | grep -i usepam
检查锁定账户:
grep ':\*:' /etc/shadow
7. 安全风险与排查建议
该漏洞最值得关注的地方是:攻击者不需要获取目标账户的原始密码,就可能登录原本被锁定的账户。
如果目标账户具有较高权限,风险会进一步扩大。
重点排查:
- 是否存在公网开放的 Alpine Linux SSH 服务。
- 是否使用 musl libc 且禁用了 PAM。
- 是否仍然允许 SSH 密码认证。
- 是否存在 root、仅允许密钥登录的部署账户等锁定账户。
- 是否存在异常 SSH 登录记录。
- 是否有不明来源的 root 登录、账户变更及权限提升行为。
对于已经暴露在公网且符合漏洞条件的服务器,建议在修复后进一步检查认证日志、登录来源、账户变更记录和异常命令执行情况。
8. 解决方案
8.1 官方修复方案
升级至 OpenSSH 10.6p2(2026-11-05 发布)。该版本在认证路径中新增密码哈希最短长度检查(MIN_PASSWORD_HASH_LEN 4),拒绝将 "*" 等短哈希作为有效比较结果。Alpine 等 musl 发行版可执行 apk upgrade openssh 并重启 sshd;源码部署需升级到 10.6p2 后重新编译安装。
信息来源:https://www.openssh.org/txt/release-10.6p2
8.2 临时缓解方案
无法立即升级时,在 /etc/ssh/sshd_config.d/00-no-passwords.conf 写入 "PasswordAuthentication no" 并重启 sshd(Alpine 可执行 rc-service sshd restart),关闭密码认证;同时将 PermitRootLogin 设置为 prohibit-password 或 no。注意:在未启用 PAM 的 Alpine 等 musl 系统上不要将 /etc/shadow 中的 "*" 改为 "!",否则会导致合法用户无法使用 SSH 密钥登录。若已暴露,应检查 sshd 日志中本应无密码的账户是否出现 Accepted password 记录。
9. 总结
SSHole 展示了一个非常典型的 Linux 身份认证安全问题:不同软件组件对异常返回值的处理方式不一致,可能让原本安全的账户锁定机制失效。
此次问题并不是传统意义上的密码破解,而是利用 musl libc 的 crypt() 返回值与 OpenSSH 密码比较逻辑之间的特殊情况,实现身份认证绕过。
核心安全建议:
- Alpine Linux 及其他 musl Linux 用户应立即检查 SSH 配置。
- 不需要密码登录的服务器应关闭
PasswordAuthentication。 - 尽快升级至 OpenSSH 10.6p2 或发行版提供的对应安全修复版本。
- 对公网 SSH 服务加强访问控制,并检查历史登录记录。
项目地址: https://sshhole.com/ sshhole lab: https://github.com/leonjza/sshhole-lab 其他: https://www.openssh.org/txt/release-10.6p2 https://www.openssh.org/releasenotes.html#10.6p2 https://git.musl-libc.org/cgit/musl/commit/?id=b3c4cc121f70faea45389fe7ddc1127ed5cbd8bb https://git.musl-libc.org/cgit/musl/commit/?id=88bf5a8a8d7d796f63cca8589f4de67aa8345f1a http://lists.mindrot.org/pipermail/openssh-commits/2016-July/005428.html https://gitlab.alpinelinux.org/alpine/aports/-/commit/fbe926afc76de76e07d078f266badc4144dde8e3 https://www.openwall.com/lists/musl/2024/12/31/2


评论0次