【Laravel】LaravelのCSRF対策の仕組み
こんにちは。今回はCSRF Tokenについて説明します。
CSRFとは
CSRFとはWEBアプリケーションに対するサイバー攻撃の一種です。Cross Site Request Forgery攻撃の各単語の頭文字をつなげてCSRFです。「シーサーフ」と読みます。
攻撃者が作成した悪意のあるリクエストを、ログインした状態のユーザーに実行させる攻撃です。リクエスト強要とも言われており、ユーザーが知らない間に攻撃者が用意したリクエストを送信してしまい、後から被害に遭ったことを知るケースが多いという特徴があります。攻撃者は、WEB上にリンクや画像に悪意のあるリクエストを配置しておきます。SNSなどにログインした状態のユーザーがそれらをクリックすることで、攻撃者が仕込んだリクエストが送信されるという仕組みです。
指定したユーザーに送金するAPIを例に考えてみます。xxx.comというWEBアプリケーションはsend-moneyというAPIを公開しております。userパラメータで指定したユーザーに、kingakuパラメータで指定した額を送金します。Aさんに100円送金するリクエストは以下の通りです。
http://xxx.com/send-money?user=A?kingaku=100
ログイン中の場合のみAPIを使用することができます。このAPIにたいしてCSRF攻撃を行ってみます。
攻撃者をBとします。Bに対して1000円送金するAPIを用意します。
http://xxx.com/send-money?user=bbb?kingaku=1000
このAPIを自分ではない誰かに実行させようと考えます。
攻撃者BはこのURLを実行させるために、罠サイトを作り、リンクや画像などにURLを組み込みます。システムにログインしている誰かが罠サイトのリンクや画像をクリックすることで偽造APIにリクエストが実行され処理が実行されます。こうしてユーザーが知らない間に偽造APIを実行し、CSRFが成功してしまうのです。
ではCSRFはどのように防止すればよいのでしょうか。CSRFは、WEBサービスの提供側が対策をすることで防止できる攻撃です。Laravelを使用する場合、どのように対策するかをみていきましょう。
LaravelのCSRF対策とは
結論から述べると、LaravelにはCSRF対策機能が予め搭載されているので、開発者自身はその機能を組み込むだけで対策が可能です。組み込むだけで実現できるので、どのような仕組みで対策されるかは普段意識しないかもしれません。とはいえどのような仕組みでLaravelがCSRF対策を実装しているかは知っておくと良いと思いますので、これから解説していきます。
毎リクエスト トークンを発行し、照合する
Laravelはリクエスト毎にトークンと呼ばれるランダムな文字列を生成します。クライアントは次回のリクエスト時に発行されたトークンをサーバーに送り返します。サーバーはトークンを受け取り、発行したトークンと照合します。トークンの文字列が合致する場合、正当なユーザーからのリクエストとみなして処理を続行します。
トークンはどのように管理されるか
Laravelが発行したトークンは、HTML内にHiddenとして埋め込まれます。Hiddenとして埋め込むにはbladeに以下のコードを埋め込みます。
@csrf
この簡単なコードを埋め込むと、以下のHTMLが生成され、トークンが埋め込まれます。
<input type="hidden" name="_token" value="Fzshww7Z8M9doUpT5Az09f96lr5i7jDtMPArf9ob">
生成されたトークンがhiddenのvalue属性に設定されます。フォーム送信時にこのトークンも送信され、Laravel側で照合する仕組みです。
なぜCSRFを防ぐことができるのか
リクエスト毎に異なるトークンが発行されるからです。この仕組みを破るためには、毎回発行されるトークンを攻撃者は知る必要があり、なおかつ罠サイトに設定する必要があります。リクエストは短時間で何度も発行されるのでトークンの値は変わり続けますので、たとえ攻撃者がトークンを入手できたとしても、その短時間で罠サイトに攻撃を仕込むことは難しいです。
まとめ
今回はLaravelのCSRF対策について解説しました。LaravelではトークンをHTMLに埋め込むだけで簡単に対策を設定することがでるので非常に便利です。普段意識することも無いので、仕組みまではよくわからないという人も多いかと思います。ただ、セキュリティ対策について説明を求められる場合もあるかと思いますので、記事にまとめてみました。お役に立てれば幸いです。
ディスカッション
コメント一覧
まだ、コメントがありません