漏洞预警|ssh曝密码绕过漏洞CVE-2026-123158,输入300个a可以直接登录的那种,附漏洞排查脚本和利用poc
原创
小白哥
小白哥
小白安全成长记
2026年11月6日 11:29
河北
去阅读
SSHhole(CVE-2026-123158)漏洞分析、利用条件与排查指南
又出洞了,还能密码绕过,还是ssh,要开始口吐芬芳了。估计运维老表们这周又是加班的一周了,我也赶忙搞了一下,还好,我用的不多,哈哈哈哈哈。但是排查脚本还是得安排一下,主要还是alpine 和 openwrt,大家还是查查,给运维老表个交代吧。
一、漏洞概述
SSHhole(CVE-2026-123158)是一个影响 OpenSSH SSH 密码认证过程的安全漏洞。漏洞主要涉及使用 musl libc 的 Linux 系统,在特定认证配置下,攻击者可能通过提交特殊构造的超长密码,绕过 SSH 密码认证,登录原本不允许密码登录的账户。漏洞的核心问题是:musl libc 在处理超长密码时,crypt() 函数可能返回 *,而 OpenSSH 在特定认证逻辑中可能将该返回值与 /etc/shadow 中的密码字段进行比较,从而导致错误匹配。
▍漏洞基本信息
| 项目 | 内容 |
|---|---|
| 漏洞名称 | SSHhole |
| CVE 编号 | CVE-2026-123158 |
| 影响组件 | OpenSSH 7.3p1 至 10.6p1 |
| CVSS评分 | 8.1 |
| 关联组件 | musl libc |
| 漏洞类型 | SSH 密码认证绕过 |
| 主要影响环境 | musl libc + 未启用 PAM 的 Linux |
| 利用方式 | 特定条件下通过超长密码触发认证绕过 |
| 修复版本 | OpenSSH 10.6p2 |
| 典型影响系统 | Alpine Linux、部分 OpenWrt、Buildroot、Yocto 环境 |
二、漏洞原理
▍2.1 正常 SSH 密码认证流程
Linux 系统通常通过 /etc/shadow 保存用户密码哈希。
例如:
root:*
alpine:*
admin:$6$xxxxxxxx$xxxxxxxxxxxxxxxx
其中:
root:*:表示该账户没有可用的常规 Unix 密码认证凭据。alpine:*:同样属于密码字段为*的账户。admin:$6$...:表示该账户使用 SHA-512 格式的密码哈希。
在未启用 PAM 的特定 OpenSSH 认证路径中,OpenSSH 会调用系统的 crypt() 函数处理用户输入的密码,并将结果与账户密码哈希进行比较。
▍2.2 漏洞产生的原因
问题出现在 musl libc 对超长密码的处理过程中。
当攻击者提交超过特定长度限制的密码时,crypt() 可能返回特殊值 *,而不是正常的密码哈希。
如果目标账户的 /etc/shadow 密码字段也为 *,就可能出现错误匹配。
| 正常情况 | 异常情况 |
|---|---|
| 用户输入密码 | 用户提交超长密码 |
| crypt() 生成密码哈希 | crypt() 返回 * |
| 比较密码哈希 | 比较特殊返回值 |
| 密码不匹配则认证失败 | 可能错误匹配 * |
| 正常认证 | 可能绕过认证 |
三、漏洞利用的条件
SSHhole 并不是所有 Linux 系统都能利用,需要同时满足以下五个条件。
▍3.1 必要的条件
| 序号 | 条件 | 具体要求 | 排查重点 |
|---|---|---|---|
| 1 | musl libc | SSH 服务运行在 musl libc 环境 | 检查 sshd 动态链接库 |
| 2 | PAM 未启用 | SSH 使用非 PAM 密码认证路径 | 检查 UsePAM 和编译配置 |
| 3 | 开启密码认证 | SSH 允许密码认证 | PasswordAuthentication yes |
| 4 | 存在目标账户 | /etc/shadow 密码字段为 * |
检查 shadow |
| 5 | 存在 Donor Hash | 存在有效的 $5$ 或 $6$ 密码哈希账户 |
检查 shadow |
▍3.2 Donor Hash 是什么?(新知识点出现了,跟着我学更多新知识,哈哈哈哈哈)
Donor Hash 可以理解为提供有效密码哈希信息的账户。
在这个漏洞的认证逻辑中,目标账户密码字段为 *,而另一个具有有效 $5$ 或 $6$ 哈希的账户可能成为 Donor。
例如:
root:*
alpine:*
admin:$6$xxxxxxxx$xxxxxxxxxxxxxxxx
这里:
| 账户 | 密码字段 | 作用 |
|---|---|---|
| root | * |
可能的目标账户 |
| alpine | * |
可能的目标账户 |
| admin | $6$... |
可能的 Donor 账户 |
需要注意:
- Donor 账户需要满足有效账户状态要求。
- 仅仅存在
$5$或$6$字符串,并不能直接认定满足条件。 - 账户锁定、过期、Shell 设置等也需要进一步核实。
▍3.3 哪些 Linux 系统需要重点排查?(windows 暂时不受影响)
| Linux 系统 | 排查优先级 | 原因 |
|---|---|---|
| Alpine Linux | 高 | 常见 musl libc 环境 |
| OpenWrt | 高 | 部分固件使用 musl libc |
| Buildroot | 高 | 嵌入式环境可能使用 musl |
| Yocto | 高 | 取决于系统构建配置 |
| Debian | 一般 | 默认使用 glibc |
| Ubuntu | 一般 | 默认使用 glibc |
| Fedora | 一般 | 默认使用 glibc |
注意:Debian、Ubuntu 等默认使用 glibc,并不意味着所有特殊构建环境都可以直接排除。并不是直接利用成功后就直接root权限了,取决于你用的哪个权限账号。
四、漏洞排查脚本(有必要安排一下)
下面提供一个 Shell 脚本,用于检查 Linux 系统是否满足 SSHhole 的五项条件。脚本采用只读检查,不会尝试漏洞利用,也不会修改系统配置。
▍4.1 检查的内容包括:
| 检查项目 | 检查方式 |
|---|---|
| 操作系统 | /etc/os-release |
| SSH 服务 | 查找 sshd |
| libc 类型 | ldd 检查 |
| PAM 状态 | sshd -T |
| 密码认证 | sshd -T |
| Root 登录策略 | sshd -T |
| 目标账户 | 检查 /etc/shadow |
| Donor Hash | 检查 $5$、$6$ |
▍4.2 完整脚本
保存为 sshhole_check.sh:
#!/bin/sh
# SSHhole CVE-2026-123158
# Read-only security detection script
echo \"==========================================\"
echo \" SSHhole Vulnerability Detection\"
echo \" CVE-2026-123158\"
echo \"==========================================\"
# 1. Operating System
echo
echo \"[1] Operating System\"
if [ -f /etc/os-release ]; then
grep -E '^(NAME|ID|VERSION_ID)=' /etc/os-release
fi
# 2. Find sshd
echo
echo \"[2] SSHD Binary\"
SSHD=$(command -v sshd 2>/dev/null)
if [ -z \"$SSHD\" ]; then
for f in /usr/sbin/sshd /sbin/sshd; do
if [ -x \"$f\" ]; then
SSHD=\"$f\"
break
fi
done
fi
if [ -z \"$SSHD\" ]; then
echo \"[INFO] sshd not found\"
exit 0
fi
echo \"SSHD: $SSHD\"
# 3. Check libc
echo
echo \"[3] libc Detection\"
LIBC_INFO=$(ldd \"$SSHD\" 2>&1)
if echo \"$LIBC_INFO\" | grep -qi 'musl'; then
echo \"[RISK] musl libc detected\"
MUSL=1
else
echo \"[INFO] musl libc not detected\"
MUSL=0
fi
echo \"$LIBC_INFO\" | grep -Ei 'musl|libc\\.so' | head -5
# 4. Effective SSH configuration
echo
echo \"[4] SSHD Configuration\"
SSHD_CONFIG=$(\"$SSHD\" -T 2>/dev/null)
if [ -z \"$SSHD_CONFIG\" ]; then
echo \"[WARN] Cannot read effective SSHD configuration\"
exit 1
fi
USEPAM=$(echo \"$SSHD_CONFIG\" |
awk '$1==\"usepam\"{print $2; exit}')
PASSWORD=$(echo \"$SSHD_CONFIG\" |
awk '$1==\"passwordauthentication\"{print $2; exit}')
ROOTLOGIN=$(echo \"$SSHD_CONFIG\" |
awk '$1==\"permitrootlogin\"{print $2; exit}')
echo \"UsePAM: ${USEPAM:-unknown}\"
echo \"PasswordAuthentication: ${PASSWORD:-unknown}\"
echo \"PermitRootLogin: ${ROOTLOGIN:-unknown}\"
if [ \"$USEPAM\" = \"no\" ] || [ -z \"$USEPAM\" ]; then
echo \"[RISK] PAM disabled or unavailable\"
PAM_OFF=1
else
echo \"[INFO] PAM enabled\"
PAM_OFF=0
fi
if [ \"$PASSWORD\" = \"yes\" ]; then
echo \"[RISK] Password authentication enabled\"
PASS_ON=1
else
echo \"[INFO] Password authentication disabled\"
PASS_ON=0
fi
# 5. Account inspection
echo
echo \"[5] Account Inspection\"
if [ \"$(id -u)\" -ne 0 ]; then
echo \"[WARN] Please run as root\"
exit 1
fi
if [ ! -r /etc/shadow ]; then
echo \"[WARN] Cannot read /etc/shadow\"
exit 1
fi
TARGETS=\"\"
DONORS=\"\"
while IFS=: read -r user hash rest; do
shell=$(awk -F: -v u=\"$user\" \\
'$1==u {print $7; exit}' /etc/passwd)
case \"$shell\" in
*/nologin|*/false|\"\")
continue
;;
esac
case \"$hash\" in
'*')
TARGETS=\"${TARGETS}${user} \"
;;
\\$5\\$*|\\$6\\$*)
DONORS=\"${DONORS}${user} \"
;;
esac
done < /etc/shadow
if [ -n \"$TARGETS\" ]; then
echo \"[RISK] Potential target accounts: $TARGETS\"
TARGET_FOUND=1
else
echo \"[INFO] No target accounts found\"
TARGET_FOUND=0
fi
if [ -n \"$DONORS\" ]; then
echo \"[RISK] Potential donor accounts: $DONORS\"
DONOR_FOUND=1
else
echo \"[INFO] No donor accounts found\"
DONOR_FOUND=0
fi
# 6. Root login policy
echo
echo \"[6] Root SSH Policy\"
case \"$ROOTLOGIN\" in
yes)
echo \"[WARN] Root SSH login is permitted\"
;;
prohibit-password|forced-commands-only|no)
echo \"[INFO] Root password login restricted\"
;;
*)
echo \"[WARN] Unknown root login policy\"
;;
esac
# 7. Final assessment
echo
echo \"==========================================\"
echo \" Final Assessment\"
echo \"==========================================\"
if [ \"$MUSL\" -eq 1 ] &&
[ \"$PAM_OFF\" -eq 1 ] &&
[ \"$PASS_ON\" -eq 1 ] &&
[ \"$TARGET_FOUND\" -eq 1 ] &&
[ \"$DONOR_FOUND\" -eq 1 ]; then
echo \"[CRITICAL] ALL FIVE CONDITIONS MATCH\"
echo \"Potentially vulnerable to SSHhole!\"
else
echo \"[INFO] Five-condition match not established\"
echo \"musl=$MUSL\"
echo \"pam_disabled=$PAM_OFF\"
echo \"password_auth=$PASS_ON\"
echo \"target_account=$TARGET_FOUND\"
echo \"donor_account=$DONOR_FOUND\"
fi
echo
echo \"[NOTE] Configuration-based assessment only.\"
echo \"Verify patches, account status and running binary.\"
echo \"==========================================\"
▍4.3 脚本用法
chmod +x sshhole_check.sh
sudo ./sshhole_check.sh
Alpine Linux 也可以直接执行:
sh sshhole_check.sh
▍4.4 脚本的检查结果说明
| 检查结果 | 含义 |
|---|---|
musl=0 |
未发现 musl 环境 |
pam_disabled=0 |
PAM 已启用 |
password_auth=0 |
未开启密码认证 |
target_account=0 |
未发现符合条件的目标账户 |
donor_account=0 |
未发现符合条件的 Donor 账户 |
五项均为 1 |
高度疑似满足漏洞条件 |
注意啊: 该脚本属于初步配置检查,不等于漏洞利用验证。不等于漏洞利用验证。
五、入侵排查
如果服务器已经满足 SSHhole 的利用条件,还需要进一步判断是否曾经被利用。
最值得关注的现象是:
密码字段为 * 的账户,却出现了 SSH 密码认证成功的日志。
▍5.1 检查 SSH 登录日志
Alpine Linux:
grep \"Accepted password\" /var/log/messages
Debian / Ubuntu:
grep \"Accepted password\" /var/log/auth.log
使用 systemd 的系统:
journalctl -u sshd --since \"7 days ago\"
重点关注以下日志:
Accepted password for alpine from 192.0.2.100 port 12345 ssh2
▍5.2 检查异常账户
例如:
grep '^alpine:' /etc/shadow
如果返回:
alpine:*:20125:0:99999:7:::
同时 SSH 日志中出现:
Accepted password for alpine
则属于高度可疑行为,需要进一步排查确认。
▍5.3 检查异常权限提升
检查是否存在异常用户:
awk -F: '$3 >= 1000 {print $1,$3,$7}' /etc/passwd
检查 doas 配置:
cat /etc/doas.conf
检查 SSH 公钥是否被植入:
find /root /home -name authorized_keys -type f -ls
检查近期修改的系统文件:
find /etc /root /home -type f -mtime -7 -ls
▍5.4 入侵排查的重点
| 排查方向 | 重点检查内容 |
|---|---|
| SSH 登录 | 异常来源 IP、登录时间、账户 |
| 账户安全 | 新增用户、异常修改密码 |
| 权限提升 | sudo、doas、异常特权操作 |
| SSH 持久化 | authorized\_keys、sshd\_config |
| 系统持久化 | crontab、启动脚本、服务 |
| 命令执行 | Shell 历史、系统审计日志 |
| 网络活动 | 异常外联、反向连接、监听端口 |
注意:Accepted password 本身不能单独证明 SSHhole 被利用,还需要结合账户密码字段、认证配置、登录来源和补丁状态进行关联分析。
六、漏洞修复建议
▍6.1 升级 OpenSSH
推荐优先升级到包含修复补丁的版本。
OpenSSH 官方修复版本:
OpenSSH 10.6p2
Alpine Linux 可以使用:
apk update
apk upgrade -U -a
升级后重启 SSH:
rc-service sshd restart
需要注意,发行版可能通过补丁回移修复漏洞,因此不应只根据版本号判断是否安全,应以发行版安全公告和软件包修复状态为准。
▍6.2 临时关闭密码认证
如果暂时无法升级,可以关闭 SSH 密码认证。
编辑配置文件:
vi /etc/ssh/sshd_config
设置:
PasswordAuthentication no
检查配置:
sshd -t
重启服务:
rc-service sshd restart
执行之前应确保 SSH 公钥认证正常,避免远程管理连接中断。
最后给搞安全的兄弟安排的一些资料,请大家自觉遵守网络安全法
漏洞验证的poc:
- https://github.com/predkambrij/sshhole-repro
漏洞作者的分析:
- https://sshhole.com/
ssh官方修复说明:
* https://github.com/openssh/openssh-portable/commit/4353fdc43ef646c43a8dda7025cc1a898caf1482
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。











评论