Alpine Linuxで任意パスワードでSSHログイン可能な脆弱性が2016年から存在
原題: sshole
なぜ重要か
Alpine Linuxベースは多くの本番DockerイメージやIoTファームウェアで使われており、鍵認証のみを前提とした設計のサーバーが実は平文パスワードで侵入可能という事実は、ゼロトラスト前提のセキュリティ設計を根底から揺るがす。
musl libcを採用するAlpine Linux、OpenWrt、Buildroot、Yoctoおよび多数のDockerイメージにおいて、2016年以降、rootや鍵認証専用ユーザーなど本来パスワード認証を持たないアカウントに対し、256文字を超える任意のパスワードでSSHログインが可能な状態が続いていたことが明らかになった。複数のCVEと設計上の判断が連鎖した結果として生じた問題で、影響範囲はクラウドイメージを含む広範なLinux環境に及ぶ。
問題の根源は1980年代のUnixに遡る。パスワードを持たないアカウントには `/etc/passwd` の該当フィールドに `*`(アスタリスク)が入る慣習があり、これはどんなハッシュとも一致しないため実質的なロックとして機能してきた。
1990年代、`crypt()` 関数の仕様として「処理に失敗した場合はNULLを返す」というルールが定められた。しかし多くの実装はNULLチェックを怠り、クラッシュが頻発した。
2012年8月、musl libcの開発チームはこの問題を解消するため、`crypt()` の失敗時の戻り値をNULLではなく `*` に変更した。意図は「クラッシュを防ぐ」だったが、偶然にもロックアカウントを示す文字と同一になった。さらに同月20日後、musl はsha512cryptに対して256バイトを超えるパスワードの処理を打ち切る上限を設けた。DoS対策としての合理的な判断だったが、上限を超えた場合に `crypt()` は失敗し、`*` を返すようになった。
2016年、CVE-2016-6210への対応としてOpenSSHは、存在しないユーザーに対するタイミング攻撃を防ぐため、実在しないアカウントにも別ユーザーのsaltを使ってダミーのハッシュ計算を行うよう変更された。この修正は意図せず `*` を持つ実在ユーザーにも同様に適用された。
結果として、鍵認証専用のdeployユーザー、LDAP管理のアカウント、パスワードなしのroot、AlpineのAWSおよびAzure公式イメージのデフォルトユーザーなど、パスワードを持つべきでないアカウントに対して、256文字を超える任意の文字列を入力するだけでSSHログインが通る状態が生まれた。
2019年にはAlpineのDockerイメージにrootパスワードが存在しない問題がCVE-2019-5021として報告され、`!` によるロックで対処されたが、musl環境では `!` も正しく機能しない可能性が残る。影響を受けるシステムは現在も広く稼働中とみられる。