2026年11月5日、Linuxエコシステムにおいて暗号理論の常識を覆す重大なセキュリティ脆弱性が公表された。Alpine Linuxベースで稼働する数百万ものコンテナにおいて、パスワードログインを無効化していたはずのアカウントが不正侵入を許す事態となったのである。攻撃者はパスワード入力欄に257文字のランダムな文字列を流し込むだけで、システム権限を奪取することができた。
パスワードは長ければ長いほど強固であり、極端に長い入力は境界防御で弾かれるはずだというのが一般的な常識だろう。しかし現実はその逆を突いた。堅牢に施錠されていたはずのゲートが、無作為に入力された長大な文字列によってあっさりと押し開けられてしまったのである。
257文字の長大入力が防壁を突破:認証ロジックのすり抜け
この脆弱性の成立条件は極めて特異かつ正確である。対象サーバーがmusl CライブラリとリンクされたOpenSSHを実行しており、かつPAMモジュールが無効化されていること。この環境下で攻撃者が257〜1024バイトのパスワードを送信すると、認証チェックは即座に通過してしまう。
257バイトという長さは通常のパスワードではあり得ない異常値だ。しかしこの入力値がパスワード照合ロジックの深部に到達した際、システムはログイン不可能なはずのアカウントを「認証成功」と判定してしまった。設計通りの防御機能が致命的な破綻をきたした瞬間である。
影響を受けるアカウントには明確な特徴があった。/etc/shadow ファイル内のパスワードハッシュフィールドに単一の文字 * が設定されていることである。UNIXの規約において、アスタリスクは「パスワード認証を恒久的に拒否する」ことを意味する。クラウド事業者の公式イメージや公開鍵認証のみを前提とする運用アカウントは、まさにこの設定で作られている。
クラウド環境はこの条件を典型的に満たしていた。Alpine公式のAWSやAzure向けイメージに含まれる既定ユーザー alpine にはこの設定が適用されており、さらにパスワード不要の doas 権限が付与されていた。このアカウントを奪取することは、即座にroot権限を掌握することを意味する。
システム内に通常のパスワードハッシュを持つアカウントがもう1つ存在しさえすれば、攻撃は確実に成立する。OpenSSHはタイミング攻撃を防ぐために、別アカウントのソルトを流用してダミーの暗号計算を実行する。複数の防御策が重なり合った結果、皮肉にも攻撃者にシステムへのフリーパスを渡す結果となった。
46年の歳月を経て衝突した「3つの合理的な決断」
UNIXとCライブラリの歴史を紐解くと、このバックドアは数十年の開きがある3つの独立した設計判断が組み合わさることで偶然誕生したことがわかる。導入当時、それぞれの決定は極めて合理的で思慮深いものだったが、最終的な組み合わせが致命的なバグへと変貌した。
最初の決断は1980年。Bill Joyが3BSDのパスワードファイルにおいて、サービスアカウント daemon のパスワードフィールドに * を書き込んだことだ。当時の暗号化アルゴリズムでは1文字のアスタリスクを出力することが不可能であったため、いかなる入力パスワードとも一致しない安全な無効化手段として機能した。
図:1980年の3BSDにおけるpasswdファイルの原本。daemonアカウントのフィールドにアスタリスクが指定されている。出典:sshhole.com
アスタリスクでアカウントをロックするというこのシンプルな慣例は、46年間にわたり業界標準として受け継がれてきた。
2つ目の決断は1997年。UNIX国際規格(SUS)は、パスワード暗号化関数 crypt() が計算エラーを起こした際にNULLポインタを返すべきであると規定した。しかし多くのC言語プログラムは戻り値のNULLチェックを怠っており、NULL参照によるセグメンテーション違反でサービスが突然クラッシュする問題を抱えていた。
2012年8月、軽量Cライブラリであるmuslの開発陣はこの潜在的リスクに対応した。NULLクラッシュを根絶するため、コミット b3c4cc12 において、計算エラー発生時の戻り値を単一のアスタリスク * に変更した。「エラーは起こり得ない」とされていた過去のコメントも同時に削除された。
図:エラー発生時に単一のアスタリスクを返すことを明記したmuslヘッダーのコメント。出典:sshhole.com
musl開発者にとってアスタリスクは「計算の失敗」を意味した。一方、システム管理者にとってアスタリスクは「ログイン禁止」を意味していた。全く異なる2つの文脈が、同じ1文字に相反する意味を付与していたのである。
DoS防止の文字数制限とサイドチャネル対策の偶発的連鎖
3つ目の決断が、この2つのアスタリスクを決定的に結びつけた。2012年8月29日、前回の変更からわずか20日後、muslライブラリはSHA-512暗号化のサポートを追加した。
SHA-512は計算コストが極めて高く、パスワードの長さに比例して処理時間が増大する。過剰に長いパスワードによるCPU枯渇(DoS攻撃)を防ぐため、muslはパスワード長の上限を厳格に256バイトに定めた。256バイトを超える入力が渡されると計算を拒否し、エラーとして単一のアスタリスク * を返す仕様とした。
図:過度な計算負荷によるDoSを防ぐためcrypt_sha512.cに追加された256バイト上限。出典:sshhole.com
この256バイトのハードリミットはリソース枯渇攻撃を未然に防ぎ、何年間も安定して機能し続けた。
そして2016年7月、OpenSSHはタイミング解析脆弱性(CVE-2016-6210)の修正を実施した。存在しないユーザーに対する応答が早いことを利用して有効なユーザー名を列挙されるのを防ぐため、OpenSSHは計算時間の均一化ロジックを導入した。
パスワードハッシュを持たないアカウントに対しては、別のアカウントからソルトを借用して1回ダミーのハッシュ計算を行い、意図的に時間を消費させるようにした。アスタリスクで無効化されているアカウントも、このダミー計算の経路を通ることになった。
ここで脆弱性の鎖が完全に噛み合った。攻撃者がrootアカウント宛てに257バイトの長大パスワードを送信する。OpenSSHはソルトを借用して crypt() を呼び出す。muslは長さ制限オーバーを検知して即座に処理を中断し、エラーを示す * を返す。OpenSSHは返された * と /etc/shadow 内の文字列を比較する。双方は完全に一致し、システムは認証成功と判断してシェルを明け渡してしまう。
コンテナ普及が招いた波及:軽量設計が数百万のクラウドホストへ
かつてmuslはルーターなどの組み込み機器で主に利用されており、潜在的な攻撃対象は限られていた。しかしコンテナ技術の急速な普及が、この設計を世界のクラウドアークテクチャの中心へと押し上げた。
わずか5MBという超軽量なフットプリントを持つAlpine Linuxは、瞬く間に世界中のコンテナのデファクトスタンダードとなった。2019年、公式イメージのrootアカウントの空パスワード問題を修正する際、パスワードフィールドを感嘆符 ! に変更したことがあった。しかし感嘆符は非PAM環境での公開鍵認証を阻害し、クラウド各社のSSH接続でトラブルを引き起こした。
これを受けて2022年リリースのAlpine 3.16では、rootのパスワードフィールドを再びアスタリスク * へ戻す変更が行われた。これにより鍵認証は復旧したが、同時にそれ以降のすべてのコンテナイメージが脆弱性の成立条件を抱え込むこととなった。
技術コミュニティでは被害規模の検証が迅速に進められた。開発者jbyersは、単一のコンテナがすべての条件に合致する確率は極端に高くはないものの、世界全体で稼働する膨大なコンテナ母数を乗算すれば影響を受けるインスタンスは膨大な数に上ると指摘した。何百万もの本番コンテナが意図せずこの危険な組み合わせを採用していたのである。
標準規格への適合性をめぐる議論も巻き起こった。開発者NewJazzはmuslの仕様がPOSIX標準から逸脱していると疑問を呈したが、POSIXの原文を引用した他の開発者は、規格上は単一のエラーコードが定義されているに過ぎず、例外時の挙動に関する明確な基準が欠如していたことを指摘した。
Lobstersのコメント欄ではmortが脆弱性報告のスタイルに苦言を呈し、ドラマチックな演出よりも影響範囲と具体的な修正方法を簡潔に提示すべきだと主張した。
パッケージ更新だけでは不十分:プロセスの即時再起動が必須
2026年11月5日、OpenSSHの上流プロジェクトはバージョン10.6p2をリリースした。新バージョンでは1文字の戻り値を直接受け入れないフィルタリングルールが追加され、アプリケーション層がライブラリの戻り値仕様を無批判に信用しないよう対策が施された。
しかし、パッケージを更新しただけでは対策は完了しない。Linuxのプロセス常駐メカニズムが管理者の盲点となりやすい。
パッケージマネージャーがディスク上のバイナリを書き換えても、メモリ上に常駐している古いプロセスは以前のコードを実行し続ける。サービスを明示的に再起動しなければ、システムは依然として脆弱な状態に晒される。管理者は直ちに sshd サービスを再起動するか、対象コンテナを再構築・再デプロイする必要がある。
このセキュリティ事件を振り返ると、悪意を持って書かれたコードは1行も存在しなかった。1980年のアスタリスクによるアクセス無効化、1997年のクラッシュ回避のための戻り値変更、2012年のDoS対策による入力制限、2016年のタイミング攻撃を防ぐダミー計算。すべてがその時代における合理的な技術的選択であった。
数十年を隔てて積み重ねられたこれら複数の防御ロジックが、ある一点で交錯した。仕様の意味論的なわずかな食い違いが、特権昇格の裏口を作り出してしまったのだ。複雑化した現代のソフトウェア環境において、互いの前提を理解せぬまま積み重なった防御機構は、単一の欠陥よりもはるかに見つけにくく、根深いリスクをもたらす。
参考リンク:
- sshhole.com 脆弱性開示原文とオンライン検証ツール
- Alpine aports コミット fbe926af:rootのパスワードフィールドを感嘆符からアスタリスクに変更
- OpenSSH 10.6p2 公式リリースノートおよびパッチソースコード
- Hacker Newsにおけるmusl cryptエラー戻り値に関する技術的議論
- Lobstersにおけるコンテナセキュリティ境界と対応策に関する議論