Yoshi.dev

技術系の趣味、またはやった仕事やそこから学んだことを忘れないために

二重サブミット防止策が十分じゃなかった

仕事のWebシステムでCSRFトークンを使用したリクエストの二重サブミット防止策があるのだけど、それの不備が発覚したのでそれの調査~対応策までをやりました。
ちなみにこの件はユーザーからの連絡で気づいた。

まず現状の仕組みについて
リクエストにCSRFトークンをパラメータとしてつけてもらい、それがサーバーのセッションで保持しているトークンと一致するかどうか確認します。
これで一致しない場合は二重サブミットの疑いがあるのでエラーにします。
一致した場合はセッションのトークンを削除します。
セッション情報についてはmemcachedで管理していました。

最初にやったのは再現性の確認です。
まずlocalの開発環境で確認してみたけどどうにも発生しない。
次にstaging環境で確認すると発生するときと発生しない時があることに気が付きました。

単純に考えると二重申請ができてる=既存の防止策に問題がある
ってことになると思います。なのでそのへんのコードを重点的に見ながら考えました。

localとstaging環境の違いというと一つはサーバーが冗長化されているかどうかです。
最初はセッション情報は各サーバーで共有しているのでトークンのチェックで引っかかるはずだと思っていたのですが、
よくよく考えるとほぼ同時のタイミングで別々のサーバーで処理が走った場合、両方共sessionから同じトークンが取れるということに気づきました。
これだと現状の仕組みだと二重サブミット問題が発生してしまいます。

現状考えている対策としては、
クライアント側でボタンの二重クリック防止策を入れてもらおうと思っています。

参考
qiita.com


バグ調査系タスクってつまんねーなーってずっと思ってたけど、普段の開発とは違う視点で調査したりするから、めちゃくちゃ学びの多い作業だと考え方を変えたら気持ちが楽になってきた。