【入門編】Content-Security-Policy (CSP) の設計と厳格なポリシー適用 – アプリケーションセキュリティ & 安全な開発防御ガイド

そのWebサイト、大丈夫? 新米担当者さんが知っておきたい「Content Security Policy (CSP)」で、見えない攻撃からお客さんを守る方法

やあ、みんな! サイバーセキュリティの世界へようこそ。君たちがこれから触れるWebサイトやアプリケーションは、まるで「お店」みたいなものなんだ。お客さん(ユーザー)が安心して商品(情報)を選べるように、お店の中を綺麗に整頓して、怪しい人が入ってこないように見張る必要がある。

でも、最近の「泥棒」は、ただ窓を割って入ってくるような原始的な方法だけじゃない。巧妙な手口で、お客さんになりすまして、お店のシステムに忍び込もうとするんだ。そんな現代の泥棒が狙う「隙」の一つが、クロスサイトスクリプティング(XSS)と呼ばれる攻撃なんだ。

「XSS? なんだか難しそう…」って思った? 大丈夫、大丈夫。今日のブログでは、このXSS攻撃から君たちの「お店」を守るための強力な「鍵」となるContent Security Policy(CSP)について、家づくりの話に例えながら、とことん優しく解説していくよ。新人のIT担当者さんや、セキュリティに初めて触れる開発者さん、みんなで一緒に一歩ずつ対策を学んでいこう!

1. 「XSS攻撃」って、一体どんな泥棒なんだ? ~家の窓から忍び込む巧妙な手口~

まず、CSPの話に入る前に、CSPが守ってくれる「XSS攻撃」について、身近な例で理解を深めよう。

想像してみてほしい。君が経営するお店(Webサイト)に、お客さんがやってきたとする。そのお客さんは、お店の掲示板(コメント欄や検索窓など)にメッセージを書き込める。本来なら、そのメッセージは「〇〇さん、こんにちは!」みたいな普通の言葉であるはずだ。

ところが、悪意のある泥棒(攻撃者)は、その掲示板に「ちょっとした『仕掛け』の入ったメッセージ」を書き込むんだ。例えば、こんな感じ。

攻撃者の書き込み例:

「こんにちは! このお店、素敵ですね! あ、そうそう、こんな面白いコード(JavaScript)もあるんですよ! 👇」

そして、その「仕掛け」というのが、実は「他の場所から怪しいコードを勝手に実行させるための命令」なんだ。
君のお店(Webサイト)が、その「仕掛け」をそのまま表示してしまうと、どうなるか?

お店のお客さん(他のユーザー)が、その掲示板を見たときに、泥棒が仕掛けた「怪しいコード」が、まるで君のお店から許可されたかのように、勝手に実行されてしまうんだ!

これは、まるで泥棒が君の家の鍵をこじ開けるのではなく、「お客さんになりすまして、勝手に窓を開けて、中に忍び込む」ようなもの。そして、その忍び込んだ泥棒が、君のお客さんの財布(個人情報)を盗んだり、お店のシステムを勝手に操作したりするかもしれないんだ。これがXSS攻撃の怖さなんだ。

XSS攻撃のメカニズム(超シンプル版):

1. 攻撃者が、Webサイトの入力フォーム(コメント欄など)に、悪意のあるJavaScriptコードを仕込んだテキストを投稿する。
2. Webサイト側が、そのテキストをそのまま画面に表示してしまう。
3. 他のユーザーがそのページを閲覧した際に、仕込まれたJavaScriptコードが、そのユーザーのブラウザで勝手に実行されてしまう。
4. 攻撃者は、そのコードを通じて、ユーザーのCookie情報(ログイン状態を保持する情報など)を盗んだり、ユーザーになりすまして不正な操作を行ったりする。

2. 「Content Security Policy (CSP)」って、どんな「監視員」なんだ? ~お店のルールブックを徹底する~

さて、ここで登場するのが、今日の主役、Content Security Policy(CSP)だ。
CSPは、HTTPヘッダーという形でWebサーバーからブラウザに送られる「指示書」のようなもの。この指示書には、「このお店(Webサイト)では、どこから、どんな種類の『もの』だけを許可しますよ」という、非常に詳しいルールが書かれているんだ。

例えるなら、君の「お店」の入り口に立つ、非常に厳格な「監視員」なんだ。
この監視員は、こんな風に君に指示を出す。

  • 「えーっと、今日の『お客さん』(Webページ)を飾るための『飾り付け』(JavaScript、CSS、画像など)は、『このお店の倉庫』(自社サーバー)にあるものだけを使いなさい!
  • 「もし、遠くの『専門業者』(外部CDNなど)から『飾り付け』を持ってくるなら、あらかじめ君(開発者)が『この業者さんなら信用できますよ』ってリストに書いておいた業者さんからだけだよ!
  • 「あと、この『飾り付け』は、『お店の壁』(HTML)に直接書き込むんじゃなくて、ちゃんと『指定された場所』(外部ファイル)に置いてあるものだけを使いなさい!

つまり、CSPは、Webブラウザに対して、「このWebページを表示する際に、どんなリソース(JavaScript、CSS、画像、フォントなど)を、どこから、どのように読み込んで実行して良いか」を、開発者が細かく指示できるようにしてくれるんだ。

