パスワードを持たないアカウントが、どんなパスワードでも通す——OpenSSH「*sshole」と、1980年から続く1文字の話【2026】

インターネット・SNS

パスワードを設定していないアカウントは、本来ログインできません。それが前提です。

ところが、Alpine Linuxなどのmusl環境で動くOpenSSHのsshdには、その前提が崩れる穴がありました。パスワード欄が「*」のアカウントに、257バイト以上のパスワードを1回送るだけでログインできてしまいます。

通称は「*sshole」、CVE-2026-123158、CVSS 3.1は8.1。2026年11月5日、OpenSSH 10.6p2とAlpineの修正版が同時に公開されました。本記事では、この穴がどうやって生まれたのかを1980年まで遡って整理し、影響範囲と今すぐ取るべき対策をまとめます。

何が起きたのか——「パスワードなし」のアカウントが、長いパスワードで開く

まず、現象を正確に押さえます。派手な攻撃ではなく、地味な一致の問題です。

対象は、muslというCライブラリの上で、PAMを使わずにパスワード認証をしているsshdです。Alpine Linuxの標準パッケージが、そのまま当てはまります。

攻撃者は、パスワード欄が「*」になっているアカウント名を知っていればよいだけです。257〜1024バイトの長いパスワードを1回送れば、認証が通ります。

総当たりも、辞書攻撃も要りません。1回の接続で、毎回成功します。Alpineの勧告はそう書いています。

仕組み——「*」と「*」が一致してしまうまで

なぜ、そんなことが起きるのでしょうか。鍵は、3つの実装の重なりにあります。

パスワード照合の、ごく普通の流れ

sshdは受け取ったパスワードをcrypt()でハッシュ化し、/etc/shadowに保存された値と文字列で比べます。一致すればログイン成功です。

パスワード欄が「*」のアカウントには、ハッシュがありません。何を送っても一致しないはずです。

他人のソルトを借りる、という親切

ハッシュの計算にはソルトが要ります。ふつうは、保存されたハッシュの中に埋まっています。

ソルトがないアカウントでは、sshdは別アカウントのソルトを借りて計算します。2016年のCVE-2016-6210への対策として入った挙動です。存在するユーザーを応答時間から見分けられないようにするための工夫でした。

256バイトの壁と、失敗の返し方

muslのcrypt()は、パスワードが256バイトを超えるとエラーを返します。そのとき返す値が「*」です。

保存欄も「*」ですから、比較は一致します。sshdは「パスワードが合った」と判断します。

結果として、パスワードを持たないアカウントが、どんなパスワードでも受け入れる入り口に変わります。「失敗の印」と「ログイン不可の印」が、同じ1文字になったことが起点です。

4つの条件がすべて揃ったときだけ、穴は開く

ただし、どの環境でも起きるわけではありません。Alpineの勧告は、条件を4つに整理しています。

条件内容手元での確認
1. sshdがPAMを使っていないopenssh-serverはPAMなしでビルド。openssh-server-pamでもUsePAM noなら同じsshd -T にusepamの行が出ない
2. PasswordAuthenticationがyesOpenSSHの既定値。未設定ならyesになるsshd -T でpasswordauthenticationを確認
3. パスワード欄が「*」のアカウントがある鍵専用ユーザー、usermod -p ”、musl-nscd経由のユーザーなどshadowの2列目が「*」の行を探す
4. $5$か$6$のハッシュを持つアカウントが1つあるパスワードを持つユーザーが1人いれば足りるshadowの2列目が$5$または$6$で始まる行を探す

4つが揃って初めて影響を受けます。1つでも欠ければ対象外です。

見落としやすいのが4番目です。「自分はパスワードを設定しているから大丈夫」とはなりません。誰か1人がパスワードを持っていれば、パスワードなしのアカウントすべてに届きます。

40年の連鎖——1980年の1文字から、2016年の親切まで

この穴は、単独のバグではありません。4つの妥当な判断が、40年かけて積み上がった結果です。

