セキュリティ向上のためのHTTPヘッダー設定

# 初めに
私は、Webアプリケーションのエンジニアをやっています。

自分のスキルは、アプリ開発の知識はそこそこあると思っていますが、セキュリティに関する知識はまだまだだと思っています。
また、インフラ側のWebサーバー設定などもあまり知識がないです。

ということもあり、Webサーバーにおけるセキュリティに関する設定を調べて、知識の幅を広げていきたいと思います！

***

# Content Security Policy

> クロスサイトスクリプティング (Cross-site_scripting) やデータインジェクション攻撃などのような、特定の種類の攻撃を検知し、影響を軽減するために追加できるセキュリティレイヤーです。これらの攻撃はデータの窃取からサイトの改ざん、マルウェアの拡散に至るまで、様々な目的に用いられます。

https://developer.mozilla.org/ja/docs/Web/HTTP/CSP

## 何ができるか
* サーバーからスクリプト実行可能なドメインを指定できる
* インラインスクリプト（`<script>`タグ内に記述されたスクリプト）や、html属性のイベントハンドラ（onclickなど）を実行を無効化できる

## 設定方法
```
Content-Security-Policy: <directive>; <directive>
```
### ディレクティブ（directive）と値（value）

| ディレクティブ | 説明 |
| ---- | ---- |
| script-src | JavaScriptを有効にするソースを指定します。 |
| default-src | 全てのコンテンツ（script,style,imageなど）を有効にするソースを指定します。 |


| 値 | 説明 |
| ---- | ---- |
| self | 同オリジンのみ許可する |
| Host | 指定したホストのみを許可する（ワイルドカードを利用可） |


## ユースケース及び設定例
### 前提（未設定時）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698420/e11ff45b-42ab-c78f-b98c-749a888645d1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698420/04c7e713-b15d-e9e0-6315-db1bec7addb9.png)

### １．すべてのコンテンツ（JS、CSS等）を同オリジンからのみ許可する。
#### 設定内容
```
Header always set Content-Security-Policy "default-src 'self';"
```

#### 実行結果
* インラインスクリプト、スタイルがブロックされる。**※オリジンで関係なくNG**
* 同オリジン以外のJS、CSSファイル参照がブロックされる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698420/a3706b3c-00e3-811d-99b2-6252da9432b3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698420/009b704b-ebdf-a58c-c0b2-4dc93728b85d.png)

### ２．JSを同オリジンからのみ許可する。
#### 設定内容
```
Header always set Content-Security-Policy "script-src 'self';"
```

#### 実行結果
* インラインスクリプトがブロックされる。
* 同オリジン以外のJSファイル参照がブロックされる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698420/f826bed6-978b-5c8a-21ad-e14d4099d786.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698420/635fc550-97af-f5da-df81-6273e2badfc6.png)


### ３．すべてのコンテンツ（JS、CSS等）を同オリジンからのみ許可する。（特定ドメインのスクリプトは許可）
#### 設定内容
```
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' code.jquery.com"
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698420/a7d358dd-df04-4770-e157-ec4f1e3e632f.png)

### ４．すべてのコンテンツ（JS、CSS等）を同オリジンからのみ許可する。（特定ドメインのスクリプトは許可）
#### 設定内容
```
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' code.jquery.com; style-src 'self' cdn.jsdelivr.net;"
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698420/ecb57180-48e2-a5bd-af15-dd8c91b83195.png)

***

# Strict-Transport-Security
> HTTP の Strict-Transport-Security レスポンスヘッダー (しばしば HSTS と略されます) は、ウェブサイトがブラウザーに HTTP の代わりに HTTPS を用いて通信を行うよう指示するためのものです。

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Strict-Transport-Security

## 何ができるか
* HTTPでリクエストがあった際に、Webサーバーからそれ以降はHTTPS通信をするように指示できる。
　それにより、暗号化通信となり傍受を受けずに安全な通信が可能。

## 設定方法
```
Strict-Transport-Security: max-age=<expire-time>
```

### ディレクティブ（directive）

| ディレクティブ | 説明 |
| ---- | ---- |
| max-age | ブラウザに対してHTTPS通信を継続する時間（秒）。リクエスト毎に更新される。|

## 設定例
### １．1,000秒間HTTPS通信するように記憶させる
#### 設定内容
```
Header always set Strict-Transport-Security "max-age=1000"
```

#### 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698420/3829574e-53b1-93bd-4a9f-a29cad0e467e.png)

***

# X-Frame-Options
> X-Frame-Options は HTTP のレスポンスヘッダーで、ブラウザーがページを frame、iframe、embed、object の中に表示することを許可するかどうかを示すために使用します。サイトはコンテンツが他のサイトに埋め込まれないよう保証することで、クリックジャッキング攻撃を防ぐために使用することができます。

## 何ができるか
* iframeなどの表示を制限することができる。それによりボタンやリンクの上に見えない要素を配置して、意図しない動作にさせるいわゆるクリックジャッキングを防ぐ。

## 設定方法
```
X-Frame-Options: <directive>
```

### ディレクティブ（directive）

| ディレクティブ | 説明 |
| ---- | ---- |
| DENY | 同オリジンに関わらず、フレームの表示をしない |
| SAMEORIGIN | 同オリジンのフレームのみ表示する |

