CSRF対策でトークンチェックが入っている画面遷移を自動的に辿るには、画面上の値を取得し、次画面へのPOST値に組み込む必要があります。Zestだとその処理を簡単に設定できます。
■Zest編(4)CSRFチェックのある複数画面遷移
part7で利用したサンプルサイト、およびサンプルサイト用に作成したZestスクリプトをそのまま今回も利用します。
Zestスクリプトのindex.phpへのGETのノードを選択し、右クリック - 「Add Zest Assignment」- 「Assign variable to a form field」を選択します。
すると、「アサインの追加」というダイアログが出るのですが、そこの「Replacement Field」欄に、履歴に記録されたオリジナルのレスポンスに含まれるformのパラメーターがプルダウンリストの選択肢として出てきます。
(参考)index.phpのレスポンスのフォーム部分抜粋:
user registration:<br> <form method="POST" action="confirm.php"> <input type="hidden" name="anticsrftoken" value="5ccd3cd47428d8182137c71ef3fbc3aa72d3cade"><br> name:<input type="text" name="name" value="Test Taro"><br> address:<input type="text" name="address" value="Test Street 12345"><br> <input type="submit" value="submit"><br> </form>
CSRF防止用トークンは「anticsrftoken」なので、この値を取得する必要があります。
さきほど表示された「アサインの追加」ダイアログで、
変数名: anticsrftoken1
Replacement Form: 0 (そのまま)
Replacement Field: anticsrftoken
を選択し、「保存」を押下すると、「GET」の下に「Assign」の項目が一つ増えます。
これで、この画面に対するGETリクエストのレスポンスにある、フォーム項目「anticsrftoken」の値を「anticsrftoken1」という変数に格納するという処理が書けました。
このコードで目的とするCSRF防止用トークンの値が本当に変数に格納されるのか、一度printして確かめてみます。
「Assign anticsrftoken1=(Form 0:Field anticsrftoken)」のノードを選択して右クリック - 「Zest Actionを追加します」 - 「Action Print」を選択します。
すると「Zest Actionを追加します」というタイトルの、「message:」というテキストボックスのみの殺風景なダイアログが出てきます。
Zestでは変数を参照するときにデリミタとして(デフォルトでは)「{{」「}}」で目的の変数名を挟んだものを利用します。ここでは「anticsrftoken1」という変数の値をprintしたいので、ダイアログの「message:」欄に
anticsrftoken1 value is {{anticsrftoken1}}
このように記入し、「保存」を押下します。すると「Assign」のノードの下に、「Action」のノードができます。
これでいったんスクリプトを実行してみると、script output panelに「anticsrftoken1 value is XXXXXXXX(ランダムな英数字)...」という文字列が出力されます。
ここで表示された「anticsrftoken1 value is XXXXXXXX(ランダムな英数字)...」は、Zestスクリプト動作時にZAPが新しくGETリクエストを投げて、取得したレスポンスに含まれるFormのInput項目「anticsrftoken」の値です。
本当にちゃんとリクエストを行って最新の値を取得しているかを確認したい場合は、Zest Resultsの結果の行を選択してZAPの「リクエスト」「レスポンス」タブを開くと、Zest実行時のリクエスト/レスポンスを確認可能です。
ここで取得したCSRF防止用トークンの値を次画面へのPOSTに含めれば、CSRFチェックを突破することができるはずです。その処理も簡単に書くことができます。
Zestスクリプトのconfirm.phpへのPOSTをダブルクリックし、「Zest Request」というウィンドウを表示させます。
「リクエスト」「cookies」「レスポンス」というタブがありますが、その「リクエスト」タブを開きます。
Body:の欄の内容が、このPOSTリクエストが履歴に加えられた時のリクエストボディの値(POSTパラメーター)となっています。
このPOST値の anticsrftoken=XXXXX(ランダムな英数字)... を、printの時と同じ要領で anticsrftoken={{anticsrftoken1}} に書き換えます。
それでZestを実行すると、confirm.phpの画面がCSRFチェックエラーにならず、正常表示されることが確認できます。
同じ要領で、confirm画面のフォームにある「anticsrftoken」欄の値を「anticsrftoken2」という変数に格納し、complete画面へのPOSTに含ませると、complete画面のCSRFチェックも突破でき、サンプルサイトの登録完了画面まで無事遷移できます。
続きます。
次へ