読者です 読者をやめる 読者になる 読者になる

Mozilla Security Blog 日本語版

Mozilla Security Blog を日本語に翻訳(非公式)

【翻訳】現実の Web に向けた CSP

この記事は、2014 年 10 月 4 日付で Mozilla Security Blog に投稿された CSP for the web we have(筆者: Mark Goodwin)の翻訳です。この翻訳は公式なものではありません。詳しくはこちらをご覧ください。


イントロダクション

Content Security Policy (CSP) は、クロスサイトスクリプティングXSS)を防ぐセーフティネットに適したものです。実際、CSP はとても良く作られており、新しい Web サイトの構築時には CSP をぜひ導入してほしいと思います。

CSP を導入するとデフォルトの制約がいくつか適用されるため、既存の Web サイトに CSP を導入するのは難しい場合があります。また、このような制約を考慮せずにコードが書かれていた場合でも、導入には労力が必要となってしまいます。これらの問題に対する回避策は確かに存在しますが、ポリシーを適用して得られる利益が回避策によって損なわれてしまい、本末転倒になりかねません。とりわけ、インラインスクリプトには注意が必要です。インラインスクリプトはよく使われていますが、もしポリシーでそれを許可してしまうと、もはや CSP の主な利益を享受することはできません。これまで CSP を効果的に利用するには、コードを書き直して既存のインラインスクリプト・スタイルを削除するしかありませんでした。

CSP を既存の Web サイトに適用する労力に最初は驚くかもしれませんが、その労力に見合うほどの利益をセキュリティに得ることができます。幸いにも、CSP 2 では既存サイトへの導入が容易になりました。

CSP 2 の機能

CSP 2 では hash-source と nonce-source という、本当に便利な機能が提供されています。これらの機能を用いると、コンテンツを差し込む隙を攻撃者に与えることなく、インラインのスクリプト・スタイルを使用できるようになります。

それではまず nonce-source の動作を確認してみましょう。

nonce-source を用いた CSP は次のような形をとります。

content-security-policy: default-src 'self'; script-src 'nonce-2726c7f26c'

そして対応するドキュメントには以下の script 要素が含まれています。

<script nonce="2726c7f26c">
alert(123);
</script>

ここで注意すべきことが 2 つあります。1 つ目はレスポンスごとに nonce の値を変えることが重要だということ(先程の例では値が変わりません!)、2 つ目は nonce に対する予測困難性が重要だということです。

nonce は予測できない方法で変更されるため、攻撃者はどの値を nonce に入れればよいか分かりません。そのため、正しい nonce を持った script (style) 要素だけを許可することができ、コンテンツが差し込まれていないことを保障できるのです。

さて hash-source はどうでしょうか?先程と同様に、ドキュメント内の script 要素や style 要素が、CSP に指定された source と一貫性を持っていることが保障されます。しかし、動作の仕組みは異なります。hash-source の場合はドキュメント内の script 要素に属性値を指定せずに、許可したい script 要素のハッシュ値を計算し、その値を CSP の中に指定します。

従って次のような script 要素の場合、

<script>
alert(123);
</script>

hash-source を用いた CSP は次のような形をとります。

content-security-policy: script-src 'sha256-cLuU6nVzrYJlo7rUa6TMmz3nylPFrPQrEUpOHllb5ic='

すぐ分かるように、ドキュメントに含めたいスクリプト・スタイルのそれぞれについて hash-source を追加する必要があります。

どちらを使うべきか(そして使うタイミング)

ここで、なぜ 2 つの仕組みがあるのか(インラインのスクリプト・スタイルを許可するに際して、どのような場合を意図して設計されているのか)疑問に思うかもしれません。どちらを使えばよいのか悩むかもしれません。実際、これらのテクニックはインラインスクリプトを取り除くことができないケースのみを意図しているため、どんな場合でもこの仕組みを使おうとするのは避けるべきです。

nonce-source はシンプルなため、ほとんどの場合で nonce-source のほうが便利でしょう。インライン要素が数多く存在する場合でも、ポリシーに追加する source は 1 つだけで十分です。反対に欠点としては、nonce は一度だけしか使ってはいけないため、ページがロードされるたびに新しいヘッダ(と新しいドキュメント)を生成する必要があります。従って、動的に生成されるページに nonce-source は適していますが、静的なコンテンツには全く適していません。

hash-source はより複雑です。許可したいすべての要素ごとにハッシュ値を計算する必要があり… とはいえ、ハッシュ値は攻撃者に知られても問題ないため、毎回 CSP と script 要素に変更を加える必要がありません。従って、hash-source は静的なコンテンツを保護するのに役立つ仕組みといえます。

利用上の注意

これらの機能を動的に生成されたコンテンツに用いる際は気を付けてください。なぜなら、nonce 属性を設定した(または hash-source を計算する元となった)要素内に攻撃者がコンテンツを差し込めた場合、攻撃者はどのような制限も回避できてしまうからです。

機能上の制約

CSP によるインラインスクリプトの制限は、スクリプトを値にとる属性(DOM Level 0 イベントハンドラで通常用いられる onclick など)も含まれ、hash-source と nonce-source はこれらに対応できません。現在の CSP では属性値のスクリプトにディレクティブを適用できませんが、今後の動向に注目しましょう!