CSRFとCORSについて

概要

CSRFとかCORSとかについて理解が薄かったのでメモ

もし自分以外の方は、こちらを見ていただいた方がわかりやすいと思います。

qiita.com

CORSとは?

Same Origin Policyというのがある。

これは、異なるOriginのサイトに対して、Post リクエストなどを送信できるが、レスポンスを読み取ることはできない。

CORSは、この異なるOriginのレスポンスを読み取ることができるようにするための手法。これを使わないと、新たにAPIを作っても、他のドメインからアクセスできない。

参考: CORS (Cross-Origin Resource Sharing) ってなに?

注意としては、リクエストを送信しているため、SameOriginPolicy によるエラーが出たとしても、サーバ側で処理は行われる。

また、HTMLフォーム送信からだと、SameOriginPolicy によるエラーは発生しない。(Javascriptによる通信のものが対象)

Railsの場合

gem を導入する。

RailsのAPIモードでいい感じにCORS設定をする - Qiita

CSRFとは?

サイトを跨いだ偽装リクエストを送信する攻撃

いろいろ対策の方法はあるが、tokenを使った方法が一番良さそう。

一般的な対策

  1. cookieかsessionにtokenを保存する。
  2. 保存されたtokenを form のhidden tag に置いておく
  3. formから送られたtokenを検証して、正しいものであれば正しいリクエストとする

Railsの場合

RailsのCSRF保護を詳しく調べてみた(翻訳)|TechRacho(テックラッチョ)〜エンジニアの「?」を「!」に〜|BPS株式会社

  1. RailsでHTMLをレンダリングする。その際に、HMTL内のmetatagと、session cookiecsrf-tokenが保存される。
  2. form_forやform_tag を作って、formを生成すると、自動でcsrf-tokenが配置される。
  3. そのformからリクエストを送ると、csrf-tokenが検証されて、正しいかを判断する。

Rails + Vueを使う場合

VueからAPIに通信を行う時はformを利用しない。

そのため、axiosを用いて、csrf tokenをheaderに追加する。

上述した通り、Railsのmeta tagには、csrf_token が置かれているので、下記のように取得してリクエストを送ればOK。

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

参考: 【Vue】axiosで、デフォルトでCSRFトークンを設定できるようにする - Qiita

Nuxt(SSR)の場合

  1. NuxtでSSRする際にcsrf token を発行する
  2. その発行されたtokenをstoreに保存しておく
  3. APIを叩く時に、storeに保存したtokenを一緒に付け加えてrequestを送る。
  4. Expressがtokenの検証を行う

参考: Nuxt.jsでcsrfTokenを埋め込みセキュアな通信を行う - Qiita

その他の対策

もしCookieで認証したあとだけを保護したいのならば、違うドメインからCookieを遅れないようにする方法も良さそう。

Cookie の性質を利用した攻撃と Same Site Cookie の効果 | blog.jxck.io