泥棒に「出口」を教えない!CSPのconnect-srcでデータ流出を封じ込める方法
こんにちは。セキュリティの世界で長く戦っていると、「完璧な防御」なんて存在しないという事実にぶち当たります。どんなに強固な金庫(データベース)を作っても、そこから誰かが「勝手に持ち出すルート」を見つけてしまったら、すべて台無しですよね。
今日は、Web開発を始めたばかりの方に向けて、「泥棒が盗んだ情報を外へ送るルート」を遮断する、非常に強力な武器「CSPのconnect-src」についてお話しします。
—
「泥棒はどこから持ち出すのか?」を想像する
まず、少し想像してみてください。あなたが大切なお宝(ユーザーの個人情報やセッション情報)を保管する家(Webアプリケーション)を持っているとします。
もし、泥棒があなたの家に侵入して、お宝を見つけたとしましょう。泥棒は、それをどうやって外に持ち出すでしょうか? 玄関(ブラウザ)を通って、堂々と外の仲間の車(攻撃者のサーバー)まで運ぶはずです。
Webアプリケーションにおいて、この「盗んだ情報を外部サーバーへ送信する手段」としてよく使われるのが、JavaScriptの fetch や XMLHttpRequest (XHR) といった通信機能です。
攻撃者は、あなたのサイトに「悪意のあるスクリプト」をこっそり仕込みます。そのスクリプトは、ユーザーがブラウザでページを開いた瞬間に動き出し、裏でこっそりと攻撃者のサーバーへデータを送信してしまいます。これが「データ流出」の典型的なメカニズムです。
—
CSP(Content Security Policy)という「防犯警報装置」
ここで登場するのが、CSP(Content Security Policy)です。これは、Webサーバーがブラウザに対して、「うちのサイトでは、こういう通信しか許可しないよ!」と命令を下すための防犯ルールブックです。
このルールブックの中にある connect-src という項目は、まさに「通信の出口管理」を担当する警備員です。
connect-src がやっていること
connect-src を設定すると、ブラウザは「JavaScriptからの通信先(APIサーバーなど)は、ここに書かれているドメインだけにしてね」と厳格に守るようになります。
もし、リストに載っていない「攻撃者の怪しいサーバー」へデータを送ろうとしても、ブラウザが「おい、その行き先は許可されていないぞ!」と強制的に通信を遮断してくれます。これなら、たとえスクリプトが埋め込まれても、泥棒は「お宝を外へ運び出す手段」を失うわけです。
—
実践!CSPの設定を書いてみよう
設定はとてもシンプルです。Webサーバーのレスポンスヘッダーに、以下のような命令を付け加えるだけです。
HTTPレスポンスヘッダーの例
Content-Security-Policy: default-src ‘self’; connect-src ‘self’ https://api.trusted-service.com;
設定の意味を噛み砕くと…
default-src 'self': 「基本的には、自分自身のサイト内のものしか信用しないよ」という大原則です。connect-src 'self' https://api.trusted-service.com:'self':自分自身のサイトへのAPI通信は許可します。https://api.trusted-service.com:信頼できる外部APIサーバーへの通信も許可します。- それ以外:上記に含まれないサーバーへの送信は、ブラウザが即座にブロックします。
—
「まずは知ることから」がセキュリティの第一歩
「でも、運用中にAPIの通信先が増えたらどうするの?」と心配になるかもしれませんね。大丈夫です。最初は Content-Security-Policy-Report-Only というヘッダーを使って、「ブロックはしないけど、違反があったら教えてね」というテストモードで運用することもできます。
セキュリティは、最初から完璧を目指す必要はありません。まずは「自分のサイトがどこにデータを送っているのか」を把握し、少しずつ「怪しい通信先」を制限していく。この一歩が、あなたのサイトを守る最強の防壁になります。
もし、新しく開発した機能で「あれ?通信がブロックされた?」となったら、それはCSPがあなたを守ろうとしている証拠です。その時は、ログを確認して「この通信先は許可していいものか?」を冷静に判断しましょう。
泥棒に「出口」を教えない。この鉄則を守るだけで、あなたのサービスは格段に安全になります。一歩ずつ、着実に安全な開発環境を築いていきましょうね!
コメント