相互 TLS の認可は「秘密鍵の所持を確かめた証明書」だけで行う:LXD・MicroCloud のなりすまし
Canonical の LXD と MicroCloud で、他人の公開証明書を使ってなりすませる脆弱性が修正された。相互 TLS(mTLS)で、接続者が秘密鍵を持っていると確かめられたリーフ証明書以外の証明書まで、登録済み証明書との照合に使っていたのが原因。
なぜなりすませるのか
- TLS クライアントは、自分のリーフ証明書に加えて中間証明書などのチェーンを送れる。TLS のハンドシェイクで秘密鍵の所持が証明されるのは、リーフ証明書だけ。
- 公開証明書は誰でも入手できる。サーバーが「受け取ったチェーンの中に、登録済みの証明書が 1 枚でも含まれていれば許可」と実装すると、攻撃者は自分の鍵のリーフ証明書の後ろに被害者の公開証明書を付けて送るだけで、被害者として認可される。
実装で守ること
- 認可(どの利用者か、許可リストに載っているか)の判定には、リーフ証明書だけを使う。Go なら
tls.ConnectionState.PeerCertificates[0]、検証済みならVerifiedChains[i][0]を見る。 - 証明書のピン留め(フィンガープリント照合)も、リーフ証明書に対して行う。チェーン全体を走査して一致を探す書き方を避ける。
- 中間証明書は「リーフを検証するための材料」としてだけ扱い、身元の根拠にしない。
- 自作の mTLS 認可コードがあれば、「被害者の証明書を余分に付けたチェーン」を送るテストを足す。
利用者側の対応
- LXD と MicroCloud を Canonical の修正版に更新する。信頼済みクライアント証明書を使う遠隔管理を公開している環境は優先する。