質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
CSRF

クロスサイトリクエストフォージェリ (Cross site request forgeries、CSRF)は、 外部Webページから、HTTPリクエストによって、 Webサイトの機能の一部が実行されてしまうWWWにおける攻撃手法です。

Q&A

解決済

3回答

3149閲覧

CSRF対策のやり方

gogogolang

総合スコア1

CSRF

クロスサイトリクエストフォージェリ (Cross site request forgeries、CSRF)は、 外部Webページから、HTTPリクエストによって、 Webサイトの機能の一部が実行されてしまうWWWにおける攻撃手法です。

1グッド

2クリップ

投稿2021/06/07 20:11

CSRF対策についてです。

一般的にWebアプリケーションにはCSRF対策がされるかと思います。
いろいろ調べた結果、
①ユーザーのログイン時にクッキーにハッシュ値(トークン)を登録する
②hiddenフィールドもしくはリクエストヘッダーにXSRF-TOKENにクッキーのトークン値を設定し、リクエスト(Post)
③サーバー側では、クッキーの値とリクエストのトークン値が一致することを確認する

【質問】
このような流れになるのかと思いますが、
1、ユーザーの新規作成時(つまりログイン前)はクッキーにトークン値がないので、この場合は一般的にどのような実装になっているのでしょうか?
2、②でのhiddenもしくは、リクエストヘッダーのどちらにトークンを付与するのが一般的ですか?また理由も教えていただけると助かります。

また認識間違いがありましたら、教えていただけますと助かります。

tomy-c👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

1、ユーザーの新規作成時(つまりログイン前)はクッキーにトークン値がないので、この場合は一般的にどのような実装になっているのでしょうか?

ログイン前では必ずしもCSRF対策をする必要はありませんが、したいのであれば、入力フォームでトークンを発行してクッキーとHidden等にセットすれば対応可能です。

2、②でのhiddenもしくは、リクエストヘッダーのどちらにトークンを付与するのが一般的ですか?また理由も教えていただけると助かります。

「一般的」というのは難しい質問ですが、古典的なウェブアプリではhiddenを使いました。その理由は、JavaScriptなしに実装できるからです。安全性という点ではリクエストヘッダの方が安全で、その理由は、リクエストヘッダの方が攻撃が難しくなるからです。その「難しくなる理由」は下記の本のP416に書いてあります(一部を引用)。

この問題の緩和のためにも、トークンパラメータの送信にHTTPリクエストヘッダを用いることをお勧めします。クロスオリジン通信でカスタムリクエストヘッダを付与するためには、プリフライトリクエストで許可される必要があるため、API側のプリフライトリクエストの処理にバグがなければ、CSRF攻撃は成立しません。

体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 脆弱性が生まれる原理と対策の実践

恐らくここを読んだだけでは理解できないと思います。なので、CSRF対策は自分で作ろうとせず、アプリケーションフレームワーク(Ruby on RailsやLaravel、.NET等)の機能を素直に使うことをお勧めします。

投稿2021/06/08 08:30

ockeghem

総合スコア11701

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/06/08 08:55

> ログイン前では必ずしもCSRF対策をする必要はありませんが、 (釈迦に説法ですが)アプリケーションの性格にもよると思います。 例えば、匿名掲示板のような使用用途であれば、ログイン前提ではなく、すべての投稿に対して対策を行った方が良いと思います。
退会済みユーザー

退会済みユーザー

2021/06/08 08:59

あーでも、質問の文脈だと正しいのか^^; 失礼しました。
gogogolang

2021/06/08 11:05

1、2の回答ありがとうございます。 特に2についてはやっと理解できました。やはり使い分ける理由はあるんですね。 上記本購入してみます。 ありがとうございます。
guest

0

ベストアンサー

ASP.NET MVC の場合も質問者さんが書かれた機能がフレームワークに組み込まれていて、質問 1, 2 はどうなっているかと言うと、

1、ユーザーの新規作成時(つまりログイン前)はクッキーにトークン値がないので、この場合は一般的にどのような実装になっているのでしょうか?

