[解決済み] RESTfulアプリケーションでCSRFを防ぐには?
質問
クロスサイトリクエストフォージェリ(CSRF)は、通常、次のいずれかの方法で防止します。
- referer をチェックする - RESTful ですが信頼性がありません。
- トークンをフォームに挿入し、サーバーセッションにトークンを保存する - RESTfulではない
- 暗号化されたワンタイムユーティリティ - トークンと同じ理由でRESTfulではありません。
- このリクエストのためにパスワードを手動で送信する (HTTP 認証で使用されるキャッシュされたパスワードではない) - RESTful ですが便利ではありません。
私のアイデアは、ユーザーシークレット、暗号化された静的なフォームID、トークンを生成するJavaScriptを使用することです。
<form method="POST" action="/someresource" id="7099879082361234103">
<input type="hidden" name="token" value="generateToken(...)">
...
</form>
-
GET /usersecret/john_doe
は、認証されたユーザーからJavaScriptによって取得されます。 -
レスポンス。
OK 89070135420357234586534346
この秘密は観念的に静的なものですが、セキュリティを向上させるために毎日/毎時...変更することが可能です。これは唯一の機密事項です。 -
JavaScriptで暗号化された(しかしすべてのユーザーにとって静的な!)フォームIDを読み取り、ユーザーの秘密と一緒に処理します。
generateToken(7099879082361234103, 89070135420357234586534346)
- 生成されたトークンとともにフォームをサーバーに送信します。
- サーバーはユーザー秘密とフォームIDを知っているので、送信前にクライアントが行ったのと同じgenerateToken関数を実行し、両方の結果を比較することが可能です。両方の値が等しい場合のみ、アクションは承認されます。
JavaScriptなしでは動作しないという事実がありますが、このアプローチに何か問題があるのでしょうか?
追記です。
どのように解決するのですか?
ここにはたくさんの回答があり、そのうちのかなり多くの問題点があります。
やってはいけないこと。
-
JavaScript からセッション トークンを読み取る必要がある場合、何かひどく間違ったことをしています。 セッション識別子の Cookie には常に HTTPOnly を設定し、スクリプトから利用できないようにする必要があります。
この 1 つの保護により、攻撃者がログインしたユーザーのセッション トークンを取得できなくなるため、XSS の影響がかなり軽減されます。1つのエラーが王国への鍵を与えてしまうようでは困ります。
-
セッション識別子は、ページのコンテンツに書き込まれるべきではありません。これは、HTTPOnlyを設定したのと同じ理由です。つまり、csrf トークンはセッション ID にはなりえません。異なる値である必要があります。
やっておいた方がいいこと
-
フォローする OWASPのガイダンス :
-
具体的には、これがRESTアプリケーションであれば、以下のようになります。 CSRFトークンの二重送信を要求する . これを行う場合、特定のフルドメインに定義していることだけは確認してください ( www.mydomain.com ) に定義し、親ドメイン (example.com) には定義しないこと、また、人気を集めている "samesite" Cookie 属性を利用することです。
単に暗号的にランダムなものを作成し、それを ASCII Hex または Base64 エンコードで保存し、サーバーがページを返すときにそれを Cookie として、フォームに追加します。サーバー側では、クッキーの値がフォームの値と一致することを確認します。これで、CSRFを回避し、ユーザーに余計なプロンプトを表示させず、さらに脆弱性を拡大させないようにすることができました。
注意: @krubo が以下で述べているように、二重投稿のテクニックは にはいくつかの弱点があることが分かっています (二重投稿を参照)。 . この弱点は、以下のことを要求していますので。
- 親ドメインにスコープされたクッキーを定義します。
- HSTSの設定に失敗しました。 .
- 攻撃者がユーザーとサーバーの間にあるネットワークの場所をコントロールしている
この弱点は、「現実世界のセキュリティ リスク」というよりも、むしろ「クールな Defcon トーク」のカテゴリに入ると思います。いずれにせよ、二重投稿を使用するのであれば、自分自身を完全に保護するためにいくつかの余分なステップを取ることは問題ではありません。
新しいアップデート 07/06/2020
しかし、クッキーを同じ正確な値にするのではなく、証明書によって署名された文字列をエンコードした値にするのです。これはサーバー側で検証するのは簡単ですが、攻撃者が模倣するのは非常に難しくなります。それでもなお、samesite Cookie属性と、私の投稿で先に説明したその他の保護機能を使用する必要があります。
関連
-
[解決済み] cURLでJSONデータをPOSTするにはどうすればよいですか?
-
[解決済み] PHPでSQLインジェクションを防ぐにはどうしたらいいですか?
-
[解決済み] JWTは解読できても、安全性はどうなのか?
-
[解決済み] なぜCSRF防止トークンをクッキーに入れるのが一般的なのですか?
-
[解決済み] application/x-www-form-urlencoded or multipart/form-data?
-
[解決済み] CORS OriginヘッダーとCSRFトークンによるCSRF保護
-
[解決済み] ハッシュのソルトを隠蔽する必要性
-
[解決済み] REST API 呼び出しのセキュリティを確保するにはどうすればよいですか?
-
[解決済み] SSLとMan-in-the-Middleの誤解
-
[解決済み] 違法な配布からソフトウェアを守るには?[クローズド]
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] サーバー側に送信する前にパスワードをハッシュ化した方が良いですか?
-
[解決済み] セッションハイジャックを防止する最善の方法は何ですか?
-
[解決済み] なぜ、すべてをHTTPSにしないのか?
-
[解決済み] Firefoxの同一生成元ポリシーを無効にする
-
[解決済み] Firebaseのデータ改変を制限するには?
-
[解決済み] GPGとSSHキーの比較
-
[解決済み] 認証と認可は違うのですか?
-
[解決済み] GETリクエストのクエリパラメータとしてurlにjwtを入れるのは安全ですか?
-
[解決済み] 違法な配布からソフトウェアを守るには?[クローズド]
-
[解決済み] なぜ間違ったパスワードのチェックは、正しいパスワードのチェックより時間がかかるのでしょうか?