玄関の鍵を「合鍵」だらけにしていませんか? CSPで実現する最強の侵入対策
こんにちは。セキュリティの世界で泥沼のようなインシデント対応を何年も続けてきたエンジニアです。
今日は、皆さんのWebサイトという「家」を守るための、非常に強力で、かつ少しだけコツがいる「CSP(Content Security Policy)」という仕組みについてお話しします。
「インラインスクリプト? nonce? なんだか難しそう…」と思うかもしれませんね。でも大丈夫。身近な防犯に例えながら、一歩ずつ紐解いていきましょう。
—
1. そもそも「インラインスクリプト」って何が怖いの?
WebサイトのHTMLの中に、直接のようにコードを書き込むことを「インラインスクリプト」と呼びます。
これ、泥棒(攻撃者)にとっては「鍵のかかっていない窓」そのものです。
もしあなたのサイトに「入力フォーム」があって、悪意ある人がそこにJavaScriptを紛れ込ませたとします。サイトがその入力を「あ、これもコードの一部なんだね」とそのまま実行してしまったらどうなるでしょう? お客さんのブラウザで勝手に怪しい操作が行われ、個人情報が盗まれてしまうかもしれません。これが「クロスサイトスクリプティング(XSS)」という攻撃です。
2. CSP(Content Security Policy)という「最強の門番」
CSPは、ブラウザに対して「このサイトで実行していいのは、ここから来たスクリプトだけだよ!」と命令するためのヘッダー(Webサイトからの手紙のようなもの)です。
しかし、古いやり方で全部を禁止すると、サイトが動かなくなってしまいますよね。そこで登場するのが「nonce(ナンス)」と「hash(ハッシュ)」です。
—
3. 「nonce」は究極の「使い捨て招待状」
nonce(number used onceの略)は、その名の通り「1回限りの使い捨て招待状」です。
1. サーバーがページを表示するたびに、ランダムな文字列(招待状)を生成する。
2. のように、許可したいスクリプトにだけその招待状を持たせる。
3. ブラウザは「おっ、このスクリプトには正しい招待状があるな。実行してOK!」と判断する。
攻撃者が勝手にスクリプトを埋め込もうとしても、彼らはそのページを表示するたびに変わる「正しい招待状」を知り得ないので、ブラウザは「招待状がないから実行しないよ!」と門前払いしてくれるわけです。
実装イメージ(HTTPレスポンスヘッダー)
サーバー側で生成したランダム値をヘッダーに含めます
Content-Security-Policy: script-src ‘nonce-EDNnf03nceIOfn39fn3e9h3sdf’ ‘strict-dynamic’;
HTML側での利用例
—
4. 「hash」は「指名手配書」
一方、hashは「このコードの内容はこれです」という証明書です。
スクリプトの中身を計算(ハッシュ化)して、その結果をCSPヘッダーに書いておきます。「この内容と完全に一致するコードだけ実行していいよ」という、極めて厳しいルールです。
中身が1文字でも書き換えられたら、ハッシュ値が変わってしまうため、泥棒がこっそりコードを書き換えることは不可能です。
設定のヒント
中身をSHA-256という手法で計算した値を登録します
Content-Security-Policy: script-src ‘sha256-n66…(中略)…w=’ ;
—
5. 現場のエンジニアとしてのアドバイス
「全部をハッシュ化するのは管理が大変そう…」と感じたあなた、その直感は正しいです。
実務では、「基本はnonceを使い、どうしても動的に変更できない共通のスクリプトにはhashを使う」という使い分けが、運用の現場では最もバランスが良いです。
最後に一つだけ、覚えておいてほしいことがあります。
セキュリティ対策は「一度やって終わり」ではありません。
CSPを導入する際は、いきなり厳しく制限をかけるのではなく、まずは Content-Security-Policy-Report-Only という「違反を報告するだけ」のモードで運用し、自分のサイトが正しく動いているかログをチェックすることから始めてみてください。
いきなり完璧を目指してサイトを壊すより、一つずつ確実に穴を塞いでいく。それが、プロのエンジニアの歩み方です。
あなたのサイトという「家」が、今日も安全であることを願っています!
コメント