<CodeLearn/>
セキュリティ レッスン4

HTTPS・CORS

通信の暗号化、TLS/SSL、同一オリジンポリシーを学ぼう

HTTPSとは

HTTPS(HTTP over TLS/SSL)は、HTTP通信を暗号化したプロトコルです。 通信内容が第三者に傍受されたり改ざんされたりすることを防ぎます。 現在のWebでは HTTPS が標準であり、HTTP のサイトはブラウザに「安全でない」と警告されます。

TLS/SSL ハンドシェイクの流れ:

1. クライアント → サーバー: ClientHello
   - 対応する暗号スイートの一覧を送信

2. サーバー → クライアント: ServerHello + 証明書
   - 使用する暗号スイートと SSL 証明書を送信

3. クライアント: 証明書の検証
   - 認証局(CA)の署名が正しいか確認
   - ドメイン名が一致するか確認

4. 鍵交換: セッション鍵の共有
   - 共通鍵暗号のための鍵を安全に共有

5. 暗号化通信の開始
   - 以降のすべての通信は共通鍵で暗号化される

SSL証明書

SSL証明書は、サーバーの身元を証明するデジタル証明書です。 認証局(CA: Certificate Authority)が発行し、ブラウザはこの証明書を検証して 通信相手が本物かどうかを確認します。

DV(Domain Validation)証明書

ドメインの所有権のみ確認。Let's Encrypt で無料取得可能。個人サイトに最適。

OV(Organization Validation)証明書

組織の実在確認を含む。企業サイト向け。

EV(Extended Validation)証明書

最も厳格な審査。金融機関など高い信頼性が必要なサイト向け。

# Let's Encrypt で無料の SSL 証明書を取得(certbot)
sudo certbot --nginx -d example.com -d www.example.com

# 自動更新の設定
sudo certbot renew --dry-run

# Vercel や Netlify などのホスティングサービスでは
# HTTPS が自動的に設定される

同一オリジンポリシー(Same-Origin Policy)

ブラウザのセキュリティ機構で、あるオリジン(プロトコル + ドメイン + ポート)から 読み込まれたスクリプトが、別のオリジンのリソースにアクセスすることを制限します。

// オリジン = プロトコル + ドメイン + ポート
// https://example.com:443

// 同一オリジン(OK)
https://example.com/page1 → https://example.com/page2   // パスが違うだけ

// 異なるオリジン(ブロックされる)
https://example.com → http://example.com      // プロトコルが違う
https://example.com → https://api.example.com  // サブドメインが違う
https://example.com → https://example.com:8080 // ポートが違う

CORS(Cross-Origin Resource Sharing)

CORS は、同一オリジンポリシーの制限を安全に緩和するための仕組みです。 サーバーがHTTPヘッダーで「このオリジンからのアクセスを許可する」と明示します。

// Express での CORS 設定
import cors from "cors";

// 方法1: 特定のオリジンのみ許可(推奨)
app.use(cors({
  origin: "https://myapp.com",
  methods: ["GET", "POST", "PUT", "DELETE"],
  credentials: true, // Cookie を含むリクエストを許可
}));

// 方法2: 複数のオリジンを許可
app.use(cors({
  origin: ["https://myapp.com", "https://admin.myapp.com"],
}));

// 方法3: すべてのオリジンを許可(開発時のみ!本番では非推奨)
app.use(cors({ origin: "*" }));
// CORSレスポンスヘッダー
Access-Control-Allow-Origin: https://myapp.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 86400

// プリフライトリクエスト(OPTIONS)
// ブラウザがPOSTやPUTの前に自動送信して許可を確認する
// Content-Type が application/json の場合なども送信される

SameSite Cookie

SameSite 属性は、Cookie がクロスサイトリクエストで 送信されるかどうかを制御します。CSRF 攻撃の防止に効果的です。

SameSite=Strict

クロスサイトリクエストでは一切 Cookie を送信しない。最も安全だが、外部リンクからのアクセス時にログアウト状態になる。

SameSite=Lax(デフォルト)

トップレベルナビゲーション(リンククリック)では送信するが、POSTリクエスト等では送信しない。バランスが良い。

SameSite=None

クロスサイトでも常に送信。Secure フラグ必須。サードパーティ Cookie に必要。

まとめ

  • HTTPS は TLS/SSL で通信を暗号化し、傍受・改ざんを防ぐ
  • SSL証明書は Let's Encrypt で無料取得でき、多くのホスティングで自動設定される
  • 同一オリジンポリシーは異なるオリジンへのアクセスを制限するブラウザの防御機構
  • CORS はサーバー側で許可するオリジンを明示する仕組み
  • SameSite Cookie で CSRF 攻撃を効果的に防げる