NestJSでCSRF対策

CSRF(Cross-site Request Forgery)とは

CSRF(Cross-site Request Forgery)とは、Webシステムを悪用したサーバー攻撃の一種です。攻撃用のWebページを予め用意して、システムに意図しないリクエストを強要します。システムの脆弱性をつくことで、予期せぬ情報発信やログイン中のシステムでの設定変更などの被害に繋がります。
CSRFの恐ろしい点は、予期しないリクエストによりサービスの提供側も、またリクエストを送ってしまった側にも被害が出る点が挙げらます。意図しない犯行声明をCSRFによりWeb上に投稿され、えん罪で逮捕されるケースが考慮されます。
CSRFの説明は複雑なので、本記事ではザックリとした流れと対策を簡潔に解説していきます。詳細を確認したければ以下のサイトをご確認ください。

CSRFの流れ

①会員サイトにログインする

攻撃者が対象としているWebサイト(以下、「サイトA」と表記)にユーザがログインします。サイトAのWebサーバはユーザが入力したIDとパスワードが正しいかどうかをチェックします。

②セッションIDを発行する

サイトAのWebサーバはユーザが入力したログイン情報が正確であればセッションIDを払い出します。そして、利用者にログイン成功のレスポンス(201メッセージ)とともに払い出したセッションIDを返却します。
セッションIDはCookieを利用しクライアント側(ユーザ側)に保存されます。

③ログイン状態を維持したまま別のサイトを閲覧する

サイトAにログインしたユーザが、サイトAからログアウトせずに別のサイトを閲覧したとします。これはよくあることでしょう。
もし、たまたま(もしくは「なりすましメール」等で誘導された)閲覧したサイトが攻撃者が用意したサイト(有害なサイト)だったらどうなるでしょう?

④有害なサイトのリンクやボタンを押す

サイトAにログインした状態のまま、攻撃者が用意したサイトを閲覧し、そのサイトにあるリンクやボタンをクリックすると、サイトAのWebサーバに利用者が意図していない情報が送信されてしまいます。
この時、ユーザ側のCookieに保存されていたセッションIDも自動的に送信されます。それゆえ、サイトAのWebサーバはセッションIDが正しいので正常のリクエストと判断し、リクエストを受理します。

⑤ユーザの意図しない処理が勝手に行われる

悪意のある攻撃者が用意した有害なサイトにより、ユーザの意図しない情報がサイトAのWebサーバに送信され、会員サイトからの強制退会、SNSの強制投稿や不正送金などの処理が行われてしまいます。
これがCSRFのザックリとした流れになります。

参考サイト

実装方法

まず最初に必要なパッケージをインストールします。
npm i --save csurf
注意
csurfのドキュメントによると、このミドルウェアはセッションミドルウェアまたはcookie-parserのどちらかが最初に初期化されることを必要とします。詳しい説明はそのドキュメントを参照してください。
インストールが完了したら、csurfミドルウェアをグローバルのミドルウェアに適応させます。
import * as csurf from 'csurf';
// ...
// somewhere in your initialization file
app.use(csurf());