## ユースケース及び設定例
### 前提（未設定時）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698420/dccbcd91-99ee-44c5-03a6-f282827bac5f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698420/8413981f-e077-3158-d401-43d57fb1d344.png)

### １．すべてのフレームを表示しない
#### 設定内容
```
Header always set X-Frame-Options "DENY"
```

#### 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698420/0b0b9e76-7339-89e3-e7f3-9574ea08a572.png)

### ２．同オリジンのフレームのみ表示する
別オリジンは用意できなかったので、同オリジンが表示されるかという観点で確認する。
#### 設定内容
```
Header always set X-Frame-Options "SAMEORIGIN"
```

#### 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698420/8413981f-e077-3158-d401-43d57fb1d344.png)



***

# X-XSS-Protection
> HTTP の X-XSS-Protection レスポンスヘッダーは Internet Explorer, Chrome, Safari の機能で、反射型クロスサイトスクリプティング (XSS) 攻撃を検出したときに、ページの読み込みを停止するためのものです。強い Content-Security-Policy をサイトが実装して、インライン JavaScript の使用を無効にしていれば ('unsafe-inline')、現在のブラウザーではこれらの防御は大枠で不要なものですが、まだ CSP に対応していない古いウェブブラウザーを使用しているユーザーには防御になります。

## 何ができるか
* ブラウザに対して、XSSを検知した際の振る舞いを設定でき、ページの停止などにより攻撃を防ぐことができる
* Chrome,Firefox,Edgeは、XSSフィルター機能が廃止されたことから、設定が効きません。基本的には、CSPを設定することが推奨されている模様です。~~（設定が有効なのは、Safariのみです。）~~ Safariについて、2022年3月15日リリースのSafari 15.4 からサポート対象外になっていました。（失礼しました。）

## 設定方法
```
X-XSS-Protection: value
```

### 値（value）

| ディレクティブ | 説明 |
| ---- | ---- |
| 0 | XSS フィルタリングを無効化する（基本的に使用しない） |
| 1 | XSS フィルタリングを有効化し、攻撃を検知するとサニタリングする |
| 1; mode=block | XSS フィルタリングを有効化し、攻撃を検知するとレンダリングを停止する |
| 1; report=reporting-uri | XSS フィルタリングを有効化し、攻撃を検知するとサニタリングする。また攻撃レポートを作成する。 |

***

# X-Content-Type-Options
> X-Content-Type-Options は HTTP のレスポンスヘッダーで、 Content-Type ヘッダーで示された MIME タイプを変更せずに従うべきであることを示すために、サーバーによって使用されるマーカーです。これにより、MIME タイプのスニッフィングを抑止することができます。言い替えれば、 MIME タイプを意図的に設定することができます。

https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/X-Content-Type-Options

## 何ができるか
* 通常は、コンテンツから表示やダウンロードが決まりますが、それをMIMEタイプを使用してより厳密に行うように指示できる。それによりXSSを防ぐことができる。

## 設定方法
```
X-Content-Type-Options: nosniff
```

---

# Cross-Origin Resource Sharing
> オリジン間リソース共有 (Cross-Origin Resource Sharing, CORS) は、追加の HTTP ヘッダーを使用して、あるオリジンで動作しているウェブアプリケーションに、異なるオリジンにある選択されたリソースへのアクセス権を与えるようブラウザーに指示するための仕組みです。ウェブアプリケーションは、自分とは異なるオリジン (ドメイン、プロトコル、ポート番号) にあるリソースをリクエストするとき、オリジン間 HTTP リクエストを実行します。

## 何ができるか
* WebAPIや画像ファイルアクセスする際に、サーバー側でアクセス元の制限をすることができます。

詳しくは、別の記事にかきました。
https://qiita.com/ragner_k/items/783a797c47a348490a66

***

# 有名サイトのヘッダー情報を見てみる
ここまで調べてきて、実際どのような設定が一般的なのか見てみる。
意外と設定されていないようですが、`X-Frame-Options`はどこも設定されているようにですね。
CSPは、開発にも大きく影響するため、あまり設定されてないのかなと思います。

| サイト | Content Security Policy | Strict-Transport-Security | X-Frame-Options | X-XSS-Protection | X-Content-Type-Options |
| ---- | ---- | ---- | ---- | ---- | ---- |
| 大手飲食情報サイト | 設定なし | 設定なし | SAMEORIGIN | 1; mode=block | nosniff |
| 大手転職サイト | 設定なし | 設定なし | SAMEORIGIN | 設定なし | 設定なし |
| 大手通販サイト1 | 設定なし | max-age=47474747; includeSubDomains; preload | SAMEORIGIN | 設定なし | 設定なし |
| 大手通販サイト2 | 設定なし | 設定なし | DENY | 1; mode=block | nosniff |
| 大手SNS | connect-src 'self' blob:  default-src 'self';   form-action 'self' font-src 'self'  frame-src 'self'  img-src 'self' blob: data: manifest-src 'self';  media-src 'self' blob: object-src 'none';  script-src 'self' 'unsafe-inline' style-src 'self' 'unsafe-inline' worker-src 'self' blob:;report-uri  ※一部省略しています | max-age=631138519 | DENY | 0 | nosniff |

# 最後に
いい勉強になったので、他にもセキュリティに関する知識を身に着けていきたいと思います。