トークンはランダムに生成されます。なので、ログインしているか否かに関係なくトークンは発行されます。

2、②でのhiddenもしくは、リクエストヘッダーのどちらにトークンを付与するのが一般的ですか?また理由も教えていただけると助かります。

hidden です。

理由は、それを書いてある Mictosoft のドキュメントは見つけられなかったので不明ですが、普通に考えてサーバーがランダムに生成したトークンをリクエストヘッダに含めるのは無理があるからだと思います。

ただし、フォームデータを POST するのではなく、例えば、AJAX で JSON 文字列を POST するような場合は (hidden は送れない場合は)、リクエストヘッダを使う方法も用意されているそうです。詳しくは以下の記事を見てください。

https://docs.microsoft.com/ja-jp/aspnet/web-api/overview/security/preventing-cross-site-request-forgery-csrf-attacks#anti-csrf-and-ajax

【追記】

下の 2021/06/09 15:19 の私のコメントで「ご参考に、あとで、ログイン有り無しの時のクッキーがどうなっているか Fiddler で見た画像を回答欄に貼っておきます」と書いた件です。

編集画面で編集したあと結果を POST した場面です。__RequestVerificationToken が CSRF 対策トークンのクッキー、.AspNet.ApplicationCookie は認証クッキーです。

ログイン無し

ログインしてなくとも CSRF 対策トークンのクッキーは編集画面が表示された際に受け取っていますので、POST すると送信されます。

イメージ説明

ログイン有り

CSRF 対策トークンのクッキーは上と同じものです(ブラウザを閉じない限り同じクッキーが送信されます)。ログインした際に認証クッキーを受け取っていますので、POST 操作で両方送信されています。

イメージ説明

hidden のトークン

ちなみに、hidden 要素のトークンは以下の画像の通りです。クッキーの CSRF 対策トークンと異なるのは追加情報が含まれているからです。

イメージ説明

投稿2021/06/07 22:47

編集2021/06/09 06:45
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gogogolang

2021/06/08 03:08

回答ありがとうございます! 1、 ログインしていなくても、ランダムな値をhiddenに埋め込むんですね。 つまり、cookieにセットする一意な値を使うわけではないという事ということしょうか? 2、 例えばajaxの通信の時には、ヘッダーではなく、hiddenの値をリクエストボディに持たせて送信するという方法も一般的にあり得ますか?
gogogolang

2021/06/08 03:18

何度も質問申し訳ございません! 紹介して下さったサイトの中では、フォームのトークンとcookieのトークンを使っているのですね。 この様に、フォームトークン+cookieトークンを連結して送信するのが一般的ですか? ログインしていない場合は、cookieトークンは空になるという事ですかね…?
退会済みユーザー

退会済みユーザー

2021/06/08 04:55 編集

> 1、ログインしていなくても、ランダムな値をhiddenに埋め込むんですね。つまり、cookieにセットする一意な値を使うわけではないという事ということしょうか? どうしてログインにこだわるのか分かりませんが、少なくとも ASP.NET MVC の CSRF 対策用のトークンの話に限れば、ログインしていなくてもトークンは発行されます。(認証クッキーと CSRF トークンのクッキーとは別物です) ただし、ログインしている場合はユーザー ID が hidden 要素に設定されるトークンに組み込まれる(結果よりセキュアになる)という違いがあるそうです。トークンの生成について詳しくは以下の記事を見てください。 ASP.NET MVC と Web ページの XSRF/CSRF 防止 https://docs.microsoft.com/ja-jp/aspnet/mvc/overview/security/xsrfcsrf-prevention-in-aspnet-mvc-and-web-pages > 2、例えばajaxの通信の時には、ヘッダーではなく、hiddenの値をリクエストボディに持たせて送信するという方法も一般的にあり得ますか? 一般的かどうかは議論する話ではないです。 cookie と hidden 要素の両方にあるトークンをサーバーに送信できるか否かということです。AJAX でも以下の記事のように FormData オブジェクトを利用してフォームデータを送信する方法はあるので、その場合は hidden も一緒に送信でき、上の回答で紹介した記事のような小細工的な方法は不要になります。 ASP.NET Core MVC でファイルアップロード http://surferonwww.info/BlogEngine/post/2020/01/19/aspnet-core-mvc-file-upload.aspx > 紹介して下さったサイトの中では、フォームのトークンとcookieのトークンを使っているのですね。この様に、フォームトークン+cookieトークンを連結して送信するのが一般的ですか? それは hidden が送信できない場合にやむを得ず行う小細工的な手段ですです。決して一般などではないです。 > ログインしていない場合は、cookieトークンは空になるという事ですかね…? 上でも言いましたが、ログインと CSRF トークンのクッキーは関係ないです。
gogogolang

