[Laravel] CSRF対策の挙動を追ってみた。

2019年6月7日ITLaravel, PHP

Laravel & Blade で開発していたら、よく見かける

{{ csrf_field() }}

こちらの挙動の追っかけをしてみました。

まずBladeでこれを書けば、出力される時は下記のようになります。

<input type="hidden" name="_token" value="7753xoabfc5SK4hv1mJo3NGwC47DLZ2ZbmGoJihX">

input タグで type は hidden ですね。フォームデータを送信すればキーは _token、 value は ハッシュ値がリクエストされます。

CSRF は CrossSite Request Forgery (偽造)という意味で、

クロスサイト・リクエスト・フォージェリ(以下CSRF)とは、リクエストを偽装することで、あたかも通常のユーザからの操作のように見せかけて、ユーザの不利益になるような処理を行う手法です。

5分で完璧に理解できる!Webシステムのセキュリティ対策

ログイン状態のユーザーに偽装できる、なりすますことができる、、

(例えば、amazon にログインしていて、ログイン状態を偽装されたら、他人のカードで買い物できる、など)

これの対策として、Laravel では、、、

各セッションごとに、CSRF「トークン」を自動的に生成しています

webミドルウェアグループに含まれている、VerifyCsrfToken ミドルウェアが、リクエスト中のトークンとセッションに保存されているトークンが一致するか、確認しています。

Laravel 5.8 CSRF 保護

引用元:Laravel 5.8 CSRF 保護

csrf_field() で生成された _token とそのvalue、セッションに入ってるトークンを VerifyCsrfToken ミドルウェアが一致しているかセッションごとにチェックしているようです。

一致しているかのチェックしてるかは、、

Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php

/**
 * Handle an incoming request.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Closure  $next
 * @return mixed
 *
 * @throws \Illuminate\Session\TokenMismatchException
 */
public function handle($request, Closure $next)
{
    if (
        $this->isReading($request) ||
        $this->runningUnitTests() ||
        $this->inExceptArray($request) ||
        $this->tokensMatch($request)
    ) {
        return $this->addCookieToResponse($request, $next($request));
    }

    throw new TokenMismatchException;
}

handle メソッドで、いくつかチェックしてますが、トークン一致のチェックは tokensMatch メソッドですね。

/**
 * Determine if the session and input CSRF tokens match.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return bool
 */
protected function tokensMatch($request)
{
    $token = $this->getTokenFromRequest($request);

    return is_string($request->session()->token()) &amp;&amp;
           is_string($token) &amp;&amp;
           hash_equals($request->session()->token(), $token);
}

それぞれのトークンが文字列かチェックして、hash_equals で「2つの文字列が等しいかどうか、同じ長さの時間で」比較します。

参考:

こうやってセッション毎にリクエストとセッションのそれぞれのトークンが一致してるかチェックして、ログインユーザーがなりすましでないかチェックしてたんですね。

以上になります。

スポンサーリンク

Posted by nobuhiro harada