Railsのセキュリティに関する記事は、Railsセキュリティガイドをはじめとして、たくさんありますが、
今回はOWASPのTop10に沿って、Railsにおけるその対策を書いていきます。
※あくまでも自分が調べた一部の機能や対策の紹介のため、これらの対策を全てやっていれば問題ないという訳ではありませんし、全てのRailsアプリケーションに同じ対策が当てはまるわけではありません。
また、一部対策の重複や、説明(引用)のみの項目もあります。
対象バージョン
Rails: 7.0
OWASPとは?
OWASP - Open Web Application Security Project とは、Webをはじめとするソフトウェアのセキュリティ環境の現状、またセキュアなソフトウェア開発を促進する技術・プロセスに関する情報共有と普及啓発を目的としたプロフェッショナルの集まる、オープンソース・ソフトウェアコミュニティです
OWASP Top10
OWASP Top10は、Webアプリケーション・セキュリティに関する最も重大な10のリスクについてのランキングと修正のガイダンスを提供する、OWASPのWebサイトにあるオンライン・ドキュメントです。
このレポートは、世界中のセキュリティ専門家間で一致している意見に基づいています。
内容は4年ごとに更新され、最新は2021年版となっています。
2021 Top10の内容
最新の2021年版では、以下のような項目が選ばれました。
Aの後の数字=順位となっており、高いほど重大な項目です。右の数字は前回の順位で、いくつか新設されたものもあります。詳しい順位変動の説明は以下をご覧ください。
A01 アクセス制御の不備(5)
A02 暗号化の失敗(3)
A03 インジェクション(1)
A04 安全が確認されない不安な設計(New)
A05 セキュリティの設定ミス(6)
A06 脆弱で古くなったコンポーネント(9)
A07 識別と認証の失敗(2)
A08 ソフトウェアとデータの整合性の不具合(New)
A09 セキュリティログとモニタリングの失敗(10)
A10 サーバーサイドリクエストフォージェリ (SSRF) (New)
各項目について
各項目について、簡単な説明とRails(フレームワーク、ライブラリとその周辺環境)での対策を説明していきます。
アクセス制御の不備
アクセス制御は、ユーザに対して予め与えられた権限から外れた行動をしないようにポリシーを適用するものです。ポリシー適用の失敗により、許可されていない情報の公開、すべてのデータの変更または破壊、またはユーザ制限から外れたビジネス機能の実行が引き起こされます。
説明
- URL、内部のアプリケーションの状態、HTMLページを変更することやカスタムAPI攻撃ツールを単純に使用することによって、アクセス制御のチェックを迂回できてしまう。
- 主キーを他のユーザのレコードに変更することができ、他のユーザのアカウントを表示または編集できてしまう。
- 権限昇格。ログインすることなしにユーザとして行動したり、一般ユーザとしてログインした時に管理者として行動できてしまう。
- メタデータの操作。JSON Web Token(JWT)アクセス制御トークンや権限昇格するために操作されるCookieやhiddenフィールドを再生成または改ざんできたり、JWTの無効化を悪用できるなど。
- CORSの誤設定によって権限のないAPIアクセスが許可されてしまう。
- 認証されていないユーザを要認証ページへ、一般ユーザを要権限ページへ強制ブラウズできてしまう。 POST、PUT、DELETEメソッドへのアクセス制御がないAPIへアクセスができてしまう。
防止方法
- 公開リソースへのアクセスを除いて、アクセスを原則として拒否する。
- CORSの使用箇所を最小限に抑えるなど、アクセス制御メカニズムを一か所で実装しアプリケーション全体でそれを再利用する。
- アクセス制御モデルは、ユーザがどのようなレコードでも作成、読取、更新、または削除できるようにするのではなく、レコードの所有権があることを前提としなければならない。
- アプリケーション独自のビジネス上の制約要求はドメインモデルによって表現される必要がある。
- Webサーバーのディレクトリリスティングを無効にし、ファイルのメタデータ(.gitなど)やバックアップファイルがWebの経路上に存在しないことを確認する。
- アクセス制御の失敗をログに記録し、必要に応じて管理者に警告する(繰り返し失敗しているなど)。
- レート制限するAPIとコントローラは自動攻撃ツールによる被害を最小限に抑えるための手段である。
- JWTトークンはログアウト後にはサーバー上で無効とされるべきである。
Railsにおける対策
- 特に重要なリソース(ユーザー情報など)には、予測可能な連番IDを使わないようにする。
- 例えばPostgreSQLを使用している場合、pgcrypt拡張を使用することにより、簡単にuuidを設定することが可能です(参考: https://railsguides.jp/active_record_postgresql.html#uuid)
- リソースへのアクセスは、可能な限りリレーションを使用する。
class ResourcesController < ApplicationController
before_action :authenticate_user!
def show
current_user.resources.find(params[:id])
end
end
-
rack-attacksを使用するなどして、連続する攻撃に対する対策を行う。
- AWS WAFなど、より前段階で攻撃を防げる場合には、それを使用することも検討しましょう
- API Modeなど、CORSを許可する場合にはrack-corsを使用する
暗号化の失敗
https://owasp.org/Top10/ja/A02_2021-Cryptographic_Failures/
このカテゴリは根本的な要因よりも、暗号化技術の不適切な使用、または暗号化の欠如に関連した幅広い障害に焦点を当てています。こうした障害は、時に機微な情報の露出を結果としてもたらします。
説明
- どんなデータであれ平文で送信していないか。これは、HTTP、SMTP、FTPのようなプロトコルを使っている場合に該当する。外部インターネットへのトラフィックは危険である。また、ロードバランサー、Webサーバー、バックエンドシステムなどの内部の通信もすべて確認すること。
- 古いまたは脆弱な暗号アルゴリズムを初期設定のまま、または古いコードで使っていないか。
- 初期値のままの暗号鍵の使用、弱い暗号鍵を生成または再利用、適切な暗号鍵管理または鍵のローテーションをしていない、これらの該当する箇所はないか。
- ユーザーエージェント(ブラウザ)のセキュリティに関するディレクティブやヘッダーが欠落しているなど、暗号化が強制されていない箇所はないか。
- アプリ、メールクライアントなどのユーザエージェントが受信したサーバー証明書が正当なものか検証していない箇所はないか。
防止方法
- アプリケーションごとに処理するデータ、保存するデータ、送信するデータを分類する。そして、どのデータがプライバシー関連の法律・規則の要件に該当するか、またどのデータがビジネス上必要なデータか判定する。
- 前述の分類をもとにアクセス制御を実装する。
- 必要のない機微な情報を保存しない。できる限りすぐにそのような機微な情報を破棄するか、PCI DSSに準拠したトークナイゼーションまたはトランケーションを行う。データが残っていなければ盗まれない。
- 保存時にすべての機微な情報を暗号化しているか確認する。
- 最新の暗号強度の高い標準アルゴリズム、プロトコル、暗号鍵を実装しているか確認する。そして適切に暗号鍵を管理する。
- 前方秘匿性(PFS)を有効にしたTLS、サーバーサイドによる暗号スイートの優先度決定、セキュアパラメータなどのセキュアなプロトコルで、通信経路上のすべてのデータを暗号化する。HTTP Strict Transport Security (HSTS)のようなディレクティブで暗号化を強制する。
- 機微な情報を含むレスポンスのキャッシングを無効にする。
- パスワードを保存する際、Argon2、scrypt、bcrypt、PBKDF2のようなワークファクタ(遅延ファクタ)のある、強くかつ適応可能なレベルのソルト付きハッシュ関数を用いる。
- 設定とその設定値がそれぞれ独立して効果があるか検証する。
Railsにおける対策
- DBに保存する際には、重要なデータは暗号化する。
- ActiveRecordはモデルレベルで暗号化することが可能です。
- ログを保存する際にも、重要なデータはフィルタリングを行う。
- filter_parameterにより、一括での設定が可能です。
- ただし、SQLの発行ログではフィルタリングは行われません。
- 常にforce_sslを
true
にする。- デフォルトでは
true
に設定されているため、特別な対応は必要ありません
- デフォルトでは
- 可能な限りdeviseなどの認証用gemを使用し、デフォルト設定を変更しない。
- 例えばdeviseでは、パスワードの保存に上記推奨されているbcryptを使用しています
インジェクション
94%のアプリケーションで、何らかのインジェクションに関する問題が確認されています。
説明
次のような状況では、アプリケーションはこの攻撃に対して脆弱です。
- ユーザが提供したデータが、アプリケーションによって検証、フィルタリング、またはサニタイズされない。
- コンテキストに応じたエスケープが行われず、動的クエリまたはパラメータ化されていない呼出しがインタープリタに直接使用される。
- オブジェクト・リレーショナル・マッピング(ORM)の検索パラメータに悪意を持ったデータが使用され、重要なレコードを追加で抽出してしまう。
- 悪意を持ったデータを直接または連結して使う。動的クエリ、コマンドまたはストアド・プロシージャにおいてSQLやコマンドがそのような構造と悪意を持ったデータを含む。
防止方法
- インジェクションを防止するためにはコマンドとクエリからデータを常に分けておくことが必要です。
- 推奨される選択肢は安全なAPIを使用すること。インタープリタの使用を完全に避ける、パラメータ化されたインターフェースを利用する、または、オブジェクト・リレーショナル・マッピング・ツール(ORM)を使用するように移行すること。
- 注意: パラメータ化されていたとしても、ストアドプロシージャでは、PL/SQLまたはT-SQLによってクエリとデータを連結したり、EXECUTE IMMEDIATEやexec()を利用して悪意のあるデータを実行することによって、SQLインジェクションを発生させることができる。
- ポジティブな、言い換えると「ホワイトリスト」によるサーバーサイドの入力検証を用いる。特殊文字を必要とする多くのアプリケーション、たとえばモバイルアプリケーション用のテキスト領域やAPIなどにおいては完全な防御方法とはならない。
- 上記の対応が困難な動的クエリでは、そのインタープリタ固有のエスケープ構文を使用して特殊文字をエスケープする。
- 注意: テーブル名やカラム名などのSQLストラクチャに対してはエスケープができない。そのため、ユーザ指定のストラクチャ名は危険である。これはレポート作成ソフトウェアに存在する一般的な問題である。
- クエリ内でLIMIT句やその他のSQL制御を使用することで、SQLインジェクション攻撃が発生した場合のレコードの大量漏洩を防ぐ。
Railsでの対策
- SQLインジェクトション:ユーザー入力値に応じたSQLを実行する際には、必要に応じてプレースホルダやエスケープ用のメソッドを使用する。
- ActiveRecordの
find(:id)
やfind_by_xxx(aaa)
では自動的にエスケープが行われますが、SQLフラグメント、特に条件フラグメント(where("..."))
、connection.execute()
またはModel.find_by_sql()
メソッドでは自動でのエスケープが行われないので、ユーザーの入力値をそのまま使うのではなく、where句のプレースホルダや、sanitize_sqlを行いましょう。
- ActiveRecordの
- XSS:ユーザーの入力値をテキストやリンクとして表示する場合には、必要に応じでエスケープを行う。
- CSSインジェクション:基本的にユーザーにCSSをカスタマイズさせない。どうしても必要な場合はsanitizeを行う。
- コマンドラインインジェクション:適切なメソッドを使用し、任意のコマンドを実行できないようにする。
-
systemコマンドは、OSのコマンドを実行しますが、
system(コマンド, パラメータ)
とすれば、パラメータのみをユーザーに指定させることが可能です。 - Karnel.openは垂直バー|で始まる引数を渡すとOSコマンドを実行できます。File.openなどを使用しましょう。
-
systemコマンドは、OSのコマンドを実行しますが、
- 基本的に入力値に対するvalidationをかける場合には、ブラックリストではなくホワイトリスト形式にする。
安全が確認されない不安な設計
設計やアーキテクチャの欠陥に関するリスクに焦点を当てています。 私たちは脅威のモデル化、セキュアなデザインパターンおよび、リファレンスアーキテクチャなどをもっと利用していくことが必要です。
説明
「安全な設計が行われていない」または、「効果的ではない設計が行われている」と表現されます。 「安全な設計が行われていない」とは、管理策が欠如していることを意味します。例として、センシティブなデータを暗号化すべきコードに、暗号化するためのメソッドがない場合があげられます。 「効果的ではない設計が行われている」とは、攻撃者が脅威を発生させる可能性があるにもかかわらず、ドメイン(ビジネス)ロジックの検証が不十分であるために、リスクが顕在化する場合を意味します。 例として、所得区分に基づいてパンデミック税の軽減措置を処理することになっているドメインロジックが、すべての入力が正しく署名されているかどうかを検証しておらず、本来付与されるべきものよりもはるかに大きな軽減措置を提供している場合が挙げられます。
防止方法
- セキュリティおよびプライバシー関連の管理策の評価および設計を支援するために、アプリケーションセキュリティの専門家とともにセキュアな開発ライフサイクルを確立し使用する
- セキュアなデザインパターンまたは、信頼性が高く安全性も検証されているコンポーネントライブラリを構築し使用する
- 重要な認証、アクセスコントロール、ビジネスロジック、および暗号鍵の管理フローに脅威モデルを使用する
- ユーザーストーリーにセキュリティ言語とコントロールを組み込む
- (フロントエンドからバックエンドまで)アプリケーションの各層に妥当性チェックを統合する
- ユニットテストおよび統合テストを実施し、すべての重要なフローが脅威モデルに対して耐性があることを検証する。アプリケーションの各階層のユースケースとミスユースケースをまとめる
- リスク管理における保護の必要性に応じて、システム層とネットワーク層の階層を分ける
- すべての階層でテナントを分離した堅牢な設計を行う
- ユーザーやサービスによる過剰なリソース消費を制限する
Railsでの対策
セキュリティの設定ミス
アプリケーションの 90 %には何らかの設定ミスが確認され、平均発生率は 4 %です。
説明
- アプリケーションスタックのいずれかの部分におけるセキュリティ堅牢化の不足、あるいはクラウドサービスでパーミッションが不適切に設定されている
- 必要のない機能が有効、あるいはインストールされている(例えば、必要のないポートやサービス、ページ、アカウント、特権)
- デフォルトのアカウントとパスワードが有効になったまま変更されていない
- エラー処理がユーザに対して、スタックトレースやその他余計な情報を含むエラーメッセージを見せる
- アップグレードしたシステムでは、最新のセキュリティ機能が無効になっているか正しく設定されていない
- アプリケーションサーバやアプリケーションフレームワーク(例えば、Struts、Spring、 ASP.NET)、ライブラリ、データベース等のセキュリティの設定が、安全な値に設定されていない
- サーバがセキュリテイヘッダーやディレクティブを送らなかったり、安全な値に設定されていなかったりする
防止方法
- 繰り返し堅牢化するプロセスは、素早くかつ容易に他の環境に展開され、正しくロックダウンすること。 開発やQA、本番環境は完全に同じように設定し、それぞれの環境で別々の認証情報を使用すること。 このプロセスを自動化し、新しい安全な環境をセットアップする際には、手間を最小限にすること。
- プラットフォームは最小限のものとし、必要のない機能やコンポーネント、ドキュメント、サンプルを除くこと。 使用しない機能とフレームワークは、削除もしくはインストールしないこと。
- レビューを実施して、セキュリティ関連の記録と更新の全てに加え、パッチを管理するプロセスの一環としてパッチの設定を適切に更新すること(# A06:2021 – 脆弱で古くなったコンポーネント を参照)。 クラウドストレージのパーミッションは、詳細にレビューすること (例えば、S3 バケットのパーミッション)。
- セグメント化したアプリケーションアーキテクチャは、セグメンテーションやコンテナリゼーション、クラウドのセキュリティグループ(ACL)をともなったコンポーネントやテナント間に、効果的で安全な仕切りをもたらす。
- セキュリティディレクティブをクライアントへ送ること。例としては セキュリティヘッダー が挙げられる。
- プロセスを自動化して設定の有効性を検証し、環境すべてに適用すること。
脆弱で古くなったコンポーネント
脆弱なコンポーネントは、テストやリスク評価に苦労する問題として知られています
説明
- 使用しているすべてのコンポーネントのバージョンを知らない場合(クライアントサイド・サーバサイドの両方について)。 これには直接使用するコンポーネントだけでなく、ネストされた依存関係も含む。
- ソフトウェアが脆弱な場合やサポートがない場合、また使用期限が切れている場合。 これには、OSやWebサーバ、アプリケーションサーバ、データベース管理システム(DBMS)、アプリケーション、API、すべてのコンポーネント、ランタイム環境とライブラリを含む。
- 脆弱性スキャンを定期的にしていない場合や、使用しているコンポーネントに関するセキュリティ情報を購読していない場合。
- 基盤プラットフォームやフレームワークおよび依存関係をリスクに基づきタイムリーに修正またはアップグレードしない場合。 パッチ適用が変更管理の下、月次や四半期のタスクとされている環境でよく起こる。 これにより、当該組織は、解決済みの脆弱性について、何日も、場合によっては何ヶ月も不必要な危険にさらされることになる。
- ソフトウェア開発者が、更新やアップグレードまたはパッチの互換性をテストしない場合。
- コンポーネントの設定をセキュアにしていない場合。(A05-2021: セキュリティの設定ミス 参照)
防止方法
- 未使用の依存関係、不要な機能、コンポーネント、ファイルや文書を取り除く。
- Versions Maven Plugin, OWASP Dependency Check, Retire.jsなどのツールを使用して、クライアントおよびサーバの両方のコンポーネント(フレームワークやライブラリなど)とその依存関係の棚卸しを継続的に行う。 コンポーネントの脆弱性についてCVE(Common Vulnerability and Exposures)やNVD(National Vulnerability Database)などの情報ソースを継続的にモニタリングする。ソフトウェア構成分析ツールを使用してプロセスを自動化する。 使用しているコンポーネントに関するセキュリティ脆弱性の電子メールアラートに登録する。
- 安全なリンクを介し、公式ソースからのみコンポーネントを取得する。 変更された悪意あるコンポーネントを取得する可能性を減らすため、署名付きのパッケージを選ぶようにする。 (A08-2021: ソフトウェアとデータの整合性の不具合 参照)
- メンテナンスされていない、もしくはセキュリティパッチが作られていない古いバージョンのライブラリとコンポーネントを監視する。 パッチ適用が不可能な場合は、発見された問題を監視、検知または保護するために、仮想パッチの適用を検討する。
Railsでの対策
-
rails new
を行う際に不要なファイルを生成しない。-
rails newには複数のオプションがあり、
-api
や–minimal
モードを選ぶと必要なファイルだけが生成されます。 - また、
–skip-action-mailbox
など、特定の機能だけを除くオプションもあります。
-
rails newには複数のオプションがあり、
-
scaffold
時に不要なファイルを生成しない。- generatorsの設定を変更することにより、scaffold時に生成するファイルを除くことができます。
- dependabotを使用してライブラリのアップデートを行う。
- 脆弱性のある依存関係に対するアラートを設定することで、gemやjavascriptなどのライブラリに脆弱性が判明した場合に場合に自動でプルリクエストが出るようになります。
- 脆弱性のアラートだけに限らず、ライブラリの依存関係を常に新しいものにしておくことにより、セキュリティの問題が起こった場合に「依存関係ですぐにアップデートができない」などの問題を防ぐことができるでしょう。
識別と認証の失敗
説明
ユーザーのアイデンティ確認、認証そしてセッション管理は、認証関連の攻撃対策として極めて重要です。 もしアプリケーションに次に列挙するような問題があれば、認証に問題があると言えます。
- パスワードリスト攻撃(クレデンシャル・スタッフィング攻撃)のような自動化された攻撃が出来てしまう。パスワードリスト攻撃とは、攻撃者が正当なユーザー名とパスワードの組み合わせを入手して行う攻撃手法のことです。
- ブルートフォース攻撃(総当たり攻撃)などの自動化された攻撃が出来てしまう。
- デフォルトのパスワード、弱いパスワード、良く使われるパスワードが利用できてしまう。たとえば「Password1」や「admin/admin」などです。
- クレデンシャルの復旧やパスワードを忘れた場合のプロセスが弱い、あるいは効果がない。たとえば「秘密の質問」のようなやり方は安全とは言えません。
- パスワードを保存する際に、プレーンテキストのままで保存している、または暗号化して保存している。あるいはハッシュ化して保存していたとしても脆弱なハッシュ関数を利用している。(OWASP Top 10 2017 A3:機微な情報の露出 も参照)
- 多要素認証を採用していない。あるいは間違った使い方をしている。
- セッションIDがURLの一部として露出してしまっている。(URLリライティングなどに注意)
- ログイン後にセッションIDを変更していない。(セッション固定攻撃に注意)
- セッションIDを正しく無効化していない。たとえば、ログアウトした際や一定期間リクエストが無い場合にも、ユーザーセッションや認証トークン(シングルサインオンのトークンなどが多い)が、無効化されない。
防止方法
- 多要素認証を可能な限り実装する。これにより、パスワードリスト攻撃、ブルートフォース攻撃、盗用したクレデンシャルの再利用など多くの自動化された攻撃を防ぐことができます。
- デフォルトのクレデンシャルのままプログラム(サービス)をデプロイしない。特に管理者ユーザーのパスワードをデフォルト設定のままデプロイするのは言語道断です。
- 弱いパスワードを設定していないかチェックする機能を実装する。たとえばパスワードの新規設定や更新時には、「弱いパスワード トップ10,000」などのリストを使って検証する。
- パスワードの「長さ」や「複雑さ」そして「定期的な変更」などのパスワードポリシーについては、NISTガイドライン(800-63b セクション5.1.1:記憶シークレット)や、近代的で根拠に基づくポリシーに沿うようにする。
- 新規登録の場合、クレデンシャルリカバリーの場合、またAPI経由の場合など、どのような場合であってもアカウント列挙攻撃に対して強化されていることを確認する。認証の際にはどのような結果であれ(成功でも失敗でも)同じメッセージを使うようにする。
- ログイン試行回数に制限を設けるか、ログインに繰り返し失敗するようなら徐々に処理を遅延させる。ログインの失敗はすべてログに記録する。そしてパスワードリスト攻撃やブルートフォース攻撃などの攻撃を検知した際には管理者に通知する。
- セッション管理はサーバ側で行い、安全でプログラム言語などに内蔵されているものを使います。ログイン毎にエントロピーの高いランダムなセッションIDを発行するセッション管理機構を利用する。セッションIDはURLに含まれるべきではなく、安全に保管されなければなりません。また、セッションIDはログアウトした際、一定期間アクセスが無い場合、タイムアウト時間を経過した場合には無効にしなければなりません。
Railsでの対策
-
deviseなど、信頼性の高いgemを使用する。
- deviseには、以下のような機能が備わっています。
- Lockableによる同一IDへのリクエスト制限
- Timeoutableによるセッションの破棄
- 適切なパスワードのバリデーションなど、devise-securityを使用することでよりセキュリティを高めることができます。
- deviseには、以下のような機能が備わっています。
- rack-attackにより、同一IPからの連続したリクエストを防ぐ。
-
reCAPTCHAを使用し、botの攻撃を防ぐ。
- recaptchaのようなgemを使用すれば簡単に導入が可能です。
- 認証の失敗時には、常に同じエラーメッセージを表示する。
- ユーザー情報の変更時にパスワードの再入力を求める。
ソフトウェアとデータの整合性の不具合
、ソフトウェアの更新、重要なデータを、CI/CDパイプラインにおいて整合性を検証せずに見込みで進めることによる問題にフォーカスしています。
説明
ソフトウェアとデータの整合性の不具合は、コードやインフラストラクチャが整合性違反から保護されていないことに関連しています。 例として、アプリケーションが信頼されていないソースに由来するプラグインやライブラリ、モジュール、コンテンツデリバリーネットワーク (CDNs) に依存している場合が挙げられます。 安全でないCI/CDパイプラインも、権限のないアクセスや悪意のあるコード、システムののっとりの可能性を高めます。 今では多くのアプリケーションが自動更新の機能を備えていますが、そこで、十分な整合性の検証を行うことなくアップデートがダウンロードされ、信頼済みアプリケーションに対して適用されています。 攻撃者は自前のアップデートをアップロードし、全てのインストール対象に対して配信を行う可能性があります。 他の例として、オブジェクトやデータが攻撃者が目で見て修正することが可能な構造としてエンコードまたはシリアライズされるような場合は、安全でないデシリアライゼーションに対して脆弱であると言えます。
防止方法
- 署名あるいは類似のメカニズムを用いて、ソフトウェアやデータが意図されたソースから取得されたものであることを検証します。
- npmやMavenなど、ライブラリや依存関係が信頼されたリポジトリを使用していることを確認します。
- コンポーネントが既知の脆弱性を含まないことを検証するために、OWASP Dependency CheckやOWASP CycloneDXといったソフトウェアサプライチェーンセキュリティツールが使用されていることを確認します。
- 悪意のあるコードや設定がソフトウェアパイプラインに組み込まれる機会を最小化するために、コードや設定の変更に対するレビュープロセスが確立されていることを確認します。
- CI/CDパイプラインが適切に分離され、設定され、アクセス制御が行われていること、また、ビルドやデプロイのプロセスに至るコードフローの整合性が確保されていることを確認します。
- シリアライズされたデータの改ざんや再生成を検出する何らかの整合性確認やデジタル署名を行うことなしに、信頼されていないクライアントに対して未署名もしくは暗号化されていないシリアライズされたデータを送信しません。
Railsでの対策
- コードベースの対策ではありませんが、Railsでは5.2.4.3 未満、及び6.0.3.1 未満で信頼性のないデータのデシリアライゼーションに関する脆弱性が存在しています。
- Railsを含めライブラリのアップデートを定期的に行いましょう。
セキュリティログとモニタリングの失敗
ロギングとモニタリングはテストが難しく、インタビューやペネトレーションテストで攻撃が検出されたかどうかを確認することがよくあります。 このカテゴリの CVE/CVSS データはあまりありませんが、侵害を検知して対応することは重要です。 とはいえ、このカテゴリーで失敗が起きると、説明責任、可視化、インシデントアラート、フォレンジックなどに影響があります。
説明
アクティブな違反の検出、エスカレーション、および対応を支援するものです。 ロギングとモニタリングがなければ、侵害を検知することはできません。 ロギングや検知、モニタリング、適時の対応が十分に行われないという状況は、いつでも発生します
- ログイン、失敗したログイン、重要なトランザクションなどの監査可能なイベントがログに記録されていない。
- 警告とエラーが発生してもログメッセージが生成されない、または不十分、不明確なメッセージが生成されている。
- アプリケーションとAPIのログが、疑わしいアクティビティをモニタリングしていない。
- ログがローカルにのみ格納されている。
- アラートの適切なしきい値とレスポンスのエスカレーションプロセスが整えられていない、または有効ではない。
- ペネトレーションテストやDAST(dynamic application security testing)ツール(OWASP ZAPなど)によるスキャンがアラートをあげない。
- アプリケーションがリアルタイム、準リアルタイムにアクティブな攻撃を検知、エスカレート、またはアラートすることができない。
- ユーザまたは攻撃者がログやアラートのイベントを閲覧できると、情報の漏えいが発生する可能性があります (A01:2021-アクセス制御の不備 を参照).
防止方法
- ログイン、アクセス制御の失敗、サーバサイドの入力検証の失敗を全てログとして記録するようにする。 ログは、不審なアカウントや悪意のあるアカウントを特定するために十分なユーザコンテキストを持ち、 後日、フォレンジック分析を行うのに十分な期間分保持するようにする。
- 統合ログ管理ソリューションで簡単に使用できる形式でログが生成されていることを確認する。
- 価値の高いトランザクションにおいて、監査証跡が取得されていること。 その際、追記型データベースのテーブルなどのような、完全性を保つコントロールを用いて、改ざんや削除を防止する。
- DevSecOps チームが疑わしい活動をタイムリーに検知して対応できるように、効果的なモニタリングとアラートを確立する。
- NIST(National Institute of Standards and Technology) 800-61 rev 2(またはそれ以降)のような、インシデント対応および復旧計画を策定または採用する。
Railsでの対策
- 適切なログの出力レベルを設定し、認証失敗時のログを取得する。
- 必要に応じてTaggedLoggingを使い、デバッグを簡単にする。
サーバーサイドリクエストフォージェリ (SSRF)
問題の発生率は比較的低いものの、問題が起きた場合のエクスプロイトとインパクトは平均以上のものとなり得ます。
SSRFの詳細はこちらに分かりやすく書かれています
説明
SSRFの欠陥は、Webアプリケーション上からリモートのリソースを取得する際に、ユーザーから提供されたURLを検証せずに使用することで発生します。 ファイアウォールやVPNあるいはその他の種類のネットワークACLによってアプリケーションが保護されている場合であっても、SSRFによりアプリケーションに対して意図しない宛先へ細工されたリクエストを強制的に発行させることができます。
モダンなアプリケーションではエンドユーザーに便利な機能を提供するようになり、アプリケーション側でURLを取得することは珍しい状況ではなくなりました。 そのためSSRFの発生が増加しています。 またSSRFの深刻度も、クラウドサービスやアーキテクチャの複雑性を背景として、段々と大きくなりつつあります。
防止方法
開発者は以下の多層防御の制御の一部ないし全てを実装することにより、SSRFを防ぐことができます。
- ネットワーク層から
- SSRFの影響を減らすために、リモートのリソースへアクセスする機能を分離されたネットワークに切り出します。
- 必須のイントラネット通信を除き全ての通信をブロックするよう、「デフォルト拒否」のファイアウォールポリシーまたはネットワークアクセス制御を強制します。
- アプリケーション層から
- クライアントが提供した全ての入力データをサニタイズし、検証します。
- 明確な許可リスト用いてURLスキーム、ポート、宛先を強制します。
- 生のレスポンスをクライアントに送信しないようにします。
- HTTPのリダイレクトを無効化します。
- DNSリバインディングや"time of check, time of use" (TOCTOU) 競合状態といった攻撃を防ぐために、URLの整合性に注意します。
Railsでの対策
- インジェクションの対策を行う。
- なるべくユーザーが入力したURLに対してリクエストを発効するような機能を適用しない。
- どうしても必要な場合は、バリデーションを行う。
- paperclipの脆弱性など、ライブラリが引き起こす可能性もあるので、定期的にライブラリのセキュリティチェック・アップデートを行う。