あたしにゃ~そういう難しいことはわからないですがね(こん平風)、閲覧者に意図せず別のWebサイト上で掲示板への書き込みなどを行わせ、警察が誤認逮捕してしまった事件がありましたが、これがCSRF攻撃というから恐ろしいじゃないですか。Node.jsでもしっかり対策しなければなりませんが、Express version3.0以上で、少しはまったところがありましたのでメモします。

CSRFとは

ググればいっぱい出てきます。CSRFをscrと打ち間違えそうになるほど自分はフロント側の人間なので、詳しいことは分かりませんが、下記のサイトが割りと分かりやすかったです。

リクエスト強要(CSRF)対策

http://www.ipa.go.jp/security/awareness/vendor/programmingv2/contents/301.html

単純に、Node.js express CSRFとかでググった先人様の知恵などでは、どうもexpressのバージョンが2とかの情報が多かったです。一番目にしたのは、「express-csrf」というモジュールです。これを使うと、下記のアラートが出てしまいます。

express-csrf is deprecated. Please use Connect’s csrf middleware instead express-csrfは推奨されません。代わりに、ConnectのCSRFミドルウェアを使用してください(直訳)

express-csrfは非推奨

もうこのモジュールを使うのを推奨していないみたいでした。express verison3以降ではミドルフェアとして使えるみたいなので調べてみると、expressのconnectの中に、csrf.jsがちゃんとありました。あと、先人様の知恵情報では、dynamicHelpersを使う方法がありました。express version3以降では、このダイナミックヘルパーの使い方が変わりましたので、この辺りの使い方も変わってしまいました。いろんなサイトを探した結果、下記のサイトに使い方が載ってました。

Express 3 Tutorial: Contact Forms with CSRF

http://dailyjs.com/2012/09/13/express-3-csrf-tutorial/

要点をまとめると、

  1. CSRF対策は専門の方から具体的な内容を聞いてください
  2. express-csrfは非推奨
  3. 参考サイトでdynamicHelperで書かれていたら、express version3以降ではコピペ出来ない
  4. チュートリアルが英語サイトだったので下記にまとめます
js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
app.configure(function() {
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.cookieParser());
  //↓sessionの前に書かないと、最初のアクセスでundefinedが返ってきました。
  app.use(express.csrf());
  app.use(express.session({ secret: 'secret goes here' }));
  app.use(express.bodyParser());
  app.use(app.router);
  app.use(express.static(__dirname + '/public'));
});
 
//tokenを作るメソッド
function csrf(req, res, next) {
  //localsがexpress version3以降のhelperです。
  res.locals.token = req.session._csrf;
  next();
}
 
//第二引数にcsrfメソッドを書きます。
app.get('/', csrf, function(req, res) {
  res.render('index');
});

app.jsはこれだけでOKです。この後はviewのところです。今回はjadeで書きます。index.jadeに下記を書いてみましょう。

js
1
2
form(action='/contact', method='post')
  input(type='hidden', name='_csrf', value=token) //valueにtokenが付きます。

以上で導入完了です。動作確認は、サーバーを起動して、見えないinputタグのvalueに、乱数がセットされていれば動作しています。