【Rails】セッションとセッションハイジャック

# はじめに
こんにちは。アメリカにて独学でエンジニアを目指している者です。
現在、Railsチュートリアルを用いて学習を進めていますが、8章で出てくるセッションやセッションハイジャックについてまとめて理解度を深めようと思い記事にしました。

## セッションとは
セッションは、ユーザーがWebサイトにアクセスしている間の状態や情報をサーバー側で管理する仕組みです。
セッションの保存場所はサーバー上(データベースやメモリなど)で、**ユーザーの認証情報や一時的なデータ**（例：ログイン情報、カートの内容）を保持する目的で使用されます。
重要な情報がサーバー側に保存されるため、クライアントでの改ざんリスクが低いというメリットがあります


## `cookies`とは
`cookies`とはユーザーのブラウザに保存される小さなテキストデータです。
`cookies`の保存場所はクライアント側で、**ユーザー設定、ログイン情報の一部、訪問履歴やトラッキング**などの軽量なデータの保持に使用されます。一般的に**1ドメインあたり4KB程度**の容量制限があり、セキュリティ面では注意が必要です

## セッションと`cookies`の違い
扱うデータは違う一方でステートレスであるHTTPの機能を補う両者は混同されることがあるので違いを表にまとめてみました

| 項目               | セッション                                   | クッキー                                                 | 
| ------------------ | -------------------------------------------- | -------------------------------------------------------- | 
| 保存場所           | サーバー側                                   | クライアント側（ブラウザ）                               | 
| 保存できるデータ量 | 比較的多くのデータを扱える                   | 約4KB                                                    | 
| セキュリティ       | サーバー側で管理されるため改ざんリスクが低い | クライアント側で管理されるため改ざん・盗聴のリスクがある | 
| 利用用途           | ユーザー認証や一時的なデータの管理	          | ユーザー設定やトラッキングなどの軽量なデータ保存         | 

* セッションは重要な情報（例：ログイン状態）をサーバー側で管理するため、セキュリティ上安全ですが、その代わりサーバーのリソースを消費します。
* クッキーはユーザーの利便性（例：自動ログインやサイト設定の保持）に寄与しますが、クライアント側にデータが保存されるため、情報の改ざんや盗聴に対して脆弱な場合があります。


## セッション管理の仕組み
多くのWebアプリケーションでは、セッション管理は`cookies`を利用して実現されます。
基本的は流れは以下の通りです

#### 1. ユーザーの認証とセッションの生成
ユーザーがログインすると、サーバー側でユーザー情報（例：ユーザーID）をセッションに保存します。
```ruby
# Ruby on Rails の例
session[:user_id] = user.id
```
#### 2. セッションIDの発行と`cookies`への格納
サーバーは、一意のセッションID（例: `abcd1234efgh5678`）を生成し、このIDを`cookies`に保存してクライアントに送ります。
```
Set-Cookie: _session_id=abcd1234efgh5678; Path=/; HttpOnly
```
※この時、実際のユーザー情報はサーバー側に保存され、`cookies`にはセッションIDのみが保持されます。

#### 3. リクエスト時の認証
クライアントが再度リクエストを送る際、ブラウザは`cookies`内のセッションIDをサーバーへ送信し、サーバーはそのIDを用いて対応するセッションデータを参照、ユーザーを認証します。

## セッションハイジャック
ここまで、セッションと`cookies`について見てきました。
セッションのほうが`cookies`よりもサーバー上で管理するのでセキュリティ面で安全と伝えましたが、セッションIDはcookie上にあるのでそれを悪用するのがセッションハイジャックといいます

セッションハイジャック（Session Hijacking） とは、攻撃者が正規ユーザーのセッションIDを盗み取り、そのセッションIDを用いて不正にユーザーになりすます攻撃手法です。
セッションIDが漏洩すると、攻撃者は被害者の権限でWebアプリケーションにアクセスし、個人情報の窃取や不正操作が行われるリスクがあります。

## セッションハイジャックが発生する要因


* `cookies`依存の脆弱性:
上記で書いた通りですが、セッションIDは`cookies`に保存されるため、`cookies`が盗まれると攻撃者にセッションが乗っ取られるリスクがあります。

* 通信の暗号化不足:
HTTPSを使用せずに平文のHTTPで通信すると、パケットスニッフィングによってセッションIDが傍受されやすくなります

* XSS（クロスサイトスクリプティング）:
悪意のあるスクリプトがユーザーのブラウザ上で実行され、`document.cookie` からセッションIDが盗まれる可能性があります

* 予測可能なセッションID:
強度の低いランダム生成アルゴリズムにより、攻撃者がセッションIDを総当たりで推測するリスクがあります


## セッションハイジャックの対策
セッションハイジャックを防ぐためには、以下の対策が重要です

#### HTTPS の利用
HTTPSを使用することで、通信全体を暗号化し、ネットワーク上でのパケット傍受によるセッションIDの漏洩を防止することができます

#### `cookies`属性の適切な設定
railsであれば、以下のような設定をすることができます

* HttpOnly
`cookies`に対してJavaScriptの`document.cookie`のアクセスを禁止し、XSS攻撃によるセッションIDの取得を防ぐことができます
```ruby
cookies[:session_id] = { value: "abcd1234efgh5678", httponly: true }
```

* Secure 属性:
`cookies`がHTTPS通信時のみ送信されるように設定し、盗聴のリスクをさらに低減できます
```ruby
cookies[:session_id] = { value: "abcd1234efgh5678", secure: true, httponly: true }
```

#### セッションIDの再生成とタイムアウト設定
* セッションIDの再生成
ログイン後や特定の操作後に新しいセッションIDを生成することで、既存のセッションIDが漏洩していた場合でも被害を最小限に抑えることができます
```ruby
reset_session  # Ruby on Rails の場合、新しいセッションIDを発行
```
* タイムアウトの設定
一定時間操作がない場合にセッションを自動的に無効化することで、不正利用の可能性を減らすことができます


## まとめ
Webアプリケーションにおけるユーザー管理では、セッション と `cookies` はそれぞれ異なる役割を担っています。

* セッション はサーバー側でユーザーの状態を管理するため、重要な情報を安全に扱えますが、クライアントとのやり取りには`cookies`を利用して一意のセッションIDを送信します。
* `cookies` はユーザーの設定や軽量な情報の保持に便利ですが、クライアント側に保存されるため、セキュリティ面では十分な対策が求められます。

また、セッションIDが盗まれることで発生する セッションハイジャック は、通信の暗号化（HTTPS）や`cookies`属性（HttpOnly、Secure）の適切な設定、セッションIDの再生成、タイムアウトの導入など、複数の対策を組み合わせることで防ぐことが可能です。
安全なWebアプリケーションの構築には、これらの仕組みと対策を正しく理解し、実装することが不可欠です。