【実務・中級編】 中間者攻撃(MitM)とSSL/TLSのプロトコルダウングレード – オフェンシブセキュリティ & リバースエンジニアリング防御ガイド

現場の視点:SSL/TLSダウングレード攻撃という「見えない落とし穴」

こんにちは。レッドチームのチーフエンジニアとして、日々システムの脆弱性を叩いていると、「HTTPSで通信しているから安全だ」と盲信している現場がいかに多いかという事実に直面します。

確かにTLSは強力ですが、攻撃者は「プロトコルそのもの」を破るのではなく、「プロトコルを強制的に弱体化させる」という、泥臭い手口を好みます。本日は、MitM(中間者攻撃)とSSL/TLSダウングレードの核心に迫り、明日から使える「実戦的な防御策」を伝授します。

—

1. なぜ「ダウングレード」が成立してしまうのか

SSL/TLSダウングレード攻撃の典型例は、SSLStripに代表される手法です。

攻撃者は、ユーザーがブラウザで http://example.com にアクセスした瞬間、あるいはHTTPSへのリダイレクトが走る前のわずかな隙を突き、通信を傍受します。攻撃者はサーバーとユーザーの間に立ち、「サーバーとはHTTPSで通信しつつ、ユーザーにはHTTPでコンテンツを返す」という悪魔のような振る舞いをします。

ユーザーのブラウザは「今はHTTPだから暗号化は不要だ」と判断し、Cookieや認証情報を含むすべてのトラフィックが、攻撃者のプロキシを通して平文で流れることになります。これが、現代のWebアプリケーションにおける最大の「盲点」です。

—

2. 絶対防御の要:HSTS(HTTP Strict Transport Security)

この攻撃を物理的に無効化する唯一にして最強の武器が HSTS です。これは、Webブラウザに対して「このドメインには、今後一切HTTPでアクセスしてはならない」と強制的に覚え込ませる仕組みです。

NginxでのHSTS設定(推奨)

Nginxの設定ファイル(nginx.confまたは各サイトのコンフィグ)に以下のヘッダーを追加してください。これだけで、初回アクセス以降のダウングレード攻撃は完全に封じられます。

# HSTS設定: 1年間(31536000秒)はHTTPS接続を強制する
# includeSubDomains: サブドメインにも適用
# preload: ブラウザのプリロードリストへの登録を許可(推奨)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

—

3. 防御の二段構え:証明書ピンニング(Certificate Pinning)

HSTSだけでは、もし攻撃者が「正規の認証局(CA)」から不正な証明書を騙し取った場合(中間者攻撃の高度なケース)、防ぎきれないリスクが残ります。ここで登場するのが、特定の証明書のみを信頼させる「ピンニング」です。

JavaScript(Service Worker)によるピンニングの概念

※本来はネイティブアプリで実装されることが多いですが、Webでも厳格な管理が求められます。

// 注意: これは概念コードです。実際のプロダクションでは
// 信頼済み公開鍵のハッシュ値を保持し、通信開始時にチェックを行います。
const EXPECTED_PUBLIC_KEY_HASH = "sha256/AABBCCDD...";

async function verifyConnection(url) {
  const response = await fetch(url);
  const cert = response.headers.get('X-Server-Cert-Hash'); // カスタムヘッダー等で取得

  if (cert !== EXPECTED_PUBLIC_KEY_HASH) {
    throw new Error("セキュリティ警告: 接続先の証明書が信頼済みと一致しません!");
  }
  return true;
}

—

4. セキュアなCookie設計(現場のTips)

通信がHTTPSであっても、Cookieが「平文で送信される」設定になっていれば意味がありません。必ず Secure 属性と HttpOnly 属性を付与してください。

PHPでのCookieセッション設定例

php.ini またはアプリケーション起動時に以下の設定を徹底してください。

<?php
// セッションCookieをセキュアに設定する
session_set_cookie_params([
    'lifetime' => 0,
    'path' => '/',
    'domain' => 'yourdomain.com',
    'secure' => true,      // HTTPS通信のみで送信
    'httponly' => true,    // JavaScriptからのアクセス禁止(XSS対策)
    'samesite' => 'Strict' // CSRF対策
]);

session_start();
?>

—

最後に:エンジニアとしての心構え

「HTTPSを使っているから大丈夫」という考えは、攻撃者からすれば「どうぞ、ダウングレードしてください」と言っているのと同じです。

1. HSTSを全ドメインに適用する。
2. Cookieには必ず Secure / HttpOnly をつける。
3. 常に最新のTLSプロトコル(TLS 1.3)を強制し、古い暗号スイートを無効化する。

これらは、特別なツールや高価なWAFを導入する前に、今すぐエンジニアの裁量で実装できる「最低限の防御線」です。セキュリティは一度設定して終わりではありません。攻撃手法は進化し続けています。我々もまた、昨日よりも強固な実装を追求し続けなければなりません。

現場からは以上です。次のデプロイで、これらの設定が反映されていることを期待しています。

コメント

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