時期出来事何が起きたか
1980年BSDの/etc/passwdに「*」Bill Joyがdaemonアカウントの欄に「*」を置く。ハッシュではないので、どのパスワードも一致しない
1997年Single UNIX Specificationcrypt()は失敗時にNULLを返すと規定。呼び出し側のNULLチェックが前提になる
2012年8月muslがNULLをやめる失敗時は「*」を返すよう変更。プログラムが落ちないようにするための配慮だった
2012年8月末SHA-512 cryptと256バイト上限20日後の追加。長いパスワードで計算に時間を取られないよう打ち切り、超過時は失敗つまり「*」を返す
2016年7月CVE-2016-6210の対策ユーザー存在の推測を防ぐため、ソルトがない場合は他アカウントのソルトを借りて計算する
2019年AlpineのDockerイメージrootにパスワードが無い状態が判明(CVE-2019-5021)。「!」でロックすると、PAMなしでは鍵認証まで壊れた
2022年Alpine 3.16rootを「*」に変更。鍵は通り、パスワードは通らない。意図どおりに見えた
2026年10月30日OpenSSHのレビューpick_salt()周辺を修正。問題の4行下には、この時点でも気づかれていない
2026年11月5日OpenSSH 10.6p2とAlpine修正版保存欄が4文字未満なら一致しても通さない、という形で修正された

どこにも「間違い」はありません。それぞれの時点で、理由のある変更でした。

ところが、最終的に「失敗の印」と「ログイン不可の印」が同じ1文字になりました。片方はハッシュの代わり、もう片方は照合の結果です。意味が違うのに、文字列としては同じです。

私はこの年表を読んだとき、設計の正しさと、組み合わせの危うさは別物だと感じました。

影響する環境、しない環境

対象かどうかは、libcとPAMの2点でほぼ決まります。表で整理します。

環境影響理由
Alpine Linux 3.16〜3.24・edge受けるmusl+PAMなしのsshdが標準構成
Alpineの公式クラウドイメージ(tiny-cloud・3.18.11〜3.24.3)受けるalpineユーザーが「*」で、パスワードなしのdoasを持つ
OpenWrt・Buildroot・Yocto条件次第sshdを動かしていれば同じ条件。OpenWrt標準のDropbearは対象外
musl系ベースのDockerイメージ条件次第コンテナ内でsshdを動かしている場合のみ
Debian・Ubuntu・Fedora・RHEL受けないglibc+PAM経由で、crypt()が「*」を返さない
FreeBSD・OpenBSD・macOS受けないlibcの実装が異なる
Windows版OpenSSH Server受けない(別件あり)この穴とは無関係。ただし別の脆弱性が10月13日に修正済み

コンテナの中でsshdを動かしていなければ、影響はありません。多くの用途は該当しないはずです。

一方、Alpineのクラウドイメージは要注意です。alpineユーザーがパスワードなしでdoasを使えるため、条件が揃うとrootまで到達します。

なお、rootは既定でPermitRootLogin prohibit-passwordです。パスワードでの直接ログインを許していなければ、rootそのものは入口になりません。

今日やること——更新、再起動、そして痕跡

該当しそうなら、対応は3つです。順番に進めてください。

1. まずバージョンを確認する

openssh-serverの版を確認し、自分のブランチの修正版以上にします。Alpine 3.24なら10.3_p1-r2が目安です。

修正入りのポイントリリースは3.21.10、3.22.8、3.23.8、3.24.4です。サポートが終わった3.16〜3.20にも、修正版が用意されました。

2. 更新したら、sshdを再起動する

パッケージを更新しても、動いているデーモンは古いままです。rc-service sshd restartまで実行してください。

すぐに更新できない場合は、PasswordAuthentication noで塞げます。3.19以降なら、/etc/ssh/sshd_config.d/に1行置くだけです。作業前に鍵でログインできることを確かめ、現在のセッションは閉じないでください。

3. 侵害の痕跡を探す

Alpineは/var/log/messagesで「Accepted password for」を探すよう案内しています。パスワードを持たないアカウント名があれば、侵入されたものとして扱います。

あわせてdoasの使用履歴、最近作られたユーザー、authorized_keysも確認してください。

見つけたのは、エージェントの群れだった

発見の経緯も、この穴らしいものでした。

報告者はWakefieldのÖzgün Kültekin氏です。同氏はパスワード処理のような「地味な部分」を、libcとの境界まで含めて調べました。

glibc、musl、PAMあり、PAMなし、shadowあり、なし。考えられる構成でsshdをビルドし、約17,600通りの変なログインを投げ込みました。

同氏の解説では、この総当たりを支えたのはエージェントの群れでした。すべてのビルドが同じ答えを返すなか、muslかつPAMなしの1つだけが「通すべきでないログイン」を受け入れました。

2026年10月30日には、OpenSSHのレビューがpick_salt()を修正しています。問題の4行下には、その時点でも気づかれていませんでした。

責任はsshdにあるのか、libcにあるのか

修正は出ましたが、根本原因の所在は見解が分かれています。

OpenSSH側の立場は、原因はsshdの外にあるというものです。ただしsshd経由で悪用でき、sshd側でも避けられる、としています。

