GMOアドマーケティングでインフラを担当するK.Aです。
弊社が提供しているサービスはネット広告を扱うが故、エンドポイントに不特定多数がアクセス可能なサービスとなっています。故に脆弱性診断を定期的に実施しており、非常に気を使っています。
今回は OCSP Stapling(ステープリング)について、弊社で対応した内容を共有したいと思います。
尚、OSは来年 EoF を迎える CentOS 7 を、SSL証明書は GlobalSign 発行の証明書を使用しています。
OCSP とは
OCSPは「Online Certificate Status Protocol」の略称で、X.509公開鍵証明書の失効状態を取得するための通信プロトコルで主に HTTP を使ってやり取りされます。
脆弱性
OCSPには複数の脆弱性が報告されています。
直近であれば JVN iPedia のデータベースに下記の脆弱性が報告されています。
JVNDB-2022-001802 OpenSSL の OCSP_basic_verify 関数における OCSP レスポンスの署名者証明書の検証に関する脆弱性
これらの問題への対策として OCSP Stapling と呼ばれる機能を使用することで、解決することができます。
OCSP Stapling の有効化方法
nginx の場合、SSLの設定をしている server ディレクティブに下記2行の設定を追加し、nginx を Reload します
1 2 |
ssl_stapling on; ssl_stapling_verify on; |
ただし、SSL証明書の設定方法によってエラーが発生します。
設定を反映したら OCSP Stapling が有効化したか確認します。
1 2 3 4 5 6 7 8 |
$ openssl s_client -connect {ドメイン名}:443 -status | grep OCSP depth=2 OU = GlobalSign Root CA - R3, O = GlobalSign, CN = GlobalSign verify return:1 depth=1 C = BE, O = GlobalSign nv-sa, CN = GlobalSign GCC R3 DV TLS CA 2020 verify return:1 depth=0 CN = hogehoge.jp verify return:1 OCSP response: no response sent |
予想通り、下記のエラーが発生し有効化されていませんでした。
この時、nginx のエラーログには以下のエラーが発生していました。
1 |
2023/**/** **:**:** [error] 11369#11369: OCSP_basic_verify() failed (SSL: error:27069065:OCSP routines:OCSP_basic_verify:certificate verify error:Verify error:unable to get local issuer certificate) while requesting certificate status, responder: ocsp.globalsign.com, peer: 104.18.20.226:80, certificate: "{SSL証明書へのファイルパス}" |
このエラーの原因は、設定したSSL証明書の発行元であるルート認証局のルート証明書を nginx が認識できていない場合にも発生します。
エラーに対処すべく、追加で加えた設定が ssl_trusted_certificate です。
1 |
ssl_trusted_certificate /etc/pki/tls/certs/ca-bundle.crt |
標準のパッケージの ca-certificate にはルート証明書が含まれており /etc/pki/tls/certs/ca-bundle.crt にインストールされています。
大半の場合は ssl_trusted_certificate を設定することでエラーを回避できると思います。
それでもエラーが続く場合は、SSL証明書の発行元のサイトよりSSL証明書に合ったルート証明書をダウンロードしそのファイルを指定すれば、エラー回避できるはずです。
実際に上記の設定を追加した後、動作を確認した結果ところ、以下のようにレスポンスが返却されるようになりました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# openssl s_client -connect bid.st.dsp.reemo-ad.jp:443 -status CONNECTED(00000003) depth=2 OU = GlobalSign Root CA - R3, O = GlobalSign, CN = GlobalSign verify return:1 depth=1 C = BE, O = GlobalSign nv-sa, CN = GlobalSign GCC R3 DV TLS CA 2020 verify return:1 depth=0 CN = *.hogehoge.jp verify return:1 OCSP response: ====================================== OCSP Response Data: OCSP Response Status: successful (0x0) Response Type: Basic OCSP Response Version: 1 (0x0) Responder Id: ******************************************** Produced At: *** ** **:**:** 2023 GMT Responses: Certificate ID: Hash Algorithm: sha1 Issuer Name Hash: *************************************** Issuer Key Hash: ************************************** Serial Number: ******************** Cert Status: good |
これで OCSP Stapling の設定が有効化された事が確認できました。
念の為、nginx のエラーログを確認したところ、発生していたエラーは解消されていましたが、エラーとは別に以下のワーニングが発生している事に気が付きました。
1 |
2023/**/** **:**:** [warn] 11369#11369: no resolver defined to resolve ocsp.globalsign.com while requesting certificate status, responder: ocsp.globalsign.com, certificate: "{SSL証明書へのファイルパス}" |
このメッセージを調べた結果、nginx はReloadやRestartのタイミングでしかDNSの名前解決を行わないという情報を目にしました。どうやらこの仕様が原因で、nginx プロセス起動後に名前解決を促すには nginx 用のリゾルバ設定をする事で、回避できそうです。
さらに追加で加えた設定が resolver です。
1 |
resolver 8.8.8.8 8.8.4.4 valid=300s; |
こちらを追加する事により、TTLを無視して 300秒 に1回、名前解決を実行させる事が可能のようです。
先ほどと同じように設定を反映させ、エラーログを確認をしたところ、何も発生しなくなりました。
以上で OCSP Stapling 有効化の設定が完了になります。
緊急度は低いかもしれませんが、こうした小さい脆弱性に対して1つずつ対応していくことが、サービスの信頼性を向上させる事に繋がるかと思います。