「体系的に学ぶ 安全な Web アプリケーションの作り方」を読んで CSP ヘッダをちゃんと設定してみようという試み。
S3 + CloudFront でやってみたという話は次の記事で。
- npm パッケージの reload を使用して live reload する
- 必要な CSP ヘッダを整える
- Mozilla Obsertatory で結果を確認する
CONTENTS
- reload-wrapper を使用して live reload する
- Strict-Security-Policy
- X-Content-Type-Options
- X-Frame-Options
- X-XSS-Protection
- Referrer-Policy
- Content-Security-Policy
- Mozilla の Obsertatory を使用して結果を確認する
- まとめ
- 参考資料
reload-wrapper を使用して live reload する
reload を使用して live reload する。 用意されているコマンドラインツールはヘッダーの指定ができないので、ラッパーを用意した。
$ npm install --save-dev reload-wrapper
package.json にスクリプトの設定を行う。
{ "script": { "reload": "reload-wrapper -d ./public -w ./public/dist" } }
headers.json にヘッダを指定する。
[ ["Strict-Transport-Security", "max-age=31536000"], ["Content-Security-Policy", [ "default-src 'self'", "object-src 'none'", "base-uri 'none'", "form-action 'self'", "connect-src 'self' https://api.example.com", "img-src 'self' https://www.google-analytics.com/", "font-src 'self' https://fonts.gstatic.com/ https://use.fontawesome.com/", "script-src 'self' https://www.google-analytics.com/ https://www.googletagmanager.com/", "style-src 'self' https://use.fontawesome.com/ https://css.getto.systems/" ]], ["X-Content-Type-Options", "nosniff"], ["X-Frame-Options", "DENY"], ["X-XSS-Protection", "1; mode=block"], ["Referrer-Policy", "same-origin"] ]
サーバーを起動する。
$ npm run reload
Strict-Security-Policy
指定した秒数の間、 https でアクセスするように指示するもの。
Strict-Transport-Security: max-age=31536000
max-age は 31536000(1年)にした。
X-Content-Type-Options
Content-Type を厳密に解釈するよう指示するもの。
X-Content-Type-Options: nosniff
X-Frame-Options
frame や iframe での読み込みを許可しないように指示するもの。
X-Frame-Options: DENY
X-XSS-Protection
XSS フィルタを強制的に有効にするもの。
X-XSS-Protection: 1; mode=block
Referrer-Policy
同じ origin のみに Referrer をつけるように指示するもの。
Referrer-Policy: same-origin
Content-Security-Policy
ページに含まれるコンテンツのうち、どのコンテンツを実行するかを指示するもの。 適当にやると JavaScript が全滅するので、エラーを見つつ調整する必要がある。
default-src
デフォルトではサイト内のコンテンツのみ許可する。
default-src 'self'
その他、個別に細かく調整する必要がある。
object-src
object タグなどは使用していないので許可しない。
object-src 'none'
base-uri
base タグは使用していないので許可しない。
base-uri 'none'
form-action
form の action は self のみ許可する。
form-action 'self'
connect-src
ページからアクセスする先を指定する。
connect-src 'self' https://api.example.com/
<a>
ping、Fetch、XMLHttpRequest、WebSocket、EventSource の宛先になっているものを指定する。
img-src
画像の読み込み先を指定する。
img-src 'self' https://www.google-analytics.com/
google analytics は img タグを生成している。
font-src
フォントの読み込み先を指定する。
font-src 'self' https://fonts.gstatic.com/ https://use.fontawesome.com/
web フォント、font awesome はフォントを読み込んでいる。
script-src
スクリプトの読み込み先を指定する。
script-src 'self' https://www.google-analytics.com/ https://www.googletagmanager.com/
google analytics は googletagmanager にもアクセスしていた。
ページ内で使用するスクリプトは外部ファイルに切り出して読み込ませる必要がある。
style-src
スタイルの読み込み先を指定する。
style-src 'self' https://use.fontawesome.com/
font awesome はフォントを読み込んでいる。
ページ内で使用するスタイルは外部ファイルに切り出して読み込ませる必要がある。
全体
以上の内容をセミコロンで繋げて指定する。
Content-Security-Policy: default-src 'self'; object-src 'none'; connect-src 'self' https://api.example.com; img-src 'self' https://www.google-analytics.com/; font-src 'self' https://fonts.gstatic.com/ https://use.fontawesome.com/; script-src 'self' https://www.google-analytics.com/ https://www.googletagmanager.com/; style-src 'self' https://use.fontawesome.com/ https://css.getto.systems/
長い。
script と style について
このヘッダを指定すると、インライン実行ができなくなる。 アプリケーションの作り方によっては詰む。
Mozilla の Obsertatory を使用して結果を確認する
本番環境に適用した後、Obsertatory - Mozilla でスコアをチェックできる。 まだ必要なことがあれば対応していきたい。
まとめ
CSP ヘッダの調整を行なってみた。
スクリプトやスタイルの動かない部分がないか十分テストしてから本番環境に適用してスコアを良くしていきたい。