その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ページを埋め込む `
設定例:自社サイトの特定ページと、YouTubeのみ許可
Content-Security-Policy: default-src ‘self’; script-src ‘self’; style-src ‘self’; img-src ‘self’; connect-src ‘self’; frame-src ‘self’ https://www.youtube.com;
- `frame-src ‘self’ https://www.youtube.com;`
- 自社サイトとYouTubeの埋め込みのみ許可。
4. 難易度アップ! 「nonce」と「strict-dynamic」で、さらに厳格に!
さて、ここまでで基本的なCSPの設定を見てきたけど、「インラインスクリプトやインラインスタイルを禁止すると、既存のコードが動かなくなっちゃうよ!」という声が聞こえてきそうだ。安心してください。そんな時のための、さらに賢い「鍵」があるんだ。
4.1. `nonce`:毎回「違う合言葉」で、インラインスクリプトを許可する
`nonce`(ノンス)は、「number used once」(一度だけ使われる数)の略。これは、毎回ランダムに生成される、ユニークな文字列のこと。
CSPで `nonce` を使うと、HTMLファイル内に `