記憶に残ったことを忘れないために色々メモとしてのこしていきます
Content Security Policy (CSP) について
背景
外部ライブラリを特定のサイトに組み込むとき、リクエストが飛んでいないことがあった。コンソールをみると "Content Security Policy"なるエラーがでていた。実は以前"Content Security Policy"関連のレスポンス表示を見たことがあったのだけど、あまり調べずにそのまま放置していた。いい機会なので今回CSP (Content Security Policy) について少し調べてみた。
CSPとは?
コンテンツセキュリティポリシー (CSP) は、クロスサイトスクリプティング (Cross-site-scripting) やデータインジェクション攻撃などのような、特定の種類の攻撃を検知し、影響を軽減するために追加できるセキュリティレイヤーです。これらの攻撃はデータの窃取からサイトの改ざん、マルウェアの拡散に至るまで、様々な目的に用いられます。
引用: https://developer.mozilla.org/ja/docs/Web/HTTP/CSP
つまり、特定のサイトに下記のような制約を加えることで、CSSやJavaScriptの実行方法とリソースの読み込み先をホワイトリスト的に管理することができるようだ。
- 外部リソース (JavaScript, CSS, 画像など) の読み込み
- inlineスクリプトの実行
- evalの実行
- inlineスタイルの適用
仕組み
1. ヘッダーの指定によるリクエストの制御
2. 設定方法
HTTP Response Headerに下記を追加するポリシー
には、サイトに適用するCSPディレクティブ (CSPの内容を指定するための要素) から構成される文字列を指定する
Content-Security-Policy: ポリシー
CSP HTTP Header
Content-Security-Policy: ディレクティブ名 ソース; ディレクティブ名 ソース;
;
で区切られている点がポイント。
CSP HTTP Headerの記述例
Content-Security-Policy: img-src 'self' https://example.com
上記の場合は、画像リソース用ディレクティブ img-src
に対しての設定例。サイト自身のオリジン self
と https://example.com
からの画像かfaviconのみが有効となり、それ以外のオリジンからは、コンテンツとして受けつけないようになる。
ディレクティブ例
script-src
<script>
で読み込まれる外部リソースの制御だけでなく、inline等の onclick
などの実行も制御する。
<script src="https://not-example.com/js/library.js"></script>
<button id="btn" onclick="doSomething()"></button>
🖕上記はブロックされるため、下記のように記述する必要がある
document.getElementById("btn").addEventListener("click", doSomething);
リソースや unsafe-inline
以外にも nonce
も利用できる。
Content-Security-Policy: script-src 'nonce-2726c7f26c'
上記ディレクティブの場合は、下記の処理は実行できる (同一のnonce値である場合に許可される)
<script nonce="2726c7f26c">
const inline = 1;
// …
</script>
また、今後増えつつありそうなWASMの処理も下記のように明示的に許可をする必要がある
Content-Security-Policy: script-src 'wasm-unsafe-eval'
connect-src
a
や JS のfetch等のメソッドによって読み込まれるリソースを制限。例として、下記はブロックされ、実行できない。
<a ping="https://not-example.com">
<script>
const xhr = new XMLHttpRequest();
xhr.open("GET", "https://not-example.com/");
xhr.send();
const ws = new WebSocket("https://not-example.com/");
const es = new EventSource("https://not-example.com/");
navigator.sendBeacon("https://not-example.com/", {
/* … */
});
</script></a>
img-src
画像やfaviconに対する有効なソースを定義する
style-src
CSS関連のリソース制御
Content-Security-Policy: style-src https://example.com/
上記ディレクティブの場合、下記はブロックされる
<link href="https://not-example.com/styles/main.css" rel="stylesheet" />
<style>
#inline-style {
background: red;
}
</style>
<style>
@import url("https://not-example.com/styles/print.css") print;
</style>
<div style="display:none">Foo</div>
document.querySelector('div').setAttribute('style', 'display:none;');
document.querySelector('div').style.cssText = 'display:none;';
🖕上記はブロックされるため、下記のように記述する必要がある
document.querySelector('div').style.display = 'none';
script-src
と同様に <style>
にnonce
を利用することも可能。
default-src
別のディレクティブに対するフォールバックとして機能する。例えば、 script-src
が明示的に指定されていないとき本ディレクティブが制御する。