LoginSignup
0

More than 5 years have passed since last update.

YesodのCSRF対策の作法

Last updated at Posted at 2016-12-01

Webアプリの脆弱性としてCSRF(クロスサイトリクエストフォージェリ)というよく知られた攻撃があります。詳細はここでは割愛しますので、IPAのページでご確認下さい。
Yesodは比較的堅牢で脆弱性を作り込みにくいフレームワークだと思いますが、CSRFについてもフレームワークレベルで対策が盛り込まれています。

formでの対策

YesodのHTMLテンプレートであるhamlet内でformを扱う場合、CSRF対策となるトークンをform内のhidden項目として持つ必要があります。

が、この項目はYesodが自動生成してくれるので、プログラマはMFormを返す関数の定義で、Htmlを引数に取るようにすればいいです。

createForm :: Html -> MForm Handler (FormResult Text, Widget)

なお・・・MFormを返す関数は型宣言が面倒だが、Foundation.hsにこれを簡単に書くためのtype宣言があります。

Foundation.hs
-- | A convenient synonym for creating forms.
type Form x = Html -> MForm (HandlerT App IO) (FormResult x, Widget)

これを使うと次のように書けます。

createForm :: Form Text

Ajaxの場合

Ajaxの場合、トークンをリクエストにセットするのはプログラマの責任となります。

ただYesodは、scriptタグの中にCSRF対策のトークンを、トップレベルのスコープのvar変数として定義してくれています。
これをAjaxリクエストのヘッダにセットすれば、サーバ側でYesodがCSRFトークンをチェックしてくれます。

下記はSuperAgentを使ったAjax実行の例です。

request.get(url)
    .set(csrfHeaderName, csrfToken) // Yesodが定義しているvar変数を使っている
    .end(function(err, res) {
        ...
    });

なおこれらのヘッダの設定を怠ると、YesodはCSRFチェックをNGとし、下記のようなHTMLを返してきます。

<p>A valid CSRF token wasn&#39;t present in HTTP headers or POST parameters. Check the Yesod.Core.Handler docs of the yesod-core package for details on CSRF protection.</p>

CSRF対策のトークン値を得る

あまり必要な局面が見当たらないですが、Haskellコードの中でCSRF対策のトークンの値を得ることができます。reqToken関数を使います。

token   <- getRequest >>= return . maybe "" id . reqToken

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0