kanachi-blog

notionでの公開記事をastro-notion-blogを使って公開するよ

CSRFトークンによってCSRF攻撃を防げる仕組み

疑問

  • CSRFトークンをCORS設定とは別に生成して、生成したトークンをヘッダーに付与してサーバーサイド側で確かめきゃいけないという工程がなぜ必要なのか?
  • CSRF攻撃は一見CORS設定によって阻止できそうなのにできない理由は何故か

CSRF攻撃とは?

CSRF攻撃とは、悪意のあるサイトが、ユーザーがログインしている別のサイト(信頼されたサイト)上でリクエストを強制的に実行する攻撃手法のことです。この攻撃が成功すると、攻撃者はユーザーが信頼するサイトで、ユーザーの意図せずに行動を行わせることができます。

何故これが可能なのか?

Cookieはブラウザに対して発行される

Cookie は、ウェブサイトによってウェブブラウザーを通じて訪問者のコンピューター上に残される小さな情報です。
Cookie はウェブサイトのウェブ体験を個人化するために使用されます。ウェブサイトにアクセスする際のユーザーの設定や入力を含む場合もあります。ユーザーはウェブブラウザーを設定して Cookie の受け入れや拒否、削除を行うことができます。

このため、攻撃者のウェブサイトから送信されるリクエストも、ブラウザが保持しているログイン情報(クッキー)を使用します。結果として、サーバーから見るとユーザー自身が送信したリクエストのように見えてしまいます。

具体例①

例えば、あるユーザーが自分のインターネットバンキングにログインしているとき、そのまま別のタブで攻撃者が用意したウェブサイトを開いたとします。この悪意のあるウェブサイト上には、「ここをクリックすると1000ドルが当たる」といった誘導があり、ユーザーがそれをクリックすると、裏でそのユーザーに代わってインターネットバンキングへの送金リクエストが送られてしまいます。

この送金リクエストは、ブラウザが保持しているユーザーのログインセッションを使用しており、インターネットバンキングのサーバーから見ると、これはユーザー自身が行ったリクエストのように見えてしまいます。

具体例②

CSRF (クロスサイトリクエストフォージェリー、Cross-Site Request Forgery) は、信頼されたユーザーになりすまし、ウェブサイトに対して不正なコマンドを送信する攻撃です。

例えば、どこかへ移動すると称したリンクの URL 内に、悪意のある引数を含めたりすることで実行されます。

<img src="https://www.example.com/index.php?action=delete&id=123" />

https://www.example.com で何らかの権限を持ったユーザーでは、 <img> 要素が https://www.example.com の中になくても、気づかないうちに https://www.example.com への操作を実行してしまいます。

CSRF を防止するには、 RESTful API を使用する、セキュリティトークンを追加するなど、様々な方法があります。

CSRFトークンの役割

しかし、このような攻撃はCSRFトークンがあると防ぐことができます。

各セッションごとにユニークなCSRFトークンが生成され、それをサーバーとクライアントの間で共有する

  • サーバー側で特定のリクエストに対してCSRFトークン生成して、それをレスポンスで返す
  • フロント側でレスポンスから受け取って、それをヘッダーに付与する。
  • ユーザーが正当なリクエストを行う際には、そのリクエストのヘッダーにはCSRFトークンが含まれています。
  • サーバーは受け取ったリクエストの中のCSRFトークンを確認し、それが正しいものかどうかを検証します。
CSRFトークンをヘッダーに付与する理由

HTTPヘッダーとは

HTTP ヘッダーは、 HTTP リクエストおよび HTTP レスポンスのフィールドで、メッセージや本文のセマンティクスを変更したり、より詳細に説明したりするための追加情報を渡します。

このトークンがリクエストに含まれている場合、サーバーはそのトークンを検証し、リクエストが本当にユーザー自身によるものであることを確認できます。このトークンは通常、リクエストのヘッダーに付与されます。

ヘッダーはHTTPリクエストと対応しています。したがって、ヘッダーにCSRFトークンを含めることで、CSRF攻撃を防ぐことが可能となります。

CSRFトークンによる攻撃防止

上述したような攻撃の場合、攻撃者はそのユーザーのCSRFトークンを知ることができません。そのため、攻撃者がユーザーに代わってリクエストを送信しようとしても、そのリクエストには正しいCSRFトークンがヘッダーに含まれていないため、サーバーはそのリクエストを拒否します。

このように、CSRFトークンの仕組みを用いることで、攻撃者がユーザーになりすましたリクエストを送るCSRF攻撃を防ぐことができます。

CSRF攻撃をCORS設定で防げない理由

CORS設定

CORS (オリジン間リソース共有、 Cross-Origin Resource Sharing) は、 HTTP ヘッダーの転送で構成されるシステムであり、ブラウザーがオリジンをまたいだリクエストのレスポンスに、フロントエンドの JavaScript コードがアクセスすることをブロックするかどうかを決めるものです。

同一オリジンセキュリティポリシーは、既定でリソースへのオリジン間のアクセスを禁止している

CORS設定をすることでウェブサーバーに、リソースへのオリジンをまたいだアクセスを許可することができる

CORS設定でCSRF攻撃を防げない理由

CORSの設定だけでCSRF攻撃を防ぐことは困難であり、一部の場合では無力となる。たとえば、"simple request"(単純リクエスト)であるGETリクエストやPOSTリクエストはCORSプリフライトリクエストが発生せず、CORSポリシーによる制御を受けません。そのため、攻撃者がユーザーのブラウザを利用して単純リクエストを送信することで、CORSの制御を回避することが可能です。

したがって、CORSとCSRFトークンはそれぞれ異なる脅威に対する対策として存在し、一方だけでなく、双方を適切に設定・使用することがウェブアプリケーションのセキュリティを保つために重要

単純リクエストとは

単純リクエスト(Simple Request)は特定の条件を満たすリクエストのことで、ブラウザによって自動的に送信されます。主にGET、HEAD、POSTメソッドを使用し、設定されたヘッダーが特定の許可されたセットの中にある場合に該当します。

単純リクエストとCORS

単純リクエストは、CORSのプリフライトリクエスト(安全性の確認のためブラウザが自動的に送信するリクエスト)をトリガーしません。つまり、CORSポリシーが適用される前に、単純リクエストはサーバーに送信されます。しかし、CORSポリシー自体は単純リクエストに対しても適用され、サーバーのCORS設定がリクエストを許可しない場合、ブラウザはサーバーからのレスポンスをブロックします。

CORS設定によるブロック

CORS設定によるブロックはブラウザ側で行われるため、リクエスト自体はサーバーに到達します。その結果、リクエストが副作用(例:データの変更)を引き起こす場合、その副作用は発生します。

以上の理由から、CORS設定だけではCSRF攻撃を完全に防ぐことはできない。したがって、CSRFトークンなどの他の防御策が必要となる。