$shibayu36->blog;

株式会社はてなでエンジニアをしています。プログラミングや読書のことなどについて書いています。

Mojolicious::Plugin::CSRFDefenderというのを作った

 最近はMojoliciousを使ってWebアプリケーション開発を行っています。CSRFの対策をどうしようかなと考えていて、最初はPlack::Middleware::CSRFBlockを使っていたのですが、

  • Sessionとかの仕組みはApplicationと同じものを使いたい
  • CSRF対策はApplicationの層でやったほうがきれいに書けそう
  • MojoliciousのPluginを書いてみたい

という三つの理由から、新しくMojolicious::Plugin::CSRFDefenderというのを書いてみました。

ソースはhttps://github.com/shiba-yu36/p5-Mojolicious-Plugin-CSRFDefenderに置いておきました。まだCPANには上げてないです。

概要

 このMojolicious::Plugin::CSRFDefenderは自動的にCSRFの対策を行ってくれるモジュールです。基本的に出力のフィルタリングと入力のチェックを行ってくれます。

出力のフィルタリング

 出力にmethodがPOSTであるformタグが存在した場合、CSRFチェック用のトークンをhiddenパラメータに追加します。
例えば次のような出力の場合、

<html>
  <body>
    <form method="post" action="/">
      <input name="text" />
      <input type="submit" value="send" />
    </form>
  </body>
</html>

自動的にhiddenパラメータを追加してくれます。

<html>
  <body>
    <form method="post" action="/">
      <input type="hidden" name="csrf_token" value="zxjkzX9RnCYwlloVtOVGCfbwjrwWZgWr" />
      <input name="text" />
      <input type="submit" value="send" />
    </form>
  </body>
</html>
入力のチェック

 アプリケーションにPOSTでのアクセスが来た場合に、自動的にcsrf_tokenが妥当かどうかチェックします。妥当でなかった場合は、403を返します。

使い方

 Mojoliciousでpluginをロードするだけです。

Mojolicious::Liteでは

plugin 'Mojolicious::Plugin::CSRFDefender';

を追加してください。

Mojoliciousでは

$self->plugin('Mojolicious::Plugin::CSRFDefender');

をstartup内に追加してください。

まとめ

 とりあえず、CSRFの対策ができるところまでさっと書いたので、まだまだ甘いところがあります。CPANにはオプションを付けたり、もう少しチェックしてからあげようと思っています。何かおかしいところなどあれば教えてください。
 今回、MojoliciousのプラグインとしてCSRF対策を実装してみましたが、非常に簡単にプラグインが書けるということがわかりました。また、時間があるときにでもプラグインの書き方を記事にしてみたいと思います。