CSRFトークン・バイパス
WEBの脆弱性診断で、ログインフォームに対してブルートフォースアタックを試みる際に、いくつかパターンがある。
- ログインIDとパスワードのみの認証
- ログインIDとパスワードとCSRFトークンによる認証
- ログインIDとパスワードとCSRFトークンとcookieのセッションによる認証
- さらにその他
RailsやLaravelなどのフレームワークを使って基本的なログインフォームを作っている場合は、3番が多いと思う。ちなみに、CSRFトークンとcookieのセッションは毎度変わるので、ひたすらPOST連打というわけにはいかない。
では、1番と3番(2番も考え方は一緒)を例にして、CSRFトークンとcookieのセッションをどうやってパイパスして、ブルートフォースをするかを「Burp Suite」で検証してみる。
1番の場合(簡単)
認証が、ログインIDとパスワードだけの場合、ブルートフォースはシンプルだ。

上記の様に、ひたすら赤矢印をPOSTして検証することができるので簡単だ。そもそも、最初の「GET」すら要らないで成立する。
しかしWEBサービスが、CSRF対策をしている場合は、上記のように簡単にはいかない。
2番、3番の場合(CSRF対策がなされている)
この場合、先程のようにPOST連打というわけにはいかない。

この様に、いきなりPOST連打だと、CSRFトークン(毎度変わる)がセットされていないため、ブルートフォースは成立しない。すなわち、POSTする度にまず先にGETをして、cookeiとcsrfTokenを取得して、それを使ってPOSTする必要があるわけだ。図にすると以下のようになる。

POSTの前に、上記の青矢印を実行する必要が有る。以下の手順で、ひたすら繰返して上げる必要が有る。
- GETして、WEBサーバーから毎回変わる、cookie(session)と、csrfTokenを取得
- POSTの際に、cookie(session)と、csrfTokenをセットしてブルートフォースを実行
上記の手順を、Burp Suiteで自動化してみる。
これが今回のテーマである、「CSRFバイパス」だ。
Burp Suiteの自動化手順
結論として、POSTによるブルートフォースは、通常通り「Intruder」を使用して、GETの部分はマクロで定義してPOST前に組み込んであげる。
Intruderの設定
- ブラウザのProxy設定でBurp Suiteを指定する。
- ブラウザから対象のWEBサーバーのログイン画面を開く。
- Burp SuiteのProxyで、Interseptを「ON」にする。
- ブラウザから、ログインフォームに対して適当な値を入れてみる。以下の例だと、username=test、password=test。
- Burp SuiteによりブラウザのリクエストがInterseptされて、詳細を見ることができる。

上記のような感じでPOSTする際に、「username」と「passowrd」だけでなく、「cookie(session)」と「csrfToken(上記では、loginToken)」もサーバーに送信されていることが解る。
この、「cookie(session)」と「loginToken」はリクエストの度に変わるので、毎度取得してPOSTの際にセットしてあげる必要が有る。
- Interceptしたリクエストを、「Intruder」に送る。

- Intruderで、辞書ファイルの設定する。
Intruderを開くと自動で、「cookie(session)」と「loginToken」と「username」と「password」の全てが、辞書ファイルの挿入対象になってしまっている。
今回は、「username」と「password」は、Intruder(辞書ファイル)からセット、「cookie(session)」と「loginToken」はマクロにより、GETした内容をセットにしたいので、
- 1度「Crear」をクリックして全部対象から外す。
- usernameのバリュー(上記の場合test)と、passwordのバリュー(上記の場合test)を選択して、手動で「Add」する。

マクロの作成
- 「Settings」をクリック
- Settingsの別ウィンドウが開くので、「Project」「Sessions」を選択
- 「Macros」の「Add」をクリック。

- リクエストの履歴が表示されるので、マクロに使用したいリクエストを選択。
今回の場合は、POST前のGETをマクロに使用したいので、それを探して選択する。

以下の画面になるので、適当に名前を付けて「OK」ボタンを押してマクロを保存する。

作成したマクロを実行したいリクエストに紐付ける
- 上記までの操作をすると、カレントのコンテキストは、「Settings」の「Project」の「Sessions」に戻るはずなので、そのまま上の方の「Session handling rules」までスクロールする。
- 「Add」を押す。

そうすると、「Session handling rule editor」のウィンドウが開く。「Details」と「Scope」の2つのタブがあり、「Scope」を開く。
- 「Tools scope」のチェックボックスを今回使用する、「Intruder」のみにする。
- 「Include in scope」で、今回対象のUILを「Use custom scope」で「Add」する。
- 「OK」ボタンを押す。

次に、「Details」をクリックする。
- 「Rule description」に解りやすいルール名を付ける
- 「Rule actions」で、「Add」を押して、「Run a macro」をクリック

そうるすと、以下の画面となる。

この画面は、
「このアクションは定義済みのマクロを実行し、現在のリクエストのパラメータ、ヘッダー、クッキーを更新します。」
と、言っている。まさに定義済み(GETマクロ)を実行し、その結果で(cookie(session)、loginToken)このリクエストを上書きしてほしいのだ。
- 「Select macro」で、先程作成したマクロを選択する。
- 「Update only the following parameters and headers:」にチェックを入れ、上記指定のマクロ(GET)で取得できる「loginToken」を指定する。
- 「Update only the following cookies:」にチェックを入れ、上記指定のマクロ(GET)で取得できる「session」を指定する。
- 「OK」ボタンを押す。
さて、ここまで来たら、最初に定義したこの図を達成したことになる。

Intruderの実行
「Start attack」を押して、Intruder(ブルートフォース)を実行する。

これにて、POST連発のブルートフォースではなく、
- GETして、WEBサーバーから毎回変わる、cookie(session)と、csrfTokenを取得
- POSTの際に、cookie(session)と、csrfTokenをセットしてブルートフォースを実行
を、指定した辞書ファイルのワード数分、繰返しブルートフォースできる。