CSRF攻撃とrailsでの対策方法

Rails

はじめに

CSRF攻撃(クロスサイトリクエストフォージェリ)は、ユーザーが意図しない操作をウェブサイト上で実行させられるセキュリティ攻撃の一種です。この攻撃は、ユーザーがすでに何らかのウェブサイトにログインしている状態を悪用し、そのユーザーのブラウザを使って悪意のある操作を行わせます。

CSRF攻撃の仕組み

CSRF攻撃は、以下のステップで実行されます。

  1. ユーザー認証: ユーザーが信頼できるウェブサイト(例えば、オンラインバンキングサイト)にログインし、認証済みのセッションを持っています。
  2. 攻撃のトリガー: 攻撃者が用意した悪意のあるウェブサイトや電子メールに、ユーザーがアクセスします。このページには、攻撃者が意図したアクションを実行するためのリクエストを自動的に送信するJavaScriptや自動送信されるフォームが含まれています。
  3. 無意識のリクエスト送信: ユーザーのブラウザは、ユーザーがクリックすることなく(またはユーザーがクリックしたつもりで)このリクエストを信頼できるサイトに送信します。リクエストにはユーザーの認証情報(クッキーなど)が自動的に含まれるため、信頼できるサイトはこのリクエストを正当なものと見なします。
  4. 悪意ある操作の実行: リクエストが処理されると、攻撃者の意図した通りの操作(例えば、パスワードの変更、送金など)が実行されます。

CSRF攻撃の具体例

例として、ある銀行のウェブサイトがCSRF攻撃のターゲットになった場合を考えます。ユーザーが銀行のウェブサイトにログインしてセッションを開始した後、攻撃者は次のようなリンクを含むメールをユーザーに送ります。

<a href="https://bank.com/transfer?to=attacker_account&amount=1000">Click here for a free coupon!</a>

このリンクが「無料クーポン」などの誘惑文句で飾られていた場合、ユーザーがリンクをクリックすると、銀行のサイトはユーザーが送金リクエストをしたと解釈し、攻撃者指定のアカウントに1000ドルを送金するかもしれません。

RailsでのCSRF対策

1. フォームヘルパーによるCSRFトークンの挿入

Railsのフォームヘルパーを使用する場合、自動的にCSRFトークンがフォームに含まれます。この挿入はform_forform_withヘルパーが使われる際に行われ、生成されるHTMLフォームには隠しフィールドとしてCSRFトークンが含まれます。以下のようなフォームを作成した場合、CSRFトークンが自動的に挿入されます。

<%= form_for :message, url: messages_path do |form| %>
  <%= form.label :content %>
  <%= form.text_area :content %>
  <%= form.submit "Send" %>
<% end %>

2. protect_from_forgery

protect_from_forgeryは、フォームやAjaxリクエストから送信されたCSRFトークンを検証するために使われます。この設定がアプリケーションのApplicationControllerに含まれている場合、すべての派生コントローラで有効になります。トークンがリクエストに含まれていないか、トークンが不正な場合(例えば一致しない場合)、Railsは例外を発生させてリクエストを拒否します。

以下は、Railsアプリケーションにおけるprotect_from_forgeryの使用例です。

class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
end

この設定により、アプリケーション内のすべてのコントローラがこのCSRF保護機構を継承します。もしCSRFトークンが一致しない場合は、例外が発生し、リクエストは拒否されます。

3. JavaScriptリクエストでのCSRFトークンの取り扱い

Railsが提供するrails-ujsライブラリは、Ajaxリクエストに自動的にCSRFトークンを付加します。しかし、カスタムJavaScriptを使用してAjaxリクエストを行う場合は、CSRFトークンを手動で追加する必要があります。

const token = document.querySelector('meta[name="csrf-token"]').getAttribute('content');

fetch('/some_endpoint', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-CSRF-Token': token
  },
  body: JSON.stringify({ key: 'value' })
}).then(response => {
  return response.json();
}).then(data => {
  console.log(data);
});

このスクリプトでは、HTMLドキュメントのmetaタグからCSRFトークンを取得し、フェッチAPIを使用してサーバーにPOSTリクエストを送信する際に、トークンをHTTPヘッダーに含めています。

まとめ

CSRF攻撃は、ユーザーが知らないうちに認証済みのセッションを利用して不正な操作を行わせるセキュリティ攻撃です。この攻撃は、信頼されたサイトに対してユーザーのブラウザを通じて悪意のある操作を強制的に実行させます。RailsではCSRF対策としてprotect_from_forgeryがあり、CSRFトークンを検証を行うことでCSRF攻撃を防ぐことができます。これにより、不正なリクエストが拒否され、アプリケーションの安全性が向上します。

コメント

タイトルとURLをコピーしました