musl 上の OpenSSH パスワード回避、10.6p2 で修正 (CVE-2026-123158)
musl 上で PAM なしの OpenSSH はロックされたアカウントに 257 バイトのパスワードを受け付けます。10.6p2 と Alpine のパッケージで修正されました。
要点
- musl libc で PAM を無効にしてビルドした OpenSSH の sshd は、shadow のパスワード欄が
*のアカウントに 256 バイトを超える任意のパスワードを受け付けます。OpenSSH プロジェクトは 2026 年 11 月 5 日に CVE-2026-123158 を公開し、10.6p2 をリリースしました。 - Alpine Linux で sshd をパスワード認証ありで実行しているサーバーは、別のローカルアカウントに
$5$または$6$のハッシュがある場合に影響を受けます。Alpine の公式イメージは広く導入されています。sshd を実行しないコンテナは影響を受けません。 - MITRE は CVSS v3.1 8.1 High (CWE-394) と評価しています。公開ラボと 2 つの概念実証リポジトリがあり、現実の悪用は報告されておらず、2026 年 11 月 6 日時点で CISA の KEV カタログには掲載されていません。
- OpenSSH 10.6p2、または各ブランチの修正済み Alpine パッケージに更新し、sshd を再起動してください。更新できない場合は
PasswordAuthentication noを設定します。「修正方法」を参照してください。
影響を受けますか?
次のすべてに当てはまる場合にのみ影響を受けます。
- ホストが 10.6p2 より前の OpenSSH、または表の修正版より古い Alpine の openssh パッケージを実行している。
- sshd が musl で PAM を無効にしてビルドされ、実行されている。Alpine の
openssh-serverは PAM なしでビルドされています。openssh-server-pamとUsePAM yesの組み合わせは影響を受けませんが、同じパッケージでUsePAM noの場合は影響を受けます。 PasswordAuthentication yesが有効である。これは OpenSSH の既定値です。- パスワードで到達できる少なくとも 1 つのアカウントの shadow パスワード欄が
*である。Alpine では、およそ Alpine 3.16 以降のベースイメージでroot:*として提供される root、パスワードなしでadduserにより作成された鍵専用ユーザー、shadow エントリを持たないディレクトリサービスユーザー、公式 tiny-cloud イメージのalpineユーザーが該当します。 - 少なくとも 1 つのローカルアカウントに
$5$または$6$の crypt ハッシュがある。sshd がソルトを借用するために必要です。SHA-256 も SHA-512 もハッシュを持たないマシンでは、この不具合には到達しません。
root については、既定の PermitRootLogin prohibit-password がパスワードログインを引き続きブロックします。PermitRootLogin yes を設定した場合、またはログインできる別の * アカウントが root への経路を持つ場合、たとえば tiny-cloud イメージのパスワードなし doas がある場合に root へ到達できます。
sshd を実行しないコンテナは影響を受けません。! でロックされたアカウントはパスワードでも鍵でもログインできないため、標的になりません。PasswordAuthentication no のシステム、openssh-server-pam と UsePAM yes を使うシステム、$ 形式のハッシュがないシステムもこの不具合の対象外です。
| ブランチ | 影響を受けるバージョン | 修正バージョン |
|---|---|---|
| OpenSSH 本家 (musl、PAM 無効) | 10.6p1 以前 | 10.6p2 (2026 年 11 月 5 日公開) |
| Alpine edge | 10.6_p2-r0 より前 | 10.6_p2-r0 |
| Alpine 3.24 | 10.3_p1-r2 より前 | 10.3_p1-r2 (ポイントリリース 3.24.4) |
| Alpine 3.23 | 10.2_p1-r1 より前 | 10.2_p1-r1 (ポイントリリース 3.23.8) |
| Alpine 3.22 | 10.0_p1-r11 より前 | 10.0_p1-r11 (ポイントリリース 3.22.8) |
| Alpine 3.21 | 9.9_p2-r1 より前 | 9.9_p2-r1 (ポイントリリース 3.21.10) |
| Alpine 3.20 | 9.7_p1-r6 より前 | 9.7_p1-r6 |
| Alpine 3.19 | 9.6_p1-r3 より前 | 9.6_p1-r3 |
| Alpine 3.18 | 9.3_p2-r4 より前 | 9.3_p2-r4 |
| Alpine 3.17 | 9.1_p1-r7 より前 | 9.1_p1-r7 |
| Alpine 3.16 | 9.0_p1-r6 より前 | 9.0_p1-r6 |
Alpine は 3.16 から 3.24 までの各ブランチと edge に修正済みパッケージを公開しました。定期更新が終了したリリースも含まれます。修正を含む現在のポイントリリースは 3.21.10、3.22.8、3.23.8、3.24.4 の 4 つです。
ホストの状態を確認します。
# Alpine: the installed OpenSSH packages and versions
apk info -v openssh-server openssh-server-pam 2>/dev/null
# Whether this sshd uses PAM (no means the vulnerable build on Alpine)
sshd -T 2>/dev/null | grep -i '^usepam'
# Whether password authentication is on
sshd -T 2>/dev/null | grep -i '^passwordauthentication'
# Accounts whose shadow password field is exactly *
sudo awk -F: '$2=="*"{print $1}' /etc/shadow
# Whether any local account has a SHA-256 or SHA-512 hash
sudo awk -F: '$2 ~ /^\$[56]\$/{print $1}' /etc/shadow
sshd -T には root 権限と読み取り可能な設定が必要です。OpenWrt、Buildroot、Yocto など Alpine 以外の musl システムでは、ディストリビューションのパッケージマネージャーと ssh -V で OpenSSH のビルドを特定し、ベンダーの修正済みパッケージと比較してください。
修正方法
- Alpine ではパッケージを更新し、sshd を再起動します。
apk upgrade -U -a rc-service sshd restart更新だけでは実行中の sshd は再起動されないため、再起動が必要です。コンテナイメージは修正済みのベースまたはパッケージから再構築し、コンテナを再作成してください。新しいイメージを取得してもコンテナを再作成しなければ、古いプロセスが動き続けます。 - 他の musl システムでは、OpenSSH 10.6p2 またはディストリビューションの修正済みパッケージに更新します。OpenSSH 10.6p2 のリリースノートが修正を示し、Alpine のアドバイザリが各ブランチの修正済みパッケージを一覧にしています。
- 更新できない場合はパスワード認証を無効にします。現在のセッションを開いたままにし、閉じる前に鍵ログインをテストしてください。Alpine 3.19 以降では drop-in ファイルで足ります。
mkdir -p /etc/ssh/sshd_config.d echo 'PasswordAuthentication no' > /etc/ssh/sshd_config.d/00-no-passwords.conf sshd -t && rc-service sshd restart sshd -T | grep -i passwordauthenticationdrop-in ディレクトリを読まない古い Alpine では、/etc/ssh/sshd_configを直接編集して sshd を再起動します。PasswordAuthentication noは本物のハッシュを持つアカウントのパスワードログインも無効にします。それが意図したコストです。 - パスワード認証が必要で更新できない場合は、
*の対象を削除するか到達不能にします。未使用のアカウントを*ではなく!でロックするか、削除します。!は鍵によるログインも拒否するため、別の管理セッションを開いたままにしてください。これは特定のアカウント経路を閉じますが、比較そのものは修正しないため、できるだけ早く更新してください。
根本原因は何ですか?
この不具合は、どちらも * になる 2 つの文字列の比較です。一方はアカウントにパスワードがないため、もう一方は musl の crypt() がエラー値として * を返すためです。PAM なしの sshd は auth-passwd.c で保存されたパスワード欄を取り出し、入力されたパスワードをその欄でハッシュします。
char *pw_password = authctxt->valid ? shadow_pw(pw) : pw->pw_passwd;
if (pw_password == NULL)
return 0;
/* Check for users with no password. */
if (strcmp(pw_password, "") == 0 && strcmp(password, "") == 0)
return (1);
/*
* Encrypt the candidate password using the proper salt, or pass a
* NULL and let xcrypt pick one.
*/
if (authctxt->valid && pw_password[0] && pw_password[1])
salt = pw_password;
encrypted_password = xcrypt(password, salt);
/*
* Authentication is accepted if the encrypted passwords
* are identical.
*/
return encrypted_password != NULL &&
strcmp(encrypted_password, pw_password) == 0;
欄が * のアカウントでは pw_password[1] が終端の NUL なので、salt は NULL のままです。すると xcrypt() が pick_salt() を呼び、アカウントデータベースを走査して $5$ または $6$ の欄を見つけ、そのハッシュの種類とソルトを返します。
if (salt == NULL)
salt = pick_salt();
...
crypted = crypt(password, salt);
musl の SHA-512 実装は 256 バイトを超える鍵を拒否します。この上限はサービス拒否への対策で、SHA-512 crypt は鍵が長くなるほど遅くなるためです。
#define KEY_MAX 256
...
/* reject large keys */
for (i = 0; i <= KEY_MAX && key[i]; i++);
if (i > KEY_MAX)
return 0;
内部関数が 0 を返すと、musl の __crypt_sha512() は文字列 * を返します。
p = sha512crypt(key, setting, output);
...
if (!p || q != testbuf || memcmp(testbuf, testhash, sizeof testhash))
return "*";
return p;
sshd は返された * を保存された * と比較し、ログインを受け付けます。OpenSSH は入力パスワードを 1024 バイトに制限しているため、成功する範囲は 257 から 1024 バイトです。CVE レコードは 256 から 1024 と表現しています。256 バイトの鍵は musl にまだ受け付けられ、本物のハッシュを生成するため、エラー戻り値を引き起こす最短の値は 257 です。
この不具合が到達可能になったのは 2016 年です。OpenSSH が CVE-2016-6210 のタイミング攻撃修正として pick_salt() を追加したためです。それ以前は * のアカウントを固定の DES ソルト xx でハッシュしており、* は返りませんでした。
どのように悪用されますか?
- 攻撃者はパスワード認証が有効な musl システムの SSH サービスを見つけます。
- 対象にはパスワードでログインできる
*アカウントがあります。PermitRootLogin yesの root、鍵専用のデプロイユーザー、ディレクトリユーザー、または tiny-cloud イメージのalpineユーザーです。 - 別のローカルアカウントに
$5$または$6$のハッシュがあり、sshd がそのソルトを借用できます。 - 攻撃者は
*アカウントに対して 257 から 1024 バイトのパスワードを送ります。文字の内容は問いません。 - sshd は借用したソルトで長いパスワードをハッシュします。musl は
*を返し、保存された*との比較が成功して、攻撃者はそのアカウントのシェルを得ます。
sshhole.com の公開ラボではブラウザーで比較を試せます。CVE レコードには 2 つの概念実証リポジトリが掲載されています。2026 年 11 月 6 日時点で、現実の悪用は公に報告されていません。
攻撃の流れは?
パスワードのないアカウントに対する長いパスワードが musl の * エラー戻り値に到達し、保存された欄も * であるため sshd が受け付けます。
攻撃者に何ができますか?
攻撃者はパスワード認証で到達できる任意の * アカウントに、そのアカウントの権限でログインできます。影響はどのアカウントかによって変わります。
PermitRootLogin yesの Alpine の root: ホストの完全な制御。- パスワードなし
doasを持つ tiny-cloud イメージのalpineユーザー: インスタンスの root。 - 鍵専用のデプロイユーザー: そのユーザーが持つシェル、鍵、クラウド認証情報、アプリケーションへのアクセス。
- shadow エントリのないディレクトリサービスユーザー: そのユーザーへのなりすまし。
「影響を受けますか?」の条件はすべて適用されます。musl、PAM 無効、パスワード認証有効、* アカウント、別の $5$ または $6$ ハッシュ、ネットワーク到達性です。この不具合は本物のパスワードハッシュを明らかにしたり解読したりせず、! でロックされたアカウントには影響しません。SSH プロトコルを回避する意味の事前認証不具合ではなく、攻撃者はサーバーが拒否すべきパスワードで通常のパスワードログインを完了します。
修正が機能する理由
修正は保存されたハッシュに最小長を設け、1 文字の欄を比較しないようにします。
+#define MIN_PASSWORD_HASH_LEN 4
#define MAX_PASSWORD_LEN 1024
@@
- return encrypted_password != NULL &&
+ ret = encrypted_password != NULL &&
+ strlen(pw_password) >= MIN_PASSWORD_HASH_LEN &&
strcmp(encrypted_password, pw_password) == 0;
+ freezero(pw_password, strlen(pw_password));
+ return ret;
* の欄は 1 バイトで、新しい最小長 4 バイトを下回るため、musl が * を返しても比較は偽になります。本物の SHA-512 の欄は $6$、ソルト、ハッシュで 4 バイトよりはるかに長くなります。同じ変更が portable と UnixWare のパスワード経路に適用され、修正は shadow のコピーも解放します。OpenSSH プロジェクトは根本原因が musl のエラー値であるため回避策と呼んでいますが、sshd の経路は閉じます。Alpine の安定版パッケージも同じ修正を含みます。
侵害されたかどうかを確認するには?
公開された侵害指標はありません。ログインに成功すると、本来パスワードを受け付けないアカウントに Accepted password の行が残るため、そこから確認します。
# Alpine and other syslog-based systems
sudo grep -i "Accepted password" /var/log/messages
# Compare the account name with the * accounts on the host
sudo awk -F: '$2=="*"{print $1}' /etc/shadow
ヒットは手がかりであり、証明ではありません。本物のハッシュを持つアカウントも Accepted password の行を出します。送信元アドレスと時刻を自分のログインと照合してください。次に doas と sudo の使用、最近作成されたユーザー、新しい authorized_keys の項目、そのアカウントが到達できたファイルやサービスを確認します。tiny-cloud イメージでは、alpine ユーザーが身に覚えのないアドレスからログインしていないか確認します。
失敗した試行は特別な痕跡を残さず、成功した試行がログから削除されている可能性もあります。ログインを排除できない場合は、ホストを侵害されたものとして扱い、信頼できるイメージから再構築し、到達できたすべての認証情報を更新してください。
年表
- 2012-08: musl が
crypt()を変更し、ハッシュを計算できないときにNULLではなく*を返すようになる。 - 2012-08-29: musl が SHA-512 crypt の鍵を 256 バイトに制限し、長い鍵の経路が
*を返すようになる。 - 2016-07: OpenSSH が CVE-2016-6210 のタイミング修正として無効ユーザー向けの
pick_salt()を追加し、*の比較が到達可能になる。 - 2026-10-30: OpenSSH のセキュリティレビューが
pick_salt()を修正する。脆弱な比較はその 4 行下にある。 - 2026-11-05: OpenSSH 10.6p2 がリリースされ、CVE-2026-123158 が公開され、Alpine がアドバイザリと修正済みパッケージを公開する。
- 2026-11-06: 現実の悪用は公に報告されておらず、CVE は CISA の KEV カタログにない。
よくある質問
Debian、Ubuntu、Fedora は影響を受けますか?
いいえ。これらのシステムは glibc と PAM を使用しており、この回避には PAM を無効にした musl の * エラー戻り値が必要です。glibc 上の同じ OpenSSH バージョンはこの経路を通りません。
Alpine を使っていますが鍵ログインだけです。影響を受けますか?
はい。PasswordAuthentication が有効で * アカウントが存在する場合です。攻撃者は長いパスワードで * アカウントにログインするため、鍵ログインの方法は関係ありません。PasswordAuthentication no を設定するか更新してください。
root は既定で悪用できますか?
既定ではできません。Alpine は root を * の欄で提供しますが、OpenSSH の既定 PermitRootLogin prohibit-password が root のパスワードログインをブロックします。PermitRootLogin yes を設定した場合、またはパスワードなし doas を持つ alpine ユーザーのように別の * アカウントが昇格できる場合に root へ到達できます。
追跡できる CVE はありますか?
はい。CVE-2026-123158 は 2026 年 11 月 5 日に CVSS v3.1 8.1 High、CWE-394 で公開されました。OpenSSH のアドバイザリと Alpine のアドバイザリが主な修正情報源です。
現実の悪用はありましたか?
2026 年 11 月 6 日時点で公開された悪用報告はなく、CISA の SSVC 評価は公開された概念実証を記録していますが、活発な悪用は記録していません。この不具合は古いため、公開データだけでは静かなログインを排除できません。ログを確認してください。
SSH 鍵を更新する必要がありますか?
説明できないログインの証拠を見つけた場合だけです。ホストにアクセスされた場合は、到達できたすべての鍵と認証情報を露出したものとして扱い、再構築後に更新してください。ログがきれいなら、更新と sshd の再起動で十分です。
Ostorlab で公開 SSH サービスを見つける
Ostorlab の攻撃対象領域の検出は、インターネットに公開されたホストとそのサービスを一覧化します。TCP 22 番ポートで応答するマシンを洗い出し、まず OpenSSH のビルドとパスワード認証の設定を確認してください。
参考資料
- OpenSSH 10.6p2 リリースノート、2026 年 11 月 5 日、パスワード認証回避と Özgün Kültekin へのクレジット: https://www.openssh.org/releasenotes.html#10.6p2 (2026 年 11 月 6 日確認)
- OpenSSH コミット 4353fdc43ef646c43a8dda7025cc1a898caf1482、「avoid password authn bypass」、2026 年 11 月 5 日、
MIN_PASSWORD_HASH_LENのチェック: https://github.com/openssh/openssh-portable/commit/4353fdc43ef646c43a8dda7025cc1a898caf1482 (2026 年 11 月 6 日確認) - CVE-2026-123158 レコード、MITRE、2026 年 11 月 5 日公開、CVSS v3.1 8.1、CWE-394、概念実証の参照: https://www.cve.org/CVERecord?id=CVE-2026-123158 (2026 年 11 月 6 日確認)
- Alpine Linux、「OpenSSH password authentication bypass」、2026 年 11 月 5 日、影響する設定、修正済みパッケージ、回避策: https://alpinelinux.org/posts/2026-11-05-openssh-password-authentication-bypass/ (2026 年 11 月 6 日確認)
- 「sshole」、研究者の解説とブラウザーラボ、musl と OpenSSH の経緯、悪用条件: https://sshhole.com/ (2026 年 11 月 6 日確認)
- musl コミット b3c4cc12、「crypt: return "*" instead of NULL on failure」、2012 年 8 月: https://git.musl-libc.org/cgit/musl/commit/?id=b3c4cc12 (2026 年 11 月 6 日確認)
- musl コミット 88bf5a8a、SHA-512 鍵の 256 バイト上限、2012 年 8 月 29 日: https://git.musl-libc.org/cgit/musl/commit/?id=88bf5a8a (2026 年 11 月 6 日確認)
- OpenSSH の
auth-passwd.c、10.6p1 タグ、脆弱な比較: https://github.com/openssh/openssh-portable/blob/V_10_6_P1/auth-passwd.c (2026 年 11 月 6 日確認) - OpenSSH の
openbsd-compat/xcrypt.c、10.6p1 タグ、pick_salt()とxcrypt(): https://github.com/openssh/openssh-portable/blob/V_10_6_P1/openbsd-compat/xcrypt.c (2026 年 11 月 6 日確認) - Docker Hub、公式
alpineイメージ、12,476,923,091 回のプル、到達規模の指標: https://hub.docker.com/_/alpine (2026 年 11 月 6 日確認) - CISA Known Exploited Vulnerabilities カタログの JSON フィード、2026 年 11 月 6 日に CVE-2026-123158 を確認 (未掲載): https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json (2026 年 11 月 6 日確認)