SSHole(CVE-2026-123158):密码够长,就能登进不允许密码登录的账户
原创
MessFeel
MessFeel
MessFreeSecurity
2026年11月7日 08:44
河北
去阅读
11 月 5 日,OpenSSH 披露了 CVE-2026-123158,发现者给它起名 SSHole。在用 musl libc、又没开 PAM 的系统上,sshd 收到一个 257 到 1024 字节的密码时,会放行那些本来禁止密码登录的账户,root 也可能在其中。攻击者不需要知道真实密码,连一次就能进去。
这个洞的触发条件不少,Debian、Ubuntu、RHEL 这些 glibc 发行版都不受影响。麻烦在于,这些条件和 Alpine 的默认配置刚好对得上,而 Alpine 在云主机、容器和嵌入式设备上用得很多。研究人员放在网上的 Alpine 蜜罐,披露后几个小时就被人用这个洞登了进去。
手上有 Alpine 机器、又对外开着 SSH 的,最好今天就查一遍。
SSHole 时间线
漏洞概况
| 漏洞名称 | SSHole |
| CVE 编号 | CVE-2026-123158 |
| 漏洞类型 | 密码认证绕过 |
| CVSS 3.1 | 8.1(高危) |
| 发现者 | Özgün Kültekin(Wakefield) |
| 公开时间 | 2026 年 11 月 5 日 |
| 修复版本 | OpenSSH 10.6p2(同日发布) |
| 利用情况 | 已有在野利用记录 |
问题出在哪
在 /etc/shadow 里,没设密码的账户,密码字段通常就是一个 *,表示这个账户不能用密码登录。只配了公钥的用户、不少系统上的 root,都是这个状态。
musl libc 的 crypt() 碰到超过 256 字节的输入,不会去算哈希,而是直接返回一个 * 表示出错。
OpenSSH 不走 PAM 的时候,密码由 sshd 自己校验。它把 crypt() 的返回值和 shadow 里存的字段做字符串比较,一样就算密码正确。
这三点凑在一起,问题就出来了。攻击者发一个 300 字节的密码,crypt() 返回 *,shadow 里存的也是 *,两边一比相等,sshd 就放行了。OpenSSH 在比较之前没有检查 crypt() 有没有出错,错误值就这样被当成了哈希。
无 PAM 时的密码校验路径
这条路径还依赖 2016 年加进来的一段代码。那年 OpenSSH 修了用户名枚举漏洞 CVE-2016-6210,攻击者原本可以从响应时间的差别,判断某个用户名存不存在。修复的办法是,遇到没有可用哈希的账户,就借系统里另一个真实账户的盐,照样算一遍哈希,让各种账户的耗时看起来差不多。
SSHole 走的正是这段逻辑,所以系统里至少要有一个用 $5$(SHA-256)或 $6$(SHA-512)哈希的账户,漏洞才能触发。
哪些机器受影响
下面几条要同时成立:
-
系统用的是 musl libc。最常见的是 Alpine,部分 OpenWrt、Buildroot、Yocto 构建的系统也是
-
OpenSSH 没启用 PAM。Alpine 自带的 openssh-server 默认就不带 PAM,手动写了
UsePAM no的也算 -
密码认证开着,
PasswordAuthentication默认就是 yes -
有密码字段为
*而且能登录的账户 -
系统里至少有一个账户用的是
$5$或$6$哈希
影响范围自查
有一条不成立,就不受影响。Debian、Ubuntu、RHEL、Fedora 这类 glibc 系统没事,开了 PAM 的、已经关掉密码登录只用密钥的也没事。Dropbear 和 OpenBSD 自带的 OpenSSH 同样不在范围内。
最该担心的是 Alpine 官方云镜像,还有自己装了 openssh-server 的 Alpine 容器和各种小设备。很多人选 Alpine 是图它小,sshd 装上就用,默认配置很少有人去改,偏偏默认配置就满足了全部条件。
自己查一下
下面的命令都要 root 权限。按顺序跑,哪一步对不上,后面就不用看了。
是不是 musl 系统
cat /etc/os-release ldd 2>&1 | head -1 # 输出里有 musl 就是
OpenSSH 版本和配置
ssh -V sshd -T | grep -Ei '^(usepam|passwordauthentication)' # usepam no 加上 passwordauthentication yes,就要接着查
有没有密码字段为 \* 的账户
awk -F: '$2==\"*\" {print $1}' /etc/shadow # 再对照 /etc/passwd,看这些账户的 shell 能不能登录 grep -vE '(nologin|false)$' /etc/passwd
有没有 $5$ / $6$ 哈希
grep -cE '^[^:]+:\\$(5|6)\\$' /etc/shadow # 大于 0 就满足条件
有没有被人登录过
重点看平时只用密钥登录的账户,日志里有没有出现 Accepted password。
grep 'Accepted password' /var/log/messages /var/log/auth.log 2>/dev/null
Alpine 默认把日志写在 /var/log/messages,具体以你的 syslog 配置为准。要是真查到可疑的密码登录,得按入侵来处理,光打补丁不够。
怎么修
最稳妥的是升级到 OpenSSH 10.6p2,或者装发行版的修复包。Alpine 各个分支都已经推了更新。
apk update && apk upgrade openssh rc-service sshd restart
升级完一定要重启 sshd,不然跑着的还是旧进程。
一时没法升级的,可以先在 /etc/ssh/sshd_config 里关掉密码认证。
PasswordAuthentication no
改完先用 sshd -t 检查配置,再重启 sshd。动手之前确认自己的公钥能登上去,别把自己关在门外。
修复办法
有几件事也可以一起做。SSH 端口不要直接对公网开放,用安全组或防火墙限制来源 IP;PermitRootLogin 设成 no 或 prohibit-password;自己打的 Alpine 镜像要重新构建,并替换掉线上的实例,只改基础镜像的标签是不够的。
回头看这个洞,代码里没有溢出,也没有什么复杂的利用链。musl 和 shadow 碰巧都用 *,一个表示算不出来,一个表示不许登录,OpenSSH 又没去看 crypt() 到底成没成功。三方各自的写法单独看都说得过去,放在一起就出了事。
条件这么多,真正中招的机器不会占多数。可只要条件凑齐,攻击者什么都不用猜,连一次就能进去。Alpine 机器能升级的尽快升级,暂时动不了的,先把密码认证关掉。
参考
CVE-2026-123158 / SSHole 公开披露(2026 年 11 月 5 日)
OpenSSH 10.6p2 发布说明
CVE-2016-6210(OpenSSH 用户名枚举漏洞)
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论