Alpine LinuxでDockerコンテナを運用していて、SSHは鍵認証だけを許可し、パスワード欄は使わない印の「*」にしてある。そう設定していれば、パスワードを知らない相手はログインできない。はずだった。OpenSSHは2026年11月5日公開の10.6p2で、この前提が崩れる条件があったと明らかにし、修正した。256バイトを境にした、ある長さのパスワードを送ると、パスワード欄が「*」のアカウントにもログインが通ってしまう経路があったという。何が起きていて、どういう条件で、どう直ったのかを順に追う。
「*」アカウントに通ったログイン
Alpine Linux公式のセキュリティアドバイザリは、この問題をこう説明している。sshdには、ハッシュ用の「salt(ソルト)」を別アカウントから借りてしまう処理がある。この処理のせいで、長いパスワードを送ると、パスワード欄が「*」のアカウント(鍵認証専用のユーザーなど)にも認証が通ってしまう。攻撃者はパスワードを知らなくても、1回の接続でログインできる。
発見者のÖzgün Kültekin氏は自身の技術公開ページで、再現条件を示している。257〜1,024バイトの範囲で、中身を問わない任意の文字列を送るとこの現象が再現するという。普段使うパスワードよりずっと長い、半角で300文字前後の文字列を送るだけで、本来は拒否されるはずのログインが通る。
OpenSSHの開発チームはこれを認めた。公式リリースノートには「PAMサポートを無効にしてビルド・実行された一部のLinuxシステムにおけるパスワード認証バイパスを回避する」とある。この修正を10.6p2に含めたと記している。Alpine Linuxも同日、各バージョン系列向けの修正パッケージを公開している。
なお、国内の一部報道はこの問題に「CVE-2026-123158」という番号を充てて紹介している。だがOpenSSHの公式リリースノートにもAlpine公式のアドバイザリにも、この番号の記載はない。NVDの該当ページを確認しても詳細は表示されなかった。Alpine公式は「執筆時点でCVE識別子は未割り当て」と明言している。番号そのものより、現象と修正バージョンを基準に読み進めたほうが確実だ。
では、パスワードの中身を1文字も比較しないまま、なぜログインが通ってしまうのか。
「*」と「*」が一致してしまう仕組み
答えは、sshdが実際に比較している値が、入力したパスワードではなく別の記号だったという点にある。発見者の解説と、musl libc・OpenSSHそれぞれの公開情報をたどると、次の4つの設計判断が順につながっていた。
4つの設計判断が順につながった
- パスワード欄の「*」は、そのアカウントがパスワードではログインできないという印になる。鍵認証専用のユーザーや、LDAPで管理しているユーザーに使われる
- sshdは本来、入力されたパスワードを
crypt()という関数でハッシュ化し、その結果を保存されている値と文字列として比較する。「*」が保存値なら、どんなパスワードをハッシュ化してもまず一致しない - ところがmusl libc(Alpine Linuxなどが使うCライブラリ)の
crypt()には、SHA-512方式で256バイトを超えるパスワードを渡すと処理に失敗するという制限がある。失敗したとき、musl libcは2012年の変更以降、NULLではなく文字列"*"を返す。本来呼び出し側がクラッシュしないための配慮だった - 2016年、OpenSSHは「存在しないユーザー名を応答時間の差で当てられる」問題(CVE-2016-6210)への対策を入れた。有効なハッシュを持たないアカウント宛てにも、他の実在アカウントのsaltを借りてダミーの
crypt()計算を行い、応答時間を揃える処理だ。この対策は、パスワード欄が「*」の実在アカウントにも適用される
257バイトを境に何が起きるか
257バイト以上のパスワードを「*」のアカウントに送ると、4の処理でmuslのcrypt()が呼ばれ、3の上限に引っかかって失敗し、"*"を返す。sshdが比較するのは、保存値の「*」と、crypt()が返した「*」になる。比較の両側がどちらも同じ記号になれば、sshdにはパスワードの中身を見分ける手がかりがない。
パスワードの長さという、本来は無関係なはずの条件が、2つの独立した設計判断の組み合わせを抜け穴に変えていた。自分はこの説明を読んで、「*同士が一致する」という一文の意味が分かるまで2回読み返した。2016年の対策は当時それ単体で正しく、muslのエラー処理も単体では妥当な配慮だ。10年後に別のライブラリと組み合わさって抜け穴になるとは、どちらの変更時点でも想定しづらい。
この仕組みが分かったところで、自分の環境がこの条件に当てはまるかどうかが気になる。
自分の環境は対象か
Alpine公式アドバイザリは、影響を受ける条件を次のように挙げている。次のすべてに当てはまる環境だけが対象になる。
- sshdが、PAMを使わずにビルド・実行されている(Alpine Linuxの
openssh-serverは既定でこの状態) PasswordAuthenticationが有効になっている(OpenSSHの既定)- パスワード欄が「*」のアカウントが存在する(鍵認証専用のユーザー、LDAPユーザー、Alpineのrootなど)
$5$または$6$形式のパスワードハッシュを持つ、実在するローカルアカウントが他に1つ以上ある
この条件が示すとおり、影響はmusl libcを使うLinuxに限られる。代表例はAlpine Linuxで、発見者はOpenWrt・Buildroot・Yoctoでも同様の構成があり得ると説明している。Debian・Ubuntu・Fedoraなどglibcを使うディストリビューションや、PAM経由でログインする環境は対象外になる。自宅サーバーやVPSの大半を占めるこれらの環境であれば、今回の問題そのものは当てはまらない。
rootアカウントへのパスワードログインは、OpenSSHの既定で禁止されている。直接rootを乗っ取られるにはPermitRootLogin yesなどの設定も必要だ。ただしAlpine公式の構築済みクラウドイメージには注意点がある。既定のalpineユーザーはパスワードなしでdoasを使え、root相当の権限を持つ場合があるとアドバイザリは述べている。
対象になる条件が分かったら、次にすべきことは何か。
今すぐすべきこと
- Alpine Linuxであれば
apk upgrade -U -aでパッケージを更新し、rc-service sshd restartでsshdを再起動する。パッケージを更新しただけでは、動作中のsshdプロセスには反映されない - すぐに更新できない場合は、
/etc/ssh/sshd_config.d/にPasswordAuthentication noを設定したファイルを置き、sshdを再起動する。実施前に、鍵認証でのログインが問題なく動くことを確認しておく - OpenWrt・Buildroot・Yoctoなど他のmusl採用環境を使っている場合は、各プロジェクトが配布するOpenSSHパッケージが10.6p2相当に更新されているかを確認する
Alpine公式アドバイザリには、修正済みパッケージのバージョンがリリース系列ごとに示されている。
| Alpineのバージョン系列 | 修正済みのopenssh-server |
|---|---|
| edge | 10.6_p2-r0 |
| 3.24 | 10.3_p1-r2 |
| 3.23 | 10.2_p1-r1 |
| 3.22 | 10.0_p1-r11 |
| 3.21 | 9.9_p2-r1 |
| 3.20 | 9.7_p1-r6 |
| 3.19 | 9.6_p1-r3 |
| 3.18 | 9.3_p2-r4 |
| 3.17 | 9.1_p1-r7 |
| 3.16 | 9.0_p1-r6 |
表の行が示すとおり、サポートが終了した古い系列(3.16〜3.20)にも修正パッケージが用意されている。apk upgradeで入るopenssh-serverのバージョンが、使っている系列の行以上になっているかを確認すれば、更新できたかどうかが分かる。
まとめ
OpenSSHは10.6p2で、musl libcを使いPAMを無効にしたLinux(Alpine Linuxなど)で起きていた認証すり抜けを修正した。原因は2つあった。1つは、2016年のなりすまし対策が「*」のアカウントにもcrypt()計算を強制すること。もう1つは、muslのcrypt()が256バイトを超える入力で"*"を返して失敗することだ。この2つが重なり、比較の両側が同じ記号になっていた。Debian・Ubuntu・Fedoraなどglibcを使う環境やPAM経由のログインは対象外になる。Alpineを使っている場合は、パッケージの更新とsshdの再起動で塞げる。
コメント
気づきや感想をどうぞ記事への補足や、読んで考えたことをお寄せください。個人情報や、他の人を傷つける内容の投稿はお控えください。
投稿にはGoogleログインが必要です。
Googleでログイン投稿にはGoogleアカウントの表示名が公開されます。メールアドレスは取得・公開しません。
コメントを読み込んでいます…