これにより、もし万が一、泥棒(攻撃者)が「怪しいコード」を仕込もうとしても、CSPという監視員が「それは禁止された場所からのものだ!」「それは許可されていない種類のものだ!」と、ブラウザに実行させないようにブロックしてくれる。

CSPがもたらす効果:

  • XSS攻撃の緩和: 攻撃者が仕込んだ悪意のあるスクリプトが、許可されていない場所や種類のリソースだと判断され、実行がブロックされる。
  • データ漏洩の防止: 意図しない外部サイトへの情報送信(データ流出)を防ぐ。
  • クリックジャッキング対策: 悪意のあるサイトにiframeで埋め込まれ、ユーザーを騙してボタンをクリックさせるような攻撃を防ぐ。

3. CSPの「鍵」となる設定項目 ~泥棒の侵入経路を一つずつ塞ぐ~

CSPの設定は、HTTPヘッダーに「ディレクティブ」と呼ばれる命令を並べて行う。最初はちょっと難しく感じるかもしれないけど、一つずつ見ていけば大丈夫!

3.1. `default-src`:万能の「守衛さん」

まずは、一番基本的な設定から。
`default-src` は、何も指定されていない他のディレクティブすべてに適用される「デフォルトのルール」を決める、まさに「守衛さん」のような存在だ。

設定例:

Content-Security-Policy: default-src ‘self’;

  • `default-src ‘self’;`
  • `’self’`:これは「自分自身」という意味。つまり、「このWebサイト(自社サーバー)から読み込まれるものだけを許可する」という指示になる。
  • これにより、外部の怪しいサイトから勝手にスクリプトやスタイルシートなどを読み込まれるのを防げるんだ。

3.2. `script-src`:JavaScriptの「出入り口」を管理する

Webサイトの動きを担うJavaScriptは、XSS攻撃の温床になりやすい。だから、ここは特に厳しく管理したいところ。

設定例1:自社サーバーにあるJSファイルのみ許可

Content-Security-Policy: default-src ‘self’; script-src ‘self’;

  • `script-src ‘self’;`
  • これは、`default-src` と同じく、自社サーバーから読み込まれるJavaScriptファイルのみを許可する設定。

設定例2:信頼できる外部CDNも許可する

Content-Security-Policy: default-src ‘self’; script-src ‘self’ https://cdnjs.cloudflare.com;

  • `script-src ‘self’ https://cdnjs.cloudflare.com;`
  • `https://cdnjs.cloudflare.com`:これは、有名なJavaScriptライブラリを配布しているCDN(Contents Delivery Network)の一つ。ここにリストアップされたドメインから読み込むのはOK、という指示になる。
  • 「うちは、あの有名なライブラリを使ってるから、そこから読み込ませたいな」という場合に便利。ただし、登録するドメインは、絶対に信用できるところに限定しようね。

設定例3:インラインスクリプトを禁止する(最も安全!)
Webページに直接書かれているJavaScript(インラインスクリプト)は、攻撃者が悪用しやすい。これを禁止するのが `’unsafe-inline’` を使わない設定だ。

Content-Security-Policy: default-src ‘self’; script-src ‘self’;

  • 注意! この設定だと、HTMLファイル内に `` のように直接書かれたJavaScriptは実行されなくなる。もし、どうしてもインラインスクリプトを使いたい場合は、後述の `nonce` や `hash` を使う必要があるんだ。

3.3. `style-src`:CSSの「装飾ルール」

CSSも、XSS攻撃に悪用されることがある。こちらは `script-src` と同様に管理しよう。

設定例:自社サーバーにあるCSSファイルのみ許可

Content-Security-Policy: default-src ‘self’; script-src ‘self’; style-src ‘self’;

  • `style-src ‘self’;`
  • 自社サーバーから読み込まれるCSSファイルのみを許可する。
  • 注意! こちらも、HTMLファイル内に `

    ` のように直接書かれたCSS(インラインスタイル)は、`’unsafe-inline’` を指定しない限り実行されなくなる。

3.4. `img-src`:画像の「展示ルール」

画像ファイルについても、どこから読み込むかを指定できる。

設定例:自社サーバーと、信頼できる画像CDNのみ許可

Content-Security-Policy: default-src ‘self’; script-src ‘self’; style-src ‘self’; img-src ‘self’ https://example.com/images/;

  • `img-src ‘self’ https://example.com/images/;`
  • 自社サーバーと、`https://example.com/images/` というURLのパスにある画像のみを許可。

3.5. `connect-src`:通信の「行き先」を制限する

Ajaxリクエスト(非同期通信)など、Webページがバックエンドサーバーと通信する際の「行き先」を制限する。

設定例:自社APIのみ許可

Content-Security-Policy: default-src ‘self’; script-src ‘self’; style-src ‘self’; img-src ‘self’; connect-src ‘self’ https://api.example.com;

  • `connect-src ‘self’ https://api.example.com;`
  • 自社サーバーと、`https://api.example.com` というAPIサーバーへの通信のみを許可。

3.6. `frame-src`: iframeの「窓」を管理する

Webページ内に他のWebページを埋め込む `