debiruはてなメモ

はてなブログの HTML が Invalid なの、わたし、気になります

失効証明書とOCSPの不思議な関係

1月29日に271万件のLet's Encrypt証明書が失効した

特定の条件で発行したLet's EncryptのSSL/TLSサーバ証明書が無効化されるニュースが2022年1月26日(日本時間)に発表されました。該当者にはメール通知が届いており、jpドメインだけ見れば2月9日時点で7割ほどが対応済み(詳細は4章を参照)のようです。

通常、一度発行したサーバ証明書は期限(expires または notAfter と呼ばれるもの)までは正常な動作のために使用することができますが、期限内であっても何らかの理由で証明書が失効(revoke)させられることがあります。

Let's Encrypt の場合は certbot revoke コマンドを実行することで意図的に失効させることもできます。

失効しているかどうかの情報は証明書自体は持っていません。それは、ある事情で社員証を返すのが遅れ、退職日以降もその会社の社員証を持っているような状況に似ています。Webブラウザは、証明書が有効なものかどうかを別の手段で確認する必要があります。

この記事では簡単のため「Webサーバ」と「Webクライアント(Webブラウザ)」の関係で説明しますが、この記事の内容は「TLSサーバ」と「TLSクライアント」の間に成り立つ仕組みの話です。

CRL, OCSP, OCSP Stapling

Webブラウザが証明書の失効状況を確認する手段として、CRL(Certificate Revocation List; 証明書失効リスト)と、OCSP(Online Certificate Status Protocol; 証明書オンラインチェック)があります(*1)

CRL(Certificate Revocation List)

CRLは証明書失効リストとも呼ばれ、認証局(CA)が公開している失効した証明書のシリアルのリストのことを意味します。実際には認証局(CA; Certificate Authority)とは別に検証局(VA; Validation Authority)が公開している場合があります。

Webブラウザは事前に取得したCRLを元に、アクセスしようとしているサーバから送られてきた証明書の有効性をチェックします。その認証局(CA)の失効証明書が多い場合にはCRLが巨大になり、Webブラウザ側でのリスト検索の処理に時間的コストが掛かります。

OCSP(Online Certificate Status Protocol)

OCSPはその名の通り、オンラインで証明書の状態をチェックする仕組みです。OCSPの結果(OCSP Response; レスポンス)を返すOCSP Responder(OCSPサーバ)が認証局(CA)ごとに用意されており、WebブラウザOCSPサーバにシリアルを問い合わせることで証明書の有効性をチェックできます。こちらも実際には認証局(CA)とは別に検証局(VA)がOCSP Responderとなっている場合があります。

CRLでは巨大なリストを取得することのネットワーク負荷の懸念や古いリストを用いることで最新の失効情報を見逃す可能性がありました。そうした問題を解決するためにOCSPが考案されました。

しかし後になって分かったことですが、そんなOCSPにも問題点がありました。

  • パフォーマンス上の問題
    • HTTPS接続毎にOCSPサーバへの問い合わせをしてレスポンスを待つ必要があるため、目的のWebページへアクセスするのに遅延が発生してしまう。
  • セキュリティ上の問題
    • OCSPサーバから応答が得られる確証がないこと。全てのHTTPS接続毎にOCSPサーバにリクエストが来るため、OCSPサーバがダウンしたり何らかの理由で応答できなかったときに、検証ができなくなってしまう。
    • 検証できないからとエラーにしてしまうとユーザ体験を損なってしまう。そのため、(TLSクライアントの中でも特に)多くのWebブラウザでは「OCSP検証に失敗した場合は、証明書を有効とみなす」というポリシー(soft-fail)が適用されている。
  • プライバシー上の問題
    • HTTPSであるURLにアクセスするごとに、そのURLの証明書のシリアルを「WebブラウザOCSPサーバに問い合わせる」という動作が必要になるため、OCSPサーバにエンドユーザ(Webブラウザ)がどのURLにアクセスしようとしているのかが漏れてしまう。

OCSP Stapling(OCSPステープリング; ホチキス留め)

OCSPでは、WebブラウザOCSPサーバに問い合わせていました。

OCSP Staplingでは、予めWebサーバ側でOCSPサーバからOCSP Responseを受け取りキャッシュしておき、WebブラウザからHTTPS接続の要求があったときにサーバ証明書と一緒にキャッシュしていたOCSP Responseを渡すという動作にすることで、OCSPでの問題点を解消しようとしました。

OCSP Staplingで使われるOCSP ResponseはWebサーバ側で一定期間キャッシュすることが認められています(詳細は3章を参照)。リアルタイム性を多少犠牲にすることで、パフォーマンスの問題を解消しています。プライバシー上の問題点も解消しています。

OCSP Staplingは仕組みを表す用語ですが、同時に「OCSP Staplingの仕組みによって提供されるOCSP Response」を表すこともあります。どちらの意味であるかは文脈で判断してください。

私が観測した予想外の出来事

