🔒

Zenn問答第3回 「HTTPS」

に公開

Zenn問答とは

「Zenn問答」とは、開発していて「なんとなく使ってるけど、ちゃんと理解してるかな?」という技術について、改めて時間をとって深掘りしてみようという企画です🧘🧘🧘

はじめに

普段Webアプリケーションを開発していると、HTTPSが当たり前のように使われています。「HTTPSは暗号化されているから安全」みたいな理解はあるものの、実際に何がどう暗号化されているのか、などの理解が曖昧だったので深掘りしてみました。

そもそもHTTPとRESTとは

まず基本的な概念から整理します。HTTPとRESTはよく混同されがちですが、実は全く異なる概念です。

HTTPとは

HTTP(HyperText Transfer Protocol)は、WebブラウザとWebサーバー間でデータをやり取りするための通信プロトコルです。

HTTPの特徴

  • リクエスト・レスポンス形式の通信
  • ステートレス(状態を保持しない)
  • テキストベースのプロトコル
  • ポート80(HTTP)、443(HTTPS)を使用

RESTとは

REST(Representational State Transfer)は、Web APIを設計するためのアーキテクチャスタイルです。HTTPプロトコルを使って実装されることが多いですが、HTTPとは別の概念です。

RESTの設計原則:

  1. ステートレス: サーバーはクライアントの状態を保持しない
  2. 統一インターフェース: リソースはURLで識別し、HTTPメソッドで操作
  3. 階層化システム: プロキシやゲートウェイを透過的に配置可能
  4. キャッシュ可能: レスポンスにキャッシュ情報を含める
// RESTful APIの例
GET    /api/users     // ユーザー一覧取得
POST   /api/users     // ユーザー作成
GET    /api/users/123 // 特定ユーザー取得
PUT    /api/users/123 // ユーザー更新
DELETE /api/users/123 // ユーザー削除

最近はアプリケーションも複雑化してきており、第1回のZenn問答で深掘りしたcookieなどの技術を用いることが多いため、ステートレスは守られていないことが多いように思います。

違いをまとめると

項目 HTTP REST
性質 通信プロトコル アーキテクチャスタイル
役割 データ転送の方法を定義 API設計の指針を提供
関係 RESTful APIの実装に使用される HTTPプロトコルを利用して実装される

つまり、「HTTPプロトコルを使ってRESTful APIを実装する」という関係性になります。

web技術が大きく発展してhttpがメジャーになりすぎた結果、不適切な用途でも使われているのではないかなと思います。特にステートフルなものを扱うときはhttpでやらなくていいのに、、という場合も多いように思います。

HTTPSは何をどう暗号化しているのか?

次に、HTTPSの暗号化について詳しく見ていきましょう。HTTPS(HTTP Secure)は、HTTPにSSL/TLSによる暗号化を追加したプロトコルです。

SSL/TLSの基本的な仕組み

HTTPS通信は以下の手順で暗号化された通信を確立します。
認証局や鍵の理解もきちんと理解できているかは怪しいですが、なんとなく理解します。

暗号化される項目と暗号化されない項目

HTTPSで暗号化される部分と暗号化されない部分を整理してみます。

🔒 暗号化される部分

  1. HTTPリクエスト・レスポンスのボディ

    POST /api/login HTTP/1.1
    Host: example.com
    Content-Type: application/json
    
    {"username": "user123", "password": "secret123"}  ← 暗号化される
    
  2. HTTPヘッダー

    Authorization: Bearer eyJhbGciOiJIUzI1NiIs...  ← 暗号化される
    Cookie: session_id=abc123...                  ← 暗号化される
    User-Agent: Mozilla/5.0...                    ← 暗号化される
    
  3. URL のパスとクエリパラメータ

    GET /users/123?token=secret&page=2  ← /users/123?token=secret&page=2 が暗号化される
    

👁️ 暗号化されない部分

  1. 宛先IPアドレス

    • ネットワークルーティングに必要なため暗号化不可
    • どのサーバーと通信しているかは傍受可能
  2. ホスト名(SNI: Server Name Indication)

    example.com ← これは暗号化されない(TLS 1.3以前)
    
  3. 通信のタイミングと頻度

    • いつ、どのくらいの頻度で通信しているか
    • データサイズも推測可能
  4. DNS クエリ

    example.com のIPアドレスを問い合わせ ← 平文で送信される
    

