Generated by Answer me with HTML 0.5.10 · 2026-11-06 17:12 · ★ Star on GitHub
sshhole — 257 個 A 就能登入的十年老洞
musl 的 "*" 與 OpenSSH 的假驗證,串成一個 SSH 登入繞過
Lead: 在 musl、無 PAM 且開啟密碼登入的 sshd 上,257 到 1024 個字元的任意密碼能登入 "*" 帳號。OpenSSH 10.6p2 已修補(CVE-2026-123158)。
攻擊鏈
每一步單看都合理。串起來就是繞過。
時間線
- 1980第一個星號Bill Joy 在 3BSD /etc/passwd 把 daemon 帳號設為 "*"
- 2012 年 8 月musl 改回 "*"crypt() 出錯不再回 NULL,改回 "*"
- 2012 年 8 月下旬加 256 bytes 上限sha512crypt 拒絕超長密碼,三週後上線
- 2016 年 7 月OpenSSH 借 salt假驗證讓不存在的帳號也耗時相同
- 2019Alpine 鎖 rootCVE-2019-5021 用 "!" 鎖死 root,keys 一併被殺
- 2022Alpine 換成 "*""!" 改成 "*" 鎖 root,keys 恢復
- 2026 年 10 月 30 日審查修 pick_salt真 bug 在其下方四行,未被修掉
- 2026 年 11 月測出漏洞agent swarms 丟出 17,600 次怪異登入
觸發條件
| 條件 | 為什麼必要 |
|---|---|
| sshd 跑在 musl | glibc 失敗回傳 NULL,不會產生 "*" |
| 不走 PAM | 有 PAM 時 "*" 帳號不會進 crypt() |
| 密碼登入開啟 | 關閉密碼登入就免疫 |
| 有 "*" 帳號 | 無密碼可比對的帳號才是受害者 |
| 另有真密碼帳號 | sshd 借它的 salt 做假驗證 |
誰安全誰中招
| 情境 | 結果 |
|---|---|
| Alpine 官方 AWS/Azure 映像 | 可能中招:預設 alpine 帳號為 "*" 且免密碼 doas |
| OpenWrt 預設 dropbear | 安全:不用 OpenSSH |
| Debian / Ubuntu / Fedora | 安全:glibc |
| OpenBSD | 安全 |
| 有 PAM 的環境 | 安全 |
修補方式
立即升級
apk upgrade openssh
升級到 OpenSSH 10.6p2 即修好。無法升級時關掉密碼登入:
echo "PasswordAuthentication no" > /etc/ssh/sshd_config.d/00-no-passwords.confrc-service sshd restartHN 討論分歧
| 面向 | 正方 | 反方 |
|---|---|---|
| 錯誤該怎麼回報 | 回 NULL 讓呼叫端 crash,問題才會浮現 | 生產環境不能為沒檢查的呼叫端崩潰,libc 只能遷就 |
| 根因是不是語言 | C 缺 Result 逼人用 sentinel,bug 不該存在 | 換哪種語言都寫得出相容性藉口,問題在 ABI 包袱 |
| 嚴重度 | 條件全是預設值,基數龐大 | 容器通常不跑 sshd,實務上極不可能 |
| 是否蓄意 | 挑 "*" 又三週後加上限,巧合太多 | 可挑的字元本來就那幾個 |
實測筆記
- Alpine 官方映像已於發現當天更新,舊版重現要先降級 OpenSSH
- "*" 帳號第一次失敗,第二次(含)超長密碼才通過
- Alpine 3.15 手動把 "!" 改成 "*" 後可重現
- Forgejo 要開密碼登入並新增真密碼帳號才觸發,預設安全