Let's Encrypt の一部の証明書(271万件ほど)が失効された。そして、Webブラウザが失効を知る手段が用意されている。というのがここまでのお話でした。

1章の見出しの通り、Let's Encrypt からは1月29日に271万件の証明書の失効を完了したとアナウンスされています。

私は1月末の時点ではOCSPの仕組みの存在を知りませんでした。そのため、「証明書が失効されたというのに、普通にそのURLにHTTPSでアクセスできてしまう」ことが予想外でした。そこから私の調査が始まります。

なお、私の確認環境は macOSFirefoxChrome です(結果的に他のブラウザは個別に言及する必要がありませんでした。他のOSは試せていません)。

OCSP Staplingというものが関係しているらしい

ここで2章で説明した内容を初めて理解しました。では、何故かアクセスできてしまうが、一体いつまでアクセスできるのでしょうか?

OCSP Staplingは最長7日で更新が必要

WebサーバはWebブラウザに返すOCSP Staplingを最大7日間キャッシュしてよいと定められています。OCSP Response(レスポンス)には、キャッシュ生成日時(This Update)と次の更新予定日時(Next Update)が含まれています。Let's Encryptでは、Next UpdateはThis Updateの7日後の日時になっているようです。

失効から7日目で予想外の挙動

Next Updateは(有効期限ではなく)更新予定日時なので、失効対象の証明書を使っている一部のWebサーバはNext Updateを過ぎたOCSP Staplingを返していました。OCSP Staplingがあるせいなのか、少なくとも私のmacOS Firefoxでは普通にHTTPSでWebサイトにアクセスできてしまっていました。

これは一体どういうことなのか。証明書を失効したと言いつつ、Webサーバが(Next Updateを過ぎた)OCSP Staplingを送り続ける限りアクセスできてしまっていいのかと疑問に思いLet's Encrypt の公式フォーラムで質問しました

すると識者から、「調べてみたら "CA/Browser Forum Baseline Requirements" (CA/BF-BRs) というものがあり、そこではThis Updateから最長でも10日間はOCSP Staplingを使用してよいと定められていた」ということを教えてもらえました。これはMozillaWikiをよくよく読むと、「7日間よりも長い10日間」という意味ではなく「Next Updateが遠い将来(20日後など)であったとしても10日間までしか有効扱いしない」という文脈で書かれていますね。

失効から8日目以降にまた変化が

Next Updateを過ぎてもmacOS FirefoxでアクセスできていたURLが突然revoked(失効したため証明書エラー)に変わりました。教えてもらった11日目ではありませんが、これは一体どういうことでしょうか。観測上は8日間までアクセスできていたように思えます。

という感じのことをツイートしていたら、Firefoxの実装では「This Updateの10日後と、Next Updateを比較して早い方+1日でチェックしている」と教えていただきました。Let's EncryptのOCSPではNext UpdateがThis Updateの7日後になるので結果的に「8日間」までアクセスできる(9日目からrevoked)ということになりますね。ここまで分かって、これまでの挙動がだいぶ納得できました。

OSによる挙動の違い

ここまで私はmacOSでしか確認しておらず、macOSではFirefoxでもChromeでもNext Updateを過ぎた8日目以降はrevokedになることを確認していました(Firefoxでは前述の猶予があるため9日目以降)。

しかしなんと、Twitterや公式フォーラムで別の方が、9日目以降も全てのブラウザで(revokedにならず)アクセスできるというのです。少し議論したところどうやらOSの違いにより異なる結果が得られているらしいことが分かりました。

フォーラムの回答で紹介されたHow Do Browsers Handle Revoked SSL/TLS Certificates? - SSL.comでは末尾にOS/ブラウザ別の検証結果があり、結果がOSでバラバラになっていることが確認できます。

Let's Encryptの失効証明書の調査にあたって

発端は公開された271万件の失効予定のドメイン名リストでした。

これらは私が今回の調査の一環で作成したウェブページとAPIです。

更新状況の一覧表ではjpドメインしか対象にしていませんが、2月9日時点で70%強が "good" な証明書を使っていることが確認できます。

結論

結局、失効された証明書を使っているのに現在でもアクセスできてしまうOS/ブラウザがあるようです。失効とは何だったのでしょうか。私には理解できずにいます。OCSPとは何だったのでしょうか。ここまで書きましたが、上記の内容も正しいのかよく分かりません。そんなところでOCSPを巡る今回の調査はお終いにしようかと思います。

Let's EncryptでTLS-ALPN-01チャレンジによって証明書を発行し、失効対象になったものの再発行をせずにそのままの状態で放置しているサイトもいくつか見受けられます。そもそも運用するつもりのない実験サイトだったらよいのですが、jp以外にも(comやnetやら色々)同様に放置されているサイトが散見されます。管理しているドメインがあるのであれば、SSL/TLSサーバ証明書のステータスを確認してみてもよいかもしれませんね。

脚注

Next debiru's HINT 「WebはWEBじゃない