HTTPSであれば盗聴されても問題ないのか?

ここまでHTTPSの仕組みを見てきましたが、「HTTPS = 完全に安全」ではありません。HTTPSでも残る脆弱性やリスクについてみてみます。

HTTPSでも防げない攻撃

1. 中間者攻撃(Man-in-the-Middle Attack)

証明書の検証を適切に行わない場合、攻撃者が偽の証明書を使って通信を傍受する可能性があります。

2. トラフィック解析攻撃

暗号化されていても、通信パターンから情報を推測される場合があります。

// 攻撃者が観察できるパターン
const trafficAnalysis = {
  // 通信タイミングパターン
  loginPattern: {
    time: "09:00-09:05",
    frequency: "5回/分",
    dataSize: "1.2KB",
    inference: "ログイン試行の可能性"
  },
  
  // データサイズパターン  
  downloadPattern: {
    time: "14:30",
    dataSize: "50MB",
    duration: "30秒",
    inference: "大容量ファイルダウンロードの可能性"
  },
  
  // アクセス先パターン
  sitePattern: {
    sites: ["medical-site.com", "pharmacy.com", "insurance.com"],
    inference: "健康に関する情報を調べている可能性"
  }
};

アプリケーションレベルでの対策

HTTPSの限界を補うために、アプリケーション側でできる対策を見てみましょう:

1. Certificate Pinning(証明書固定化)

あらかじめ期待される証明書や公開鍵のハッシュ値を固定し、通信時に証明書が変更されていないかを検証する仕組みです。これにより、攻撃者が偽の証明書を使った中間者攻撃を防ぐことができます。

// SSL証明書の固定化
const expectedCertFingerprint = "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";

fetch('https://api.example.com/data', {
  // モダンブラウザでの実装例
  headers: {
    'Public-Key-Pins': `pin-sha256="${expectedCertFingerprint}"; max-age=2592000`
  }
}).catch(error => {
  if (error.code === 'CERT_PINNING_FAILURE') {
    console.error('証明書が期待されるものと異なります');
    // セキュリティ警告を表示
  }
});

2. Perfect Forward Secrecy(前方秘匿性)

通信ごとに一時的な暗号化鍵(セッション鍵)を生成し、通信終了後は破棄する仕組みです。これにより、仮にサーバーの秘密鍵が漏洩しても、過去の通信内容は復号できません。

// サーバー設定での PFS 有効化例(概念的)
const tlsConfig = {
  cipherSuites: [
    'ECDHE-RSA-AES256-GCM-SHA384',  // ECDHE = 前方秘匿性あり
    'ECDHE-RSA-AES128-GCM-SHA256',
    // 'RSA-AES256-GCM-SHA384'  // RSA = 前方秘匿性なし(避ける)
  ],
  protocols: ['TLSv1.3', 'TLSv1.2']
};

3. Content Security Policy(コンテンツセキュリティポリシー)

Webページでどのリソース(スクリプト、スタイル、画像など)をどこから読み込むかを制御するセキュリティ機能です。HTTPSの強制やXSS攻撃の防止に効果的です。

<!-- HTTPS通信の強制 -->
<meta http-equiv="Content-Security-Policy" 
      content="upgrade-insecure-requests; 
               default-src https: 'self'; 
               script-src https: 'self' 'unsafe-inline';">

実際の脅威事例

事例: 公共Wi-Fiでの偽証明書攻撃

事件の概要:
空港、カフェ、ホテルなどの公共Wi-Fiにおいて、攻撃者が「WiFi Pineapple」などの専用機器を使って偽のアクセスポイントを設置し、利用者のHTTPS通信を傍受する攻撃が多発しています。

攻撃の手法:

  • 攻撃者が正規のWi-Fiと同名の偽のアクセスポイントを設置
  • ユーザーが偽のWi-Fiに接続すると、攻撃者が中間者として位置
  • 攻撃者が偽のSSL証明書を提示(多くのユーザーは警告を無視)
  • HTTPS通信を復号化してログイン情報やクレジットカード情報を盗取