muslのRich Felker氏は「muslのバグではなく、呼び出し側の誤用にすぎない」と述べています。一方で、この仕組みは次のリリースサイクルで変える可能性が高いとも書きました。

運用する側にとっては、sshdの更新で塞がると分かれば十分です。ただ、境界にまたがる不具合は、どちらのテストにも入りにくいという教訓が残ります。

なぜ10年間、誰も気づかなかったのか

2016年から2026年まで、この穴は表に出ていません。理由は4つ。

1つ目は、テストの配置です。OpenSSHはOpenBSDとglibcでテストし、muslはsshdをテストしていません。境界の両側を、それぞれ別の人が見ていました。

2つ目は、PAMという安全網です。多くのディストリビューションはPAM経由で認証するため、「*」のアカウントではcrypt()自体が呼ばれません。

3つ目は、条件の多さです。4つ揃わなければ再現しません。作りたてのサーバーでは、まず起きません。

4つ目は、偶然の近さです。2013年には、Debianの開発者がglibcにmuslの「*」を採り入れるよう提案していました。2019年にDebianがlibxcryptへ移行したとき、返す値は「*0」になりました。1文字違いで、同じ穴を回避していたことになります。

2024年12月のmuslのメーリングリストには、257文字のパスワードでbusybox passwdが壊れる、という投稿があります。同じ「*」、同じ上限です。それでも、誰もsshdの名前を出していません。

これは特別な話ではない——AIが40年分の負債を暴く時代

今回の件は、単独の事故として片づけられません。

2026年10月下旬には、PHPの重大な脆弱性「PHP2Shell」が公表されました。元になったバグは2024年に報告されていましたが、「通常は落ちるだけ」として後回しにされていました。

OpenAIの支援でPHPを監査した企業の研究者が、AIツールを使って2週間で任意コード実行の方法を見つけた、とIEEE Spectrumが伝えています。

40年かけて書かれたレガシーコードが、AIによって次々に暴かれています。今回のssholeも、人間が1つずつ確かめていたら、膨大な時間がかかったはずです。

同時期には、Windows版OpenSSHのCVE-2026-97816(CVSS 9.8)や、IPv4のTCP処理に関するカーネルのCVE-2026-98432も動いています。サーバーの待ち受けまわりは、いま静かに再点検の時期に入っています。

【FAQ】OpenSSHの「*sshole」に関するよくある質問

最後に、問い合わせの多い点をまとめました。

質問回答
UbuntuやDebianのサーバーも危ないのですか?この穴の影響は受けません。glibc+PAM経由で認証するため、crypt()が「*」を返す経路を通りません。ただし同時期の別の脆弱性は別途確認が必要です。
「*」と「!」は何が違うのですか?どちらもログイン不可を示す記号ですが、扱いが異なります。PAMなしの環境では「!」が鍵認証まで止めてしまうため、Alpineは2022年から「*」を使っています。今回の穴は、その「*」が起点です。
コンテナを使っていても影響を受けますか?コンテナ内でsshdを動かしていなければ影響はありません。動かしている場合は、ベースイメージのlibcとPAMの設定を確認してください。
修正版に上げれば、設定はそのままで大丈夫ですか?更新後にsshdの再起動が必要です。再起動しなければ、古いデーモンが動き続けます。あわせて侵害の痕跡も確認してください。
すでに侵入されていた場合、何を見れば分かりますか?「Accepted password for」の記録に、パスワードを持たないアカウント名が出ていないかを見ます。doasの履歴、新しいユーザー、authorized_keysの変更も手がかりになります。
この穴に名前が付いたのはなぜですか?「*」とSSHを掛けた通称です。研究者自身の表記は「*sshole」で、CVE番号はCVE-2026-123158です。名前の軽さに反して、CVSSは8.1の高い深刻度です。

まとめ——「入れないつもり」のアカウントが、いちばんの入口になる

鍵だけで入るつもりで作ったアカウントが、パスワードを持たないせいで入口になっていました。

私は今回、セキュリティの弱点は「設定ミス」よりも「正しい判断の積み重ね」から生まれるのだと理解しました。4つの設計判断は、どれも当時の理由がはっきりしています。

できることは限られています。libcとPAMの構成を知り、opensshを更新して再起動する。それが済んだら、shadowの「*」と「!」がどう並んでいるかを一度眺めておく。

まずは自分の環境で、sshdの設定とlibcの種類を確認してください。小さな違和感を放置しない運用を、今日から始めましょう。

コメント

タイトルとURLをコピーしました