セキュリティ対策で指定すべきとされているHTTPヘッダーとして、以下のものがよく知られています。
- X-XSS-Protection
- X-Content-Type-Options
- Strict-Transport-Security
- X-Frame-Options
- Content-Security-Policy
世の中の大規模サービスがこれらのヘッダーをどう設定しているのか気になったので調べてまとめました。Content-Security-Policyについては設定値が長いのでヘッダーの有無だけを記載しています。
HTTPヘッダー | Github | Netflix | Slack | ||
---|---|---|---|---|---|
X-XSS-Protection | 0 | 1; mode=block | 1; mode=block | 1; mode=block | 1; mode=block |
X-Content-Type-Options | nosniff | nosniff | nosniff | nosniff | nosniff |
Strict-Transport-Security | max-age=15552000; preload |
max-age=631138519 | max-age=31536000; includeSubdomains; preload |
max-age=31536000 | max-age=31536000; includeSubDomains; preload |
X-Frame-Options | DENY | SAMEORIGIN | DENY | DENY | SAMEORIGIN |
Content-Security-Policy | あり | あり | あり | なし | なし |
X-XSS-Protection
ブラウザのXSSフィルターを有効化/無効化するためのヘッダー。
設定値は1; mode=block
とし、XSSフィルターを有効化かつXSS検出時にページのレンダリングを停止させるのが定石です(mode=block
を指定しない場合、ページをサニタイズした上でレンダリングが続行されます)。
Facebookは唯一XSSフィルターを無効化していますが、その分後述のContent-Secirity-Policyを厳密に定義しアプリケーション側の対策を十分に行なっているということだと思われます。
また、表ではスペースの都合上省略していますが、TwitterとNetflixではXSSが検出されたときにページの情報をサーバーに送信するオプションを指定しています。
X-XSS-Protection: 1; mode=block; report=https://twitter.com/i/xss_report
X-Content-Type-Options
ブラウザがファイルの中身からContentTypeを決める機能(sniffing)を無効化し、常にレスポンスヘッダのContentTypeが優先されるよう指示するヘッダー(XSS対策)。
上記の全てのサービスでnosniff
を指定しています。
Strict-Transport-Security
HTTPSでのアクセスを強制するヘッダー。初回のHTTPSアクセス後、max-age
に指定された時間(秒)の間はHTTPSによりリクエストが行われるようになります(HTTPリクエストもHTTPSリクエストに変換される)。
上記のすべてのサービスで、十分に長い時間をmax-age
に指定してHTTPSでのアクセスを強制しています。GithubとSlackはincludeSubdomain
を指定してこのポリシーをサブドメインにも適用しています。
preload
については以下を参照。
https://developer.mozilla.org/ja/docs/Web/Security/HTTP_Strict_Transport_Security#Preloading_Strict_Transport_Security
X-Frame-Options
フレーム(frameまたはiframeタグ)内でページの表示を許可するか/しないかを指定するヘッダー(クリックジャッキング対策)。
DENY
(一切禁止)とするか、SAMEORIGIN
(同一ドメインのみ許可)とするかの選択です。
Content-Security-Policy (CSP)
jsやcssなどのコンテンツの取得元ドメインを制限するためのヘッダー(XSS対策)。metaタグでも指定可能です。
大規模サービスだと、複数のドメインを持っていたりCDNを多用していたりでコレの記述はめちゃくちゃ細かいです。Githubの場合はこんな感じです。
Content-Security-Policy: default-src 'none'; base-uri 'self'; block-all-mixed-content; child-src render.githubusercontent.com; connect-src 'self' uploads.github.com status.github.com collector.githubapp.com api.github.com www.google-analytics.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com wss://live.github.com; font-src assets-cdn.github.com; form-action 'self' github.com gist.github.com; frame-ancestors 'none'; img-src 'self' data: assets-cdn.github.com identicons.github.com collector.githubapp.com github-cloud.s3.amazonaws.com *.githubusercontent.com; manifest-src 'self'; media-src 'none'; script-src assets-cdn.github.com; style-src 'unsafe-inline' assets-cdn.github.com; worker-src 'self'
NetflixとSlackではこのヘッダがありませんでした。metaタグでの指定もなかったのでCSPの設定は行なっていないということでしょうか(?)