実際の被害事例:

  • 2019年、ロンドンのカフェチェーンで大規模な攻撃が発生
  • 数千人の顧客のオンラインバンキング情報が漏洩
  • 2020年、国際空港での攻撃により出張者のビジネス機密が流出

特に狙われやすい場所:

  • 空港・駅などの交通機関
  • カフェ・レストランなどの飲食店
  • ホテル・会議場
  • 大学・図書館などの公共施設

対策:

  • VPN使用による通信経路の暗号化
  • 証明書エラーが出た場合は絶対に接続を続行しない
  • 公共Wi-Fi使用時は重要な操作(オンラインバンキング等)を避ける
  • Certificate Pinningに対応したアプリの使用

公共Wi-Fiでの通信傍受リスクについて

ここで補足として、暗号化されていない公共Wi-Fiにおける通信傍受のリスクについて説明します。

暗号化されていないWi-Fiでの傍受の仕組み

基本的な構造:

公共Wi-Fiでは、同じネットワーク上のすべてのデバイスが同じ「電波」を共有しています。攻撃者は自分のネットワークカードを「プロミスキャスモード」に設定することで、本来は自分宛てではないパケットもすべて受信・解析できるようになります。

プロミスキャスモードとは?

通常、ネットワークカードは「自分宛て」のパケットのみを処理し、他のデバイス宛てのパケットは無視します。しかし、プロミスキャスモード(promiscuous mode)に設定すると、ネットワーク上を流れるすべてのパケットを受信・処理するようになります。

通常モード(正常な状態):

プロミスキャスモード(攻撃者の状態):

これは本来、ネットワーク管理者がトラブルシューティングやセキュリティ監視のために使用する機能ですが、悪意のある攻撃者によって通信傍受に悪用される可能性があります。

実際に傍受される情報

HTTP通信の場合(完全に危険)

暗号化されていないHTTPサイトへのアクセスでは、以下の情報が完全に平文で傍受可能です:

  • ログイン情報(ユーザー名・パスワード)
  • フォーム送信データ
  • Cookieやセッション情報
  • 閲覧しているサイトのURL
  • 個人情報や機密データ

HTTPS通信の場合(部分的にリスクあり)

HTTPS通信でも、以下のメタデータは傍受可能です:

  • 接続先のホスト名(SNI情報)
  • 接続先のIPアドレス
  • 通信のタイミングと頻度
  • データサイズ
  • DNS クエリ内容

ただし、実際の通信内容(パスワード、フォームデータなど)は暗号化されているため読み取れません。

傍受の手法

技術的には以下のようなツールで簡単に傍受が可能です:

一般的なパケットキャプチャツール:

  • Wireshark(最も有名なパケット解析ツール)
  • tcpdump(コマンドライン版)
  • Ettercap(中間者攻撃用ツール)

攻撃者の行動例:

  1. 公共Wi-Fiに接続
  2. ネットワークカードをモニターモードに設定
  3. パケットキャプチャツールでトラフィックを記録
  4. 後からゆっくりとデータを解析

実用的な対策

基本的な対策

  1. VPNの使用: すべての通信を追加で暗号化
  2. HTTPSサイトのみ利用: 平文通信を完全に避ける
  3. 重要な操作の回避: 公共Wi-Fiではオンラインバンキングや重要な個人情報の入力を避ける

行動面での対策

  1. 証明書エラーを絶対に無視しない: 証明書警告が出た場合は接続を中止
  2. 信頼できるWi-Fiのみ使用: 店舗スタッフに正式なWi-Fi名を確認
  3. 同名のWi-Fiが複数ある場合は注意: Evil Twin攻撃の可能性
  4. スマートフォンのテザリング活用: 可能な限り自分のモバイル回線を使用

この技術的背景を理解することで、なぜVPNやHTTPSが重要なのか、そして公共Wi-Fiでの適切な行動指針を理解できるはずです。

まとめ

HTTPSは重要なセキュリティ技術ですが、意外と仕組みを知らずに使っており色々知ることですっきりしました。世の中も徐々にセキュリティ対策が進歩してきてhttpのサイトは見かけなくなってきましたが、特に個人情報を入力するhttpのサイトがあったら要注意な理由もはっきりと理解できました。

この記事を読んでくださった方の学びの一助になれば幸いです、最後まで読んでいただきありがとうございました!

GitHubで編集を提案

Discussion