今回は、Webサーバで利用しているSSLをよりセキュアにしていきたいと思います
記事が長くなりそうなので、複数回に分けていきます。
だいぶ間が空いてしまいましたが、第3回はWebサーバのForward SecrecyとTLS1.3の対応を進めていきます
これまでのサーバ構築同様にUbuntu 20 & NGINX をベースにしますが、Apache2の設定例も記載していきます。
Ubuntuに限らず、CentOSなどでも設定ファイルの場所を読み替えてもらえば問題ないと思いはずです。
Forward Secrecy(前方秘匿性)とは
SSLでは鍵交換を行い、共通鍵を利用して通信を行います。サーバの秘密鍵が漏洩した場合は内容が解読できる仕組みとなります。
例えば通信経路上で過去の通信データが保管され、後から秘密鍵が流出や計算などにより特定された場合は過去の通信データが解読できてしまいます。
Forward Secrecyとは、サーバの秘密鍵が漏洩した場合でも、過去に暗号化されたデータの安全性を守ろうという考え方になります。
Perfect Forward Secrecy
Forward Secrecyの中でも以下2点を満たすものはPerfect Forward Secrecyと呼ばれます。
- 鍵合意のために公開可能なランダムな値を利用
- 鍵合意の過程で家体的なアルゴリズムを一切使用しない
実用化された方法としては、DHE(Diffie-Hellman鍵共有)やECDHE(楕円曲線Diffie-Hellman鍵共有)です。
これらの方法では、データ暗号化の際にサーバの秘密鍵・公開鍵を利用するのではなく、クライアントとサーバそれぞれに秘密鍵を持たせるようにします。
公開されている2つのデータと、クライアント・サーバそれぞれの秘密鍵から生成したデータを元に、相手の秘密鍵をしることなく暗号化した通信が可能です。
第三者がこの方式で暗号化されたデータの解読を行うためにはクライアント・サーバそれぞれの秘密鍵を利用する必要があるため、仮に一方の秘密鍵が漏洩した場合もデータの安全性が守られます。またDHEやECDHEでは秘密鍵は固定ではなく随時更新されるため、現時点では第三者による解読の可能性は極めて低いとされています。
Forward Secrecyとサーバ証明書
暗号化だけでは通信相手を検証する事ができず中間者攻撃が可能となるため、SSL/TLSでは証明書と組合せた以下ような方式を利用します。
DHE-RSA | DHEとRSA証明書の組み合わせ |
DHE-DSS | DHEとDSA証明書の組み合わせ |
ECDHE-RSA | ECDHEとRSA証明書の組み合わせ |
ECDHE-ECDSA | ECDHEと楕円曲線DSA証明書の組み合わせ |
Qualys SSL Server Test:Protocol Support(対応プロトコル)
Qualys SSL Server Testの評価項目Protocol Supportは現時点で有効なプロトコルをサポートしているかがチェックされます。
これまでに規格化されているプロトコルは以下の通りです。
2021年7月現在、利用可能なプロトコルはTLS1.2およびTLS1.3です
プロトコル | 概要 | 規格化年 | 禁止/非推奨年月 |
---|---|---|---|
SSL2.0 | ネットスケープ社にて開発 SSL2.0にはチェーン証明書しかなく、ルートCAから発行したSSLサーバ証明書しか利用できない 複数の脆弱性が発見されてており、2011/3に使用禁止 |
1995 | 2011/3(RFC6176にて禁止) |
SSL3.0 | ネットスケープ社にて開発 2014/10にSSL3.0の使用上の脆弱性(POODLE攻撃)が発見されたため2015/6に使用禁止 |
1996 | 2015/6(RFC7568にて禁止) |
TLS1.0 | IETFのTLSワーキンググループで規格化 機能としてはSSL3.0とあまり変わらないが、アルゴリズムやルートCAの自己署名証明書の取扱いなどの仕様詳細が変更されたり、サーバ証明書チェックに利用されるハッシュ化アルゴリズムとして「SHA-1」を採用 複数の脆弱性があり、2021年3月をもって非推奨 |
1999 | 2021/3(RFC8996にて非推奨) |
TLS1.1 | サーバ証明書チェックに利用されるハッシュ化アルゴリズムはTLS1.0と同様で「SHA-1」を採用 CBCモードの脆弱性を利用した攻撃(BEAST攻撃など)への耐性をあげるために初期化ベクトルの明示かや、パディングの処理が改善された。また、共通鍵暗号化アルゴリズムとしてAESが選択肢に加わった。 2005年にSHA-1への効果的な攻撃方法を発見されたことなどにより、2021年3月をもって非推奨 |
2006 | 2021/3(RFC8996いて非推奨) |
TLS1.2 | ハッシュ化アルゴリズムにSHA-256が追加され、ブロック暗号にCBCモードのほかGCM、CCMといった認証付き暗号を用いたChpher Suiteが利用可能となった | 2008 | 有効 |
TLS1.3 | データ圧縮の非サポート、forwarde secrecyでない、及び認証付き暗号でない暗号化スイートが廃止された セッションのリネゴシエーションや再開に関する脆弱性のある方式を廃止し、セッションの再開については新方式を採用した ネゴシエーション(ハンドシェイク)シーケンスは大幅に変更され、セキュアかつ高速化にむけた変更がなされた |
2018 | 有効 |
TLS1.2/TLS1.3以外が有効になっていると、Qualys SSL Testではスコアが落ちていきます。
危険性のあるTLS1.1以前は無効にし、TLS1.2/TLS1.3を有効にしていきます。
OpenSSL
WebサーバとしてApacheやOpenSSLを利用する場合、TLS/SSL対応はOpenSSLをツールとして利用します。
CentOS/Ubuntuの公式レポジトリで提供されているOpenSSLのバージョンは以下の通りです。
OS | OpenSSL | 対応プロトコル |
---|---|---|
CentOS7 | 1.0.2系 | TLS 1.2 |
CentOS8 | 1.1.1系 | TLS 1.2 / TLS 1.3 |
Ubuntu18.04LTS | 1.1.0系 | TLS 1.2 |
Ubuntu20.04LTS | 1.1.1系 | TLS 1.3 |
CentOS7やUbuntu18.04LTSを利用TLS1.3に対応する場合、OpenSSL 1.1.1系をソースコードからコンパイルする、もしくは非公式パッケージを利用すれば対応可能です。
しかし、各種パッケージの依存関係が多数存在することが多いため、OS標準パッケージのOpenSSLは残したうえで別途インストールし、OpenSSL1.1.1を利用したいアプリケーション(ApacheやNGINXなど)のみOpenSSL1.1.1を利用するよう導入しなおします。
こちらは、導入手法や環境により手順は多岐にわたるため詳細は割愛します。
各Webサーバアプリケーションでのプロトコル設定方法を記載します。
Ubuntu20.04LTS8の標準パッケージを利用した際の例を記載しますが、その他の環境の際は設定ファイルの位置などは読み替えをお願いします。
OpenSSLの対応Cipher確認方法
OpenSSLコマンドで対応Cipherの確認を行います
# openssl ciphers -v 'ECDH+AESGCM !aNULL !eNULL !SSLv2 !SSLv3 !CBC'
TLS_AES_256_GCM_SHA384 TLSv1.3 Kx=any Au=any Enc=AESGCM(256) Mac=AEAD
TLS_CHACHA20_POLY1305_SHA256 TLSv1.3 Kx=any Au=any Enc=CHACHA20/POLY1305(256) Mac=AEAD
TLS_AES_128_GCM_SHA256 TLSv1.3 Kx=any Au=any Enc=AESGCM(128) Mac=AEAD
ECDHE-ECDSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(256) Mac=AEAD
ECDHE-RSA-AES256-GCM-SHA384 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD
ECDHE-ECDSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH Au=ECDSA Enc=AESGCM(128) Mac=AEAD
ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(128) Mac=AEAD
上記のCipherリストは私の環境でのアウトプットです。各Webサーバに設定する前に確認ください。
NGINXでのプロトコル設定例(TLS1.2/TLS1.3)
Ubuntu20.04LTSの場合
SSLの設定は完了している前提です。まだの方は連載第4回を参照ください。
/etc/nginx/nginx.confを修正
ssl_protocols TLSv1.2 TLSv1.3; #明示的にTLS1.2/1.3のみを有効化
ssl_pref_server_ciphers on;
ssl_ciphers 'ECDH+AESGCM !aNULL !eNULL !SSLv2 !SSLv3 !CBC';
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_ciphersではTLS1.2のCipherしか設定できません
nginx 1.18ではTLS1.3のCipher指定NGINX側ではできず、openssl側で設定が必要ですが、Ubuntu20.04LTSでは個別設定は不要です。
Apache2でのプロトコル設定(TLS1.2/TLS1.3)
Ubuntu20.04LTSの場合
SSLの設定が完了している前提です。
/etc/apache2/sites-enabled以下の該当するVirtul Host設定ファイルを修正します
単独ホストでしたら、/etc/apache2/sites-enabled/default-ssl.conf
SSLProtocol -ALL +TLSv1.2 +TLSv1.3
SSLCipherSuite 'ECDH+AESGCM !aNULL !eNULL !SSLv2 !SSLv3 !CBC'
SSLCipherSuite TLSv1.3 TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384
SSLHonorCipherOrder On
ApacheではTLS1.3に関してはCipherSuiteを個別で定義を記載します
設定後の確認
設定完了後はQualy SSL Testをかけても良いですが、opensslコマンドでも簡単に確認が可能です。
# openssl s_client -tls1_2 -connect www.hoge.com:443
# openssl s_client -tls1_3 -connect www.hoge.com:443
# openssl s_client -tls1_3 -ciphersuites 'TLS_AES_256_GCM_SHA384' -connect www.hoge.com:443
1行目はTLS1.2での接続確認
2行目はTLS1.3での接続確認
3行目はTLS1.3で、且つCipherCuitesを'TLS_AES_256_GCM_SHA384'での接続確認です
接続に成功すると、アウトプット途中に接続したTLSバージョンやCipher情報などが記載されます
(省略)---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
(省略)
Qualy SSL Testでの確認
構成変更後に再度確認してみます
対応プロトコルやCipher Suiteが想定通りであればOKです。
TLS1.1以前のプロトコルに対応していたり、Forward Secrecyに対応していないCipher Suitesに対応しているとINSECURE、WEAKと記載され、点数が下がります。
ここまで対応すると、テスト大項目のProtocol Supportは100点にすることが可能です。
今回はここまでとします。