How to Implement CSRF Protection

CSRF - or Cross-site request forgery - is a method by which a malicious user attempts to make your legitimate users unknowingly submit data that they don't intend to submit.

CSRF (またはクロスサイト リクエスト フォージェリ) は、悪意のあるユーザーが正当なユーザーに無意識のうちに送信するつもりのないデータを送信させようとする方法です。

CSRF protection works by adding a hidden field to your form that contains a value that only you and your user know. This ensures that the user - not some other entity - is submitting the given data.

CSRF 保護は、あなたとあなたのユーザーだけが知っている値を含む隠しフィールドをフォームに追加することによって機能します。これにより、他のエンティティではなく、ユーザーが特定のデータを送信することが保証されます。

Before using the CSRF protection, install it in your project:

CSRF 保護を使用する前に、プロジェクトにインストールします。
1
$ composer require symfony/security-csrf

Then, enable/disable the CSRF protection with the csrf_protection option (see the CSRF configuration reference for more information):

次に、csrf_protection オプションを使用して CSRF 保護を有効/無効にします (詳細については、CSRF 構成リファレンスを参照してください)。
  • YAML
    YAML
  • XML
    XML
  • PHP
    PHP
1
2
3
4
# config/packages/framework.yaml
framework:
    # ...
    csrf_protection: ~

The tokens used for CSRF protection are meant to be different for every user and they are stored in the session. That's why a session is started automatically as soon as you render a form with CSRF protection.

CSRF 保護に使用されるトークンは、ユーザーごとに異なるものであり、セッションに保存されます。そのため、CSRF 保護を使用してフォームをレンダリングするとすぐに、セッションが自動的に開始されます。

Moreover, this means that you cannot fully cache pages that include CSRF protected forms. As an alternative, you can:

さらに、これは、CSRF で保護されたフォームを含むページを完全にキャッシュできないことを意味します。別の方法として、次のことができます。
  • Embed the form inside an uncached ESI fragment and cache the rest of the page contents;
    キャッシュされていない ESI フラグメント内にフォームを埋め込み、残りのページ コンテンツをキャッシュします。
  • Cache the entire page and load the form via an uncached AJAX request;
    ページ全体をキャッシュし、キャッシュされていない AJAX リクエストを介してフォームをロードします。
  • Cache the entire page and use hinclude.js to load the CSRF token with an uncached AJAX request and replace the form field value with it.
    ページ全体をキャッシュし、hinclude.js を使用して CSRF トークンをキャッシュされていない AJAX リクエストでロードし、フォームフィールドの値をそれに置き換えます。

CSRF Protection in Symfony Forms

Forms created with the Symfony Form component include CSRF tokens by default and Symfony checks them automatically, so you don't have to do anything to be protected against CSRF attacks.

Symfony フォーム コンポーネントで作成されたフォームにはデフォルトで CSRF トークンが含まれており、Symfony はそれらを自動的にチェックするため、CSRF 攻撃から保護するために何もする必要はありません。

By default Symfony adds the CSRF token in a hidden field called _token, but this can be customized on a form-by-form basis:

デフォルトでは、Symfony は CSRF トークンを _token という隠しフィールドに追加しますが、これはフォームごとにカスタマイズできます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// src/Form/TaskType.php
namespace App\Form;

// ...
use App\Entity\Task;
use Symfony\Component\OptionsResolver\OptionsResolver;

class TaskType extends AbstractType
{
    // ...

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([
            'data_class'      => Task::class,
            // enable/disable CSRF protection for this form
            'csrf_protection' => true,
            // the name of the hidden HTML field that stores the token
            'csrf_field_name' => '_token',
            // an arbitrary string used to generate the value of the token
            // using a different string for each form improves its security
            'csrf_token_id'   => 'task_item',
        ]);
    }

    // ...
}

You can also customize the rendering of the CSRF form field creating a custom form theme and using csrf_token as the prefix of the field (e.g. define {% block csrf_token_widget %} ... {% endblock %} to customize the entire form field contents).

また、CSRF フォーム フィールドのレンダリングをカスタマイズして、カスタム フォーム テーマを作成し、フィールドのプレフィックスとして csrf_token を使用することもできます (たとえば、{% block csrf_token_widget %} ... {% endblock %} を定義して、フォーム フィールドの内容全体をカスタマイズします)。

CSRF Protection in Login Forms

See Security for a login form that is protected from CSRF attacks. You can also configure the CSRF protection for the logout action.

CSRFattacks から保護されているログイン フォームについては、セキュリティを参照してください。ログアウト アクションの CSRF 保護を設定することもできます。

Generating and Checking CSRF Tokens Manually

Although Symfony Forms provide automatic CSRF protection by default, you may need to generate and check CSRF tokens manually for example when using regular HTML forms not managed by the Symfony Form component.

Symfony フォームはデフォルトで自動 CSRF 保護を提供しますが、たとえば Symfony フォーム コンポーネントによって管理されていない通常の HTML フォームを使用する場合など、手動で CSRF トークンを生成してチェックする必要がある場合があります。

Consider a HTML form created to allow deleting items. First, use the csrf_token() Twig function to generate a CSRF token in the template and store it as a hidden form field:

アイテムを削除できるように作成された HTML フォームを考えてみましょう。まず、csrf_token() Twig 関数を使用してテンプレートに CSRF トークンを生成し、非表示のフォーム フィールドとして保存します。
1
2
3
4
5
6
<form action="{{ url('admin_post_delete', { id: post.id }) }}" method="post">
    {# the argument of csrf_token() is an arbitrary string used to generate the token #}
    <input type="hidden" name="token" value="{{ csrf_token('delete-item') }}"/>

    <button type="submit">Delete item</button>
</form>

Then, get the value of the CSRF token in the controller action and use the isCsrfTokenValid() method to check its validity:

次に、コントローラ アクションで CSRF トークンの値を取得し、isCsrfTokenValid() メソッドを使用してその有効性を確認します。
1
2
3
4
5
6
7
8
9
10
11
12
13
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
// ...

public function delete(Request $request): Response
{
    $submittedToken = $request->request->get('token');

    // 'delete-item' is the same value used in the template to generate the token
    if ($this->isCsrfTokenValid('delete-item', $submittedToken)) {
        // ... do something, like deleting an object
    }
}

CSRF Tokens and Compression Side-Channel Attacks

BREACH and CRIME are security exploits against HTTPS when using HTTP compression. Attackers can leverage information leaked by compression to recover targeted parts of the plaintext. To mitigate these attacks, and prevent an attacker from guessing the CSRF tokens, a random mask is prepended to the token and used to scramble it.

BREACH と CRIME は、HTTPcompression を使用する場合の HTTPS に対するセキュリティ エクスプロイトです。攻撃者は、圧縮によって漏洩した情報を利用して、平文の目的の部分を復元できます。これらの攻撃を軽減し、攻撃者が CSRF トークンを推測するのを防ぐために、ランダム マスクがトークンの前に追加され、それをスクランブルするために使用されます。