Observatory by Mozilla でA+評価を取得した設定例(2017-01-15時点)

Observatory by Mozilla はWebサーバのレスポンスヘッダーやSSL/TLS設定のセキュリティ状況をチェックしてくれる無償のWebサービスです。
セキュリティを強化するレスポンスヘッダーにより評価が高くなるのが特徴です。

- [Observatory by Mozilla](https://observatory.mozilla.org/)
  - https://observatory.mozilla.org/

今回、個人ブログ https://www.glamenv-septzen.net/ の設定を調整して A+ 評価を取得できましたので、レスポンスヘッダーの設定内容とその考え方など紹介します。

**注意1：今後のWeb技術の発展により評価が変化する場合があります。あくまでも 2017-01-15 時点ではこうだった、という参考として本記事をご活用ください。**

注意2：今回は 3rdパーティのスキャナーによるスキャンは含めていません。( `Don't scan with third-party scanners` にチェックを入れてスキャンしてます )

# 設定前 : F -> 設定後 : A+

* 設定前のScan Summary : F
   * https://www.glamenv-septzen.net/images/20170115_https_rating/www.glamenv-septzen.net-observatory-20170115-01before.png

* **設定後のScan Summary : A+**
   * https://www.glamenv-septzen.net/images/20170115_https_rating/www.glamenv-septzen.net-observatory-20170115-02after.png

# 参考資料と設定方針

セキュリティ系のレスポンスヘッダー全般：

- [OWASP Secure Headers Project - OWASP](https://www.owasp.org/index.php/OWASP_Secure_Headers_Project)
  - https://www.owasp.org/index.php/OWASP_Secure_Headers_Project
- [今夜つける HTTPレスポンスヘッダー （セキュリティ編） - うさぎ文学日記](http://d.hatena.ne.jp/sen-u/20131130/p1)
  - http://d.hatena.ne.jp/sen-u/20131130/p1

## Content-Security-Policy

- [Content Security Policy の紹介 - Web セキュリティ | MDN](https://developer.mozilla.org/ja/docs/Web/Security/CSP/Introducing_Content_Security_Policy)
  - https://developer.mozilla.org/ja/docs/Web/Security/CSP/Introducing_Content_Security_Policy
- [Content Security Policy (CSP) - Web セキュリティ | MDN](https://developer.mozilla.org/ja/docs/Web/Security/CSP)
  - https://developer.mozilla.org/ja/docs/Web/Security/CSP
- [CSP のポリシーディレクティブ - Web セキュリティ | MDN](https://developer.mozilla.org/ja/docs/Web/Security/CSP/CSP_policy_directives#plugin-types)
  - https://developer.mozilla.org/ja/docs/Web/Security/CSP/CSP_policy_directives#plugin-types
- [CSP 違反レポートの利用方法 - Web セキュリティ | MDN](https://developer.mozilla.org/ja/docs/Web/Security/CSP/Using_CSP_violation_reports)
  - https://developer.mozilla.org/ja/docs/Web/Security/CSP/Using_CSP_violation_reports
- [Content Security Policy Header Generator](http://cspisawesome.com/)
  - http://cspisawesome.com/
  - 項目をWebフォームで選択していくだけで、CSPのヘッダー値を組み立ててくれるサービスです。
  - 選択できる項目はやや少ないですが、まずこれで土台を作って、カスタマイズしてくとやりやすいと思います。

今回対象となるWebサイトは、CMSも含めて自分で手作りしたサイトになります。
そのため、どこでどのscriptをロードしているのか、`<script>` タグの利用状況はどうなのか、などCSPで頭を悩ませる調査作業を全て自分で完結できました。
リソースの利用状況をまとめるうと、以下のような状況でした。

* js/cssについては基本的に外部サイトからの読み込み無し => 基本的に `self` 指定で問題ない。
  * `<style>` 要素および style 属性は使っているため、 `style-src` のみ `self + unsafe-inline` 指定を使う。
  * Wikiの特定プラグインで `<script>` をinlineで使う可能性があったのだが、現在は全く使ってない & 依存してる外部サービス(Google Map)が大分変わってるため、そもそも10年近く前のコードで動くかどうかすら不明。当分使うことは無く、使うとしてもそもそも最新のGoogle Map APIに追従するところからになるので、今回はスルーしておく。
* 画像については外部サイトの画像を取ってきてるケースがあるので、 `*` 指定が必要。
* amazonのアフィリエイト広告でiframe埋め込みを使っているので、フレームのsrc属性について `*` 指定が必要。
* `<object>` タグは使っていないし、当分は使うことは無い。

CSPの主要ディレクティブ毎にまとめると、最終的に以下のような判断に落ち着きました。

* `base-uri`
  * デフォルトに任せるため、指定しない。
* `child-src`
  * amazon の iframe形式のアフィリエイトを使うため、`*` 指定を使う。
* `connect-src`
  * (`default-src` ディレクティブにfallback)
* `default-src`
  * 自分自身( `self` )にしておく。
* `font-src`
  * (`default-src` ディレクティブにfallback)
* `form-action`
  * まだexperimentalなため、未指定にしておく。
* `frame-ancestors`
  * まだexperimentalなため、未指定にしておく。
* `frame-src`
  * deprecated だが、 **`child-src`だけだと Edge で認識できず`default-src`が適用されてしまいAmazonのiframe形式のアフィリエイトが読み込めなくなった。**
  * → `*` 指定を残す。
* `img-src`
  * 外部の画像を表示する場合があるので、 `*` を指定。
* `manifest-src`
  * (`default-src` ディレクティブにfallback)
* `media-src`
  * (`default-src` ディレクティブにfallback)
* `object-src`
  * 当面使う予定が無いので `none` を指定。
* `plugin-types`
  * `object-src none` 指定によりカバーされるため、未指定。
* `referrer`
  * `deprecated, `Referrer-Policy` で指定。
* `reflected-xss`
  * `block` で試す。
* `report-uri`
  * `csp-report.php` を指定。デフォルトのblock動作で試す。
* `script-src`
  * (`default-src` ディレクティブにfallback)
* `script-dynamic`
  * 恐らく使わないので今は省略。
* `style-src`
  * `<style>`要素や属性を使っていたので、`self unsafe-inline` を指定。
* `upgrade-insescure-requests`
  * 使う。

```csp-report.php
<?php
header('HTTP/1.1 204 No Content');
$body = file_get_contents('php://input');
trigger_error('CSP-REPORT: '.$body, E_USER_WARNING);
```

PHPのエラーログはファイルに出力するよう設定しているので、たまに気がついたらPHPエラーログを確認することとしておく。個人のblogサイトなので、その程度の運用でもまぁ、問題ないかなと・・・。

実際に動作を一通り確認できて、リリースできたCSPの内容は以下になります。

```
Content-Security-Policy:
    upgrade-insecure-requests;
    default-src 'self';
    style-src 'self' 'unsafe-inline';
    img-src *;
    child-src *;
    frame-src *;
    object-src 'none';
    reflected-xss block;
    report-uri https://(...)/(...)/csp-report.php
```

## `HTTP Public Key Pinning (HPKP)`

- → 以下で今回は見送ってます。
- [Qualysの SSL Server TestでA+評価を取得した設定例(2017-01-15時点, CentOS7 + Apache HTTPD 2.4.6) - Qiita](http://qiita.com/msakamoto_sf/items/68a848fd6602dcc58b96)
  - http://qiita.com/msakamoto_sf/items/68a848fd6602dcc58b96

## `HTTP Strict Transport Security (HSTS)`

- → 以下で設定済みです。
- [Qualysの SSL Server TestでA+評価を取得した設定例(2017-01-15時点, CentOS7 + Apache HTTPD 2.4.6) - Qiita](http://qiita.com/msakamoto_sf/items/68a848fd6602dcc58b96)
  - http://qiita.com/msakamoto_sf/items/68a848fd6602dcc58b96

## Redirection

- レスポンスヘッダーではありませんが、Observatoryに検査項目があります。
- →以下で設定済みです。
- [Qualysの SSL Server TestでA+評価を取得した設定例(2017-01-15時点, CentOS7 + Apache HTTPD 2.4.6) - Qiita](http://qiita.com/msakamoto_sf/items/68a848fd6602dcc58b96)
  - http://qiita.com/msakamoto_sf/items/68a848fd6602dcc58b96

## `Referrer-Policy`

- → 一般的なデフォルト : `no-referrer-when-downgrade` を明示しました。
- [Referrer-Policy - HTTP | MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy)
  - https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy

## `Subresource Integrity (SRI)`

- レスポンスヘッダーではありませんが、Observatoryでチェックしています。設定していなくても減点されませんので、今回は見送りました。
- [Security/Guidelines/Web Security - MozillaWiki](https://wiki.mozilla.org/Security/Guidelines/Web_Security#Subresource_Integrity)
  - https://wiki.mozilla.org/Security/Guidelines/Web_Security#Subresource_Integrity


## `X-Content-Type-Options`

- → 特にIE向けにContent-Typeでセンシティブな動作が必要なページも無いので、"nosniff" を指定しました。

## `X-Frame-Options`

- → 自分のサイト内で、自分のサイトをframe表示してるところが無かった + 自分のサイトをframe表示しているような外部サイトも特に連絡を受けたことが無いため、思い切ってDENYにしました。

## `X-XSS-Protection`

- → 特に無効化が必要なページが無いため、 "1; mode=block" を設定しました。

## `X-Download-Options`

- → Observatory の検査項目には今の時点ではありませんでしたが、入れておいても特に問題にならない状況でしたので、 `noopen` で入れておきました。
- [ダウンロード エクスペリエンスのカスタマイズ (Windows)](https://msdn.microsoft.com/ja-jp/library/jj542450(v=vs.85).aspx)
  - https://msdn.microsoft.com/ja-jp/library/jj542450(v=vs.85).aspx


# 感想

- CSPの設定が、やはり非常に難易度が高い。最初はblockせず、report-onlyで動かして様子を見るしか無いのではないか。
  - 新規に開発するサイトなら、CSPも一緒にデザインしていけば綺麗に設定できそう。
  - **CMSを使ったサイトでは、CMSが生成するページ全てでリソース利用状況を把握して適切にCSPを絞るのは事実上不可能だと思う。**
     - 特定の機能、特定の条件でのみCSPに違反して動かなくなる、ような状況が頻発しそう。
     - また、それでサイトが動かなくなった場合、ブラウザの開発者ツールのconsoleログやCSP Reportの受信結果などを見る必要があり、メンテナンスが大変になりそう。
- SRIも、既存のサイトについて適用するのは難しい。新規作成するか、既存ページに新たにscriptをロードさせるタイミングで入れ込んでいくのが現実的に思えた。