大規模サービスのセキュリティ対策用HTTPヘッダーまとめ

セキュリティ対策で指定すべきとされているHTTPヘッダーとして、以下のものがよく知られています。

- X-XSS-Protection 
- X-Content-Type-Options
- Strict-Transport-Security
- X-Frame-Options
- Content-Security-Policy

世の中の大規模サービスがこれらのヘッダーをどう設定しているのか気になったので調べてまとめました。Content-Security-Policyについては設定値が長いのでヘッダーの有無だけを記載しています。

| HTTPヘッダー | Facebook | Twitter | 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;<br>preload | max-age=631138519 | max-age=31536000;<br>includeSubdomains;<br>preload | max-age=31536000 | max-age=31536000;<br>includeSubDomains;<br>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が検出されたときにページの情報をサーバーに送信するオプションを指定しています。
<pre>X-XSS-Protection: 1; mode=block; report=https://twitter.com/i/xss_report</pre>

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の設定は行なっていないということでしょうか（?）

参考リンク
-----

- [Webサーバで指定すべきヘッダ - Qiita](https://qiita.com/d6rkaiz/items/9f4ebad83b3437a0d2ea)
- [X-XSS-Protection - HTTP | MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-XSS-Protection)
- [X-Content-Type-Options - HTTP | MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options)
- [HTTP Strict Transport Security - Web セキュリティ | MDN](https://developer.mozilla.org/ja/docs/Web/Security/HTTP_Strict_Transport_Security)
- [X-Frame-Options レスポンスヘッダ - HTTP | MDN](https://developer.mozilla.org/ja/docs/Web/HTTP/X-Frame-Options)
- [Content Security Policy (CSP) - HTTP | MDN](https://developer.mozilla.org/ja/docs/Web/HTTP/CSP)