2021/06/08 11:13

1、2の回答ありがとうございます。 皆さんの回答を総合して理解できました。 1、 cookieにCSRFトークンを認証トークンとは別にセットするんですね。 2、 こちらについても、理解できました。ありがとうございます。 フォームのトークンとcookieのトークンを連結するのは、小細工なのですね。これも一応参考にしてみたいと思います。 ご教授、ありがとうございます。
退会済みユーザー

退会済みユーザー

2021/06/08 12:08

> 1、cookieにCSRFトークンを認証トークンとは別にセットするんですね。 cookie とはどういうものか分かってないのでは?
gogogolang

2021/06/09 03:06

すみません、完全に理解していませんでした。 勉強して、戻ってきました。 難しく考えていたのかも知れません。 シンプルに、一つの方法として ①フォーム表示した際に、ハッシュ値などトークンをhiddenに埋め込む ②cookieにもcsrfトークンをセットする ③ ①と②の値を検証する。 で、合っていますでしょうか?
退会済みユーザー

退会済みユーザー

2021/06/09 08:00 編集

合ってると思います。 質問者さんは、CSRF 対策はログインしているときの認証クッキーを保持していなければ不要と思われていて、それゆえログインにこだわっておられるのでしょうか? でも、そういう訳でもなさそうに思います。 ASP.NET MVC ではログインしていない状態でも起こりうる被害を考えてフレームワークを設計したのではなかろうかと想像しています。
退会済みユーザー

退会済みユーザー

2021/06/09 06:19

ご参考に、あとで、ログイン有り無しの時のクッキーがどうなっているか Fiddler で見た画像を回答欄に貼っておきます。
gogogolang

2021/06/09 11:25 編集

大変分かりやすかったです。 知りたかったことは、100%理解できました。 実は当初は、cookieのセットはログイン時に行われるものだと強く思い込んでいました。 別にログイン時でなくても、cookieにCSRFトークンをセットすること技術的には出来るのは分かっていましたが、それが一般的なのかが不安だったのです。 もしログイン後にしかcookieに値をセットしないものとした場合(この前提が間違っていました)、ログイン前のCSRF対策はどうなるの?となり質問したのです。 一通り調べたのですが、完璧に私の疑問を解消してくれる記事が見つからなかった為、質問して良かったです。ありがとうございました。画像もありがとうございます。
guest

0

投稿2021/06/08 00:12

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gogogolang

2021/06/08 03:12

回答ありがとうございます! サイト拝見しました。 この中の、トークンを検証する方法 の中で、 1.ランダム文字列を生成してセッションに格納し,繰り返して使う 2.セッション ID のハッシュ値を使う 3.セッション ID をそのまま使う (非推奨) と、あるのですが、このセッションIDというのは、cookieの値では無いということでしょうか?
退会済みユーザー

退会済みユーザー

2021/06/08 08:57

> セッションIDというのは、cookieの値では無いということでしょうか? いいえ、cookie の値です。 が、多分、話がすれ違っています。 そのレベルの話は、きちんと体系的な学習をした方が良いかと。 php の公式ドキュメントでも良いですし、一部の入門書でも取り扱っている話題です。
gogogolang

2021/06/08 11:03

初歩的な話で申し訳ないです。すみません。 PHPについて詳しくなかったので深くコードを見ていなかったのですが、上記サイトのコードによると、cookieにトークンがセットされていなければ、新規でセットする。 もしセットされていれば(ログインされていれば)、その値を使うという事なんですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問