セキュリティ入門：『安全なウェブサイトの作り方』Railsでの具体例付きさらっと解説

# はじめに

エンジニアのみなさま、日々の学習本当にお疲れ様です。
また本記事まで足を運んでいただき本当に感謝です。

今回はIPA（独立行政法人情報処理推進機構）が出している **[『安全なウェブサイトの作り方』](https://www.ipa.go.jp/security/vuln/websecurity/ug65p900000196e2-att/000017316.pdf)** でセキュリティの脆弱性について学習しました。要約したのと、Railsの場合どのような対策が出来るのかを調べたので備忘兼ねて投稿します。間違いあればコメントいただけると幸いです。


# 1. SQLインジェクション

アプリケーションのセキュリティ上の不備を意図的に利用し、アプリケーションが想定しないSQL文を実行させることで、データベースシステムを不正に操作する攻撃方法、またはその攻撃を可能とする脆弱性のことです。

### 脅威
- データベースに蓄積された非公開情報の閲覧
- データベースに蓄積された情報の改ざん・消去
- 認証回避による不正ログイン
- ストアプロシージャ等を利用したOSコマンドの実行

### 対策

以下のように位置指定ハンドラを使うことで、汚染された文字列をサニタイズできます。

```ruby:Rails
Model.where("zip_code = ? AND quantity >= ?", entered_zip_code, entered_quantity).first
```
以下のように名前付きハンドラを用いて、ハッシュから値を取り出すこともできます。

```ruby:Rails
values = { zip: entered_zip_code, qty: entered_quantity }
Model.where("zip_code = :zip AND quantity >= :qty", values).first
```


# 2. OSコマンド・インジェクション

ユーザー入力が適切に検証されずにシステムコマンドの引数として使用されると、攻撃者が任意のOSコマンドを実行できる脆弱性です。これにより、サーバー内のファイル操作や不正なプログラムの実行が可能となります。

### 脅威
- サーバ内ファイルの閲覧、改ざん、削除
- 不正なシステム操作（シャットダウン、ユーザアカウントの追加、変更、削除）
- 不正なプログラムのダウンロード・実行（ウィルス、ワーム、ボット等への感染）
- 他のシステムへの攻撃の踏み台（サービス不能攻撃、迷惑メールの送信）

### 対策

コマンドラインのパラメータを安全に渡せるsystem(コマンド名, パラメータ)メソッドを使うことです。

```ruby:Ruby
system("/bin/echo", "hello; rm *")
# "hello; rm *"を実行してもファイルは削除されない
```

Fileメソッド、IOメソッド、URIメソッドも使えます。

```ruby:Ruby
File.open("| ls") { |file| file.read }
# lsコマンドは実行されず、単に`| ls`というファイルが存在すれば開く

IO.open(0) { |file| file.read }
# stdinをオープンするが、引数をStringとして受け取らない

require "open-uri"
URI("https://example.com").open { |file| file.read }
# URLを開くが、`URI()`は`| ls`を受け取らない
```

# 3. セッションハイジャック

コンピュータネットワーク通信におけるセッション（特定利用者間で行われる一連の通信群）を、通信当事者以外が乗っ取る攻撃手法です。特に、HTTPにおけるWebセッションのハイジャックを指すことが多いですが、この用語が示す範囲は必ずしもこれに限定されません。攻撃者がセッションIDを取得することで、正規ユーザーになりすまし、不正な操作を行う可能性があります。

### 脅威
- ログイン後の利用者のみが利用可能なサービスの悪用
- ログイン後の利用者のみが編集可能な情報の改ざん・新規登録
- ログイン後の利用者のみが閲覧可能な情報の閲覧

### 対策

SSLによる安全な接続の提供が必要であるため、アプリケーションの設定ファイルで以下のようにSSL接続を強制します。

```ruby: Rails
config.force_ssl = true
```

# 4. クロスサイト・スクリプティング

Webアプリケーションの脆弱性、もしくはそれを利用した攻撃です。

### 脅威
- 本物サイト上に偽のページが表示される
- ブラウザが取得したCookieが盗まれる
- 任意のCookieをブラウザに保存させられる

### 対策

**禁止リスト方式（ブラックリスト方式）** よりも **許可リスト方式（ホワイトリスト方式）** でフィルタすることが重要です。禁止リスト方式（ブラックリスト方式）は **受け入れたくない入力や動作をリスト化** し、それらを拒否します。一方で、許可リスト方式（ホワイトリスト方式）は **信頼できる入力や動作のみをリスト化** し、それらだけを許可します。

#### ① HTMLテキストの入力を許可しない場合
- ウェブページに出力する全ての要素に対してエスケープ処理を施す
- URLを出力する場合は「http://」や「https://」で始まるもののみ許可（ホワイトリスト形式）
- `<script>`要素の動的生成を避ける
- 任意のサイトからスタイルシートを取り込まない

#### ② HTMLテキストの入力を許可する場合
- 入力されたHTMLテキストを構文解析し、スクリプトを含まない必要な要素のみを抽出

#### ③ 全てのウェブアプリケーションに共通の対策
- HTTPレスポンスヘッダの`Content-Type`フィールドに文字コード（charset）を指定

# 5. CSRF（クロスサイト・リクエスト・フォージェリ）

信頼できないデータがWebページに直接挿入され、ユーザーのブラウザで悪意のあるスクリプトが実行される脆弱性です。これにより、Cookieの盗難やユーザーの操作が不正に行われる可能性があります。

### 脅威
- ログイン後の利用者のみが利用可能なサービスの悪用
- ログイン後の利用者のみが編集可能な情報の改ざん、新規登録

### 対策
- 処理を実行するページをPOSTメソッドでアクセス
   - 「hiddenパラメータ」に秘密情報を埋め込む
   - 実行ページでその値が正しい場合のみ処理を実行
- 実行直前のページで再度パスワード入力を要求

以下の1行コードはアプリケーションのコントローラに追加するものであり、Railsで新規作成したアプリケーションにはこのコードがデフォルトで含まれます。Railsで生成されるすべてのフォームとAjaxリクエストにセキュリティトークンが自動的に含まれます。セキュリティトークンがマッチしない場合には例外がスローされます。

```ruby: Rails
protect_from_forgery with: :exception
```

# 6. HTTPヘッダ・インジェクション

HTTPを使って通信するシステムにおいて、動的にHTTPヘッダを生成する機能の不備を突いてヘッダ行を挿入することで不正な動作を行なわせる攻撃手法のこと、また、その攻撃を可能とする脆弱性のことです。

### 脅威
- 本物サイト上に偽のページが表示される
- ブラウザが保存しているCookieを取得される
- 任意のCookieをブラウザに保存させられる

### 対策
- ヘッダの出力を直接行わず、ウェブアプリケーションの実行環境や言語に用意されているヘッダ出力用APIを使用する
- 改行コードを適切に処理するヘッダ出力用APIを利用できない場合は、改行を許可しないよう、開発者自身で適切な処理を実装する
    - 改行コード以降の文字を削除する方法
    - 改行が含まれていたらウェブページ生成の処理を中止する方法

# 7. メールヘッダ・インジェクション

ユーザー入力が適切にエスケープされずにメールヘッダへ組み込まれると、攻撃者が任意のヘッダを挿入し、スパムメールの送信やメールの不正中継を行うことが可能となる脆弱性です。

### 脅威
- メールの第三者中継
    - 迷惑メールの送信に悪用される

### 対策
- メールヘッダを固定値にして、外部からの入力はすべてメール本文に出力する
- メールヘッダを固定値にできない場合、ウェブアプリケーションの実行環境や言語に用意されているメール送信用APIを使用する
- HTMLで宛先を指定しない

# さいごに

足らずの項目何個かあるので、気が向いたら更新しておきます...笑

# 参考記事

https://www.ipa.go.jp/security/vuln/websecurity/ug65p900000196e2-att/000017316.pdf

https://railsguides.jp/security.html

https://docs.ruby-lang.org/ja/latest/doc/index.html

# おまけ

弊社のご紹介もさせてください！

### 「日本で一番エンジニアが成長できる会社を創る」

https://prum.jp/

### エンジニアリングの募集

https://www.wantedly.com/projects/1808638

### PM・Webディレクションの募集

https://www.wantedly.com/projects/1355235

### セールス・事業開発の募集

https://www.wantedly.com/projects/1792065

### コーポレート系の募集

https://www.wantedly.com/projects/1752874

### コンサルティングの募集

https://www.wantedly.com/projects/1794481

弊社メンバーは日々学習した内容をアウトプットしております！
少しでもご興味を持たれた方は求人を見てみてください！
ご応募もお待ちしております！

### 最後までご覧いただき、ありがとうございました！