【実務・中級編】 TLS 1.3の強制と古い暗号スイートの無効化(CloudFront/ALB) – 暗号理論・認証基盤 & エンドポイントセキュリティ防御ガイド

TLS 1.3への強制移行:なぜ「古い暗号」を今すぐ抹殺すべきなのか

現場でインシデント対応をしていると、常に痛感させられることがある。それは、攻撃者は「最新の脆弱性」よりも「放置された過去の遺物」を好むという現実だ。

特にTLS 1.2以前、あるいはRSA鍵交換を用いた暗号スイートを有効にしたままのサーバーは、いわば「玄関の鍵をかけ忘れた家」に等しい。なぜ今、我々がTLS 1.3への強制移行と、Perfect Forward Secrecy(PFS)の担保に執着するのか。その「泥臭い理由」と「現場での実装解」を共有しよう。

—

なぜRSA鍵交換は「死んだ」のか?

TLS 1.2以前のRSA鍵交換には、致命的な盲点がある。サーバーの秘密鍵が万が一漏洩した場合、過去に傍受されたすべての通信データを遡って復号できてしまうからだ。これを防ぐのがPFS(前方秘匿性)を保証するECDHE(楕円曲線ディフィー・ヘルマン鍵交換)だ。

さらに、TLS 1.3では、これまでの複雑で脆弱な暗号スイートの組み合わせ(ネゴシエーション)を大幅に簡素化した。攻撃者が「あえて古い弱い暗号を選ばせる」というダウングレード攻撃も、TLS 1.3のプロトコル設計自体によって事実上封じられている。

これを怠ると、MITM(中間者)攻撃により、トラフィックを丸裸にされるリスクを許容し続けることになる。

—

実践:CloudFrontで「堅牢なTLS 1.3」を強制する

AWSを利用しているなら、インフラ層での防御が最もコスト対効果が高い。CloudFrontのカスタムSSL証明書設定において、レガシーな設定を排除する手順を解説する。

CloudFront セキュリティポリシーの設定

CloudFrontの「Security Policy」は、必ず TLSv1.2_2021 以降を選択すること。これにより、TLS 1.1以下の古いプロトコルを即座に無効化し、かつPFSをサポートしない暗号スイートを排除できる。

設定のポイント:

  • Minimum TLS Version: TLSv1.2 (AWSのUI上、TLS 1.3を有効にするには1.2以上を選択する必要がある)
  • Cipher Suites: ECDHE-RSA-AES128-GCM-SHA256 などのPFS対応スイートのみに限定される。

—

Nginxで暗号スイートを鉄壁にする設定

クラウドの前段にNginxを置いている場合や、オンプレミス環境では、設定ファイル(nginx.conf)での明示的な指定が必須だ。

# /etc/nginx/conf.d/ssl.conf

# 古いTLS 1.0/1.1は論外として、TLS 1.3を最優先に定義
ssl_protocols TLSv1.2 TLSv1.3;

# PFS(前方秘匿性)を保証する暗号スイートのみを許可
# RSA鍵交換を排除し、ECDHE(楕円曲線)のみに絞る
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';

# サーバー側の暗号スイート選択を強制(クライアント側の弱い要求を無視する)
ssl_prefer_server_ciphers on;

# セッションチケットの無効化(前方秘匿性を高めるための微調整)
ssl_session_tickets off;

—

開発者が知るべき「アプリ層でのTLS」と注意点

「TLSはインフラ担当の仕事」と考えているなら、それは甘い。アプリケーションがバックエンドAPIと通信する際、古いライブラリを使っていれば、そこが穴になる。

例えば、Pythonの requests やPHPの curl を使う際、OS側の OpenSSL が古いと、強固な設定を施したサーバーへの接続を拒否されることがある。

Pythonでのセキュアなリクエスト例

import requests
from requests.adapters import HTTPAdapter
from urllib3.util.ssl_ import create_urllib3_context

# TLS 1.3を強制し、レガシーな暗号を排除するアダプターを作成
class TLS13Adapter(HTTPAdapter):
    def init_poolmanager(self, *args, **kwargs):
        context = create_urllib3_context(ssl_version=19) # 19はTLS 1.3を指す
        context.set_ciphers('ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256')
        kwargs['ssl_context'] = context
        super().init_poolmanager(*args, **kwargs)

# API通信時にこのセッションを使用する
session = requests.Session()
session.mount('https://api.your-secure-service.com', TLS13Adapter())

—

まとめ:セキュリティは「足し算」ではなく「引き算」

最後に一つだけ伝えておきたい。セキュリティにおいて重要なのは、新しい技術を足すことではない。「必要のない古い機能を削ぎ落とすこと」だ。

TLS 1.3への移行は、単なるバージョンアップではない。これまで通信経路に存在していた「暗号の抜け穴」を物理的に塞ぐ作業だ。

1. 古いTLS(1.0, 1.1)を即座にDisableにする。
2. RSA鍵交換を含む暗号スイートを排除し、ECDHEへ移行する。
3. インフラのCLI/コンソールだけでなく、アプリ側のライブラリも追従させる。

これらを実施し、ssllabs.com 等のツールで「A+」評価が得られる状態を維持してほしい。それが、エンジニアとして信頼を勝ち取るための最低限の作法だ。健闘を祈る。

コメント

タイトルとURLをコピーしました