CSRF(クロスサイトリクエストフォージェリ)
CSRFのことをシーサーフって呼んだりもします。
攻撃者が用意した偽造サイトを用いて、ユーザーが意図していないリクエストを強制的に行わせる攻撃手法です。
ログイン状態のユーザーを狙って行われることが多いです。
下記の例は架空の銀行システムです。
ログイン機能があるので、基本的に各機能はログイン済みのユーザーからのリクエストしか受け付けません。
しかし、CSRF保護をしていない場合このような事が起こり得ます。
(例)
①Aさんが銀行システムにログイン
↓
②攻撃者が悪意あるリンク付きのメールをAさんに送る。
↓
③Aさんがメールのリンクをクリック
↓
④Aさんがリンクのサイトを開いた瞬間に銀行のシステムに悪意のあるリクエストを発生させる。
例えば、「Aさんから100万円を攻撃者の口座に送金する」ものとします。
↓
⑤銀行システムからすると、認証済みの(ログイン済みの)Aさんのブラウザから送信されたリクエストなので、Aさんからのリクエストだと誤認してリクエストを処理。
↓
⑥攻撃者はAさんから100万円騙し取ることに成功。
現実に金融系のシステムでこんなセキュリティがガバガバなことはまずありませんが、これを防ぐ為にCSRF保護を行う必要があります。
Same Origin Policy(同一オリジンポリシー)
攻撃者が用意したサイトは、銀行システムと同一オリジンでは無いのでそもそもリクエストを飛ばせないのではないか?と思いましたが違います。
同一オリジンポリシーとは、サーバのリソースを同一オリジンでしか共有出来ないようにするものです。
つまり、ブラウザ側の不正なレスポンスを処理しない為のセキュリティ機能であって、リクエストを制限するものではありません。
同一オリジンでなくてもGETリクエストやPOSTリクエストはサーバーまで届きます。
そのレスポンスをブラウザが処理出来ないというだけであって、CSRFのようにリクエストをサーバーに処理させることが目的なのでレスポンスは受け取れなくても攻撃者からしたら関係ないことです。
CORS(Cross-Origin Resource Sharing)
しかし、昨今のSPAではブラウザ側とAPIでドメインが異なるシチュエーションがよくあります。
例えば、ローカルの開発環境でも、フロントのReactはポート3000、APIのLaravelはport8000のようにポートが異なるケースです。
ポートが異なるのであれば異なるドメインです。
このようなシチュエーションでCross-Origin Resource Sharingが活躍します。
サーバ側でホワイトリスト形式で許可して通信が出来るようにします。
誰もが一度はCORSエラーに悩まされたことがあるかと思いますが、CORSは本来ありがたいものなんです。
ブラウザからsessionIDの送り方
javascriptでCookieの中身を見られないならどうやってセットするのか?
axiosでwithCredentials = trueを設定することで、リクエストにCookieに保持したセッションを含めて送ってくれるようになります。
sessionIDの守り方
サーバからセッションIDをブラウザに返す際、domain属性オプションを指定した上でブラウザに渡す。ブラウザはそれをCookieに保存します。
指定したドメインでなければ、withCredentials = trueを設定してもリクエストに含めることが出来なくなります。これで攻撃者がwithCredentials = trueを指定していてもリクエストにCookieのセッションIDを入れることが出来ないので安心です。
最後に
徳丸さんの以下の記事が分かりやすいので一読オススメいたします。