Trying out CSP(Content Security Policy)

Trying out CSP(Content Security Policy)

最近以下のスライドを見てCSPの存在を知り、なんだか良さそうだったので自サイトを実験台に触ってみました。

CSP(Content Security Policy)とは

CSPとは、「主にクロスサイトスクリプティング攻撃やデータインジェクション攻撃などを対象とした防御・レポートツール」のようです。

CSPの仕組み

まずサーバ側でcontent-security-policyヘッダを返すように設定します。特別なミドルウェアやツールは要りません。

ヘッダの内容は、ブラウザに対し「サイト内のコンテンツに対するアクセスポリシー」をホワイトリスト形式で羅列したものです。また、使用できるプロトコルもサーバ側から指定することが出来ます。

  • 例えば「全てのコンテンツがhttpsで読み込まれること」といったポリシーが設定できます(このポリシーでmixed contentが検出できそう!)。

するとブラウザがそれらのポリシーを受け取り、従います。

よって、CSPに対応していないブラウザでは無意味ということになります。

やってみる

とりあえず動きを見てみたいので、「自サイトからのコンテンツ以外を全て禁止」してみます。

default-srcディレクティブselfキーワードを使えば良さそう。

Webサーバにh2oを使っているのでヘッダの追加方法は下記を参照。

以下の行をh2o.confに追記します。

header.add: "Content-Security-Policy: default-src 'self'"

configテストします。

sudo /usr/sbin/h2o -t -c /etc/h2o/h2o.conf

reloadして適用。

sudo systemctl reload h2o

curlコマンドでヘッダを確認すると、末尾にcontent-security-policyが追加されました。

  • 設定前
$ curl --head https://blog.lorentzca.me/
HTTP/1.1 200 OK
...
vary: Accept-Encoding
  • 設定後
$ curl --head https://blog.lorentzca.me/
HTTP/1.1 200 OK
...
vary: Accept-Encoding
content-security-policy: default-src 'self'

さて、これで埋め込んでいるiframeやGoogleアナリティクスなどのトラッキングコード、disqusなど外部のjsで動いているものが全て禁止されたはずです。

Chromeからアクセスして確認してみます。

  • 設定前。

  • 設定後。disqusの霊圧が...消えた...?

Yay!

今後やりたいこと

ちゃんと適切な設定を考えてみる。

レポーティング機能を使ってみる(Google BigQueryに送るとか)。

mackerelと連携とかやってみる(Mixed Content数メタデータに記録とかアラート出すとか...)。

感想

CSP強い。

設定方法がヘッダを入れるだけ、というのが簡単で良いですね。

ただ、ポリシーの設定がホワイトリスト形式なので、そのサイトでどれくらいのコンテンツが読み込まれているかを完全に把握する必要がありそう。

既存のサイトに組み込む際には慎重にやらないとヤバそうですね...。実際に弾かずレポートだけ吐く設定もあるっぽい(selinux感)のでそれを使うと良さそうです。

参考リンク

W3Cのドキュメント。

Mozillaの解説サイト。

disqusとかaddthisを使ってる場合はホワイトリストの作成がめんどくさそう。

事例。