gist

ラベル セキュリティ の投稿を表示しています。 すべての投稿を表示
ラベル セキュリティ の投稿を表示しています。 すべての投稿を表示

2012年3月13日火曜日

Safari 5.1.4 でも express.csrf は undefined だった

少し前のエントリーで、Node.jsでexpress.csrf を有効にした場合、Safariで上手く動いていないのでは?と書きました。

先日Safari 5.1.4がリリースされましたので、早速アップデート。しかし現象は変わらず。

Tower.jsのcsrfではSafari, Chromeとも undefinedではないものの、CSRFの値は固定値。

config/application.coffee

@use "csrf" のコメントを外して有効化。


    @use "csrf"

リソースを確認。metaタグにcsrf_tokenに値が入るも固定値。


<meta name="csrf-token" content="WyfqwvnxM7x3WuSMhTrMR9oU" />

うーむ。僕の使い方が間違っているのかしら。。。

2012年3月6日火曜日

express.csrf でSafariでundefinedの再現

昨日の続き。express.csrf undefind問題の再現方法がようやくわかりました。Safariだけ。5.1.1をアップデートして5.1.3でも同様。

  1. Safari起動
  2. メニューから[Safari]→[Safariをリセット]→[リセット]
  3. https://localhost:3000/login にアクセス → session.csrf が発行される。
  4. ログインしてログアウト。
  5. ログイン画面 → session.csrf が undefined。以降ずっと。
  6. 再びリセットすると、最初の1回だけ session.csrf が発行されるも、3.と全く同じ値のcsrf。

やってみたこと

  • logout時に session.destroy → NG
  • 1.のとき、然るべきときに session.regenerate → NG
  • logout時に session.user だけ undefined設定 → OK
  • 3.のとき、session._csrf は 固定値になっている。そもそもChromeも。

もう眠いので推測。destoryやregenerateの挙動がブラウザで違うのは、HTTPヘッダがなんか足りない。session._csrf固定値なのは、express.csrf が static か singleton か ランダムじゃないのでは、と。この視点で明日コールドリーディングするか。

今日のコード

app.coffee

fs = require('fs')
express = require("express")
routes = require("./routes")
mongoose = require('mongoose')

app = module.exports = express.createServer
  key:fs.readFileSync 'key.pem'
  cert:fs.readFileSync 'cert.pem'

app.configure ->
  app.register ".coffee", require("coffeekup").adapters.express
  app.set "views", __dirname + "/views"
  app.set "view engine", "coffee"
  app.use express.cookieParser()
  app.use express.session
    secret: "your secret here"
    cookie: { secure: true }
  app.use express.bodyParser()
  app.use express.query()
  app.use express.methodOverride()
  app.use app.router
  app.use express.static(__dirname + "/public")
  app.use express.csrf()

app.dynamicHelpers token:(req, res) ->
  console.log(req.session._csrf)
  return req.session._csrf

app.configure "development", ->
  mongoose.connect 'mongodb://localhost/sample'
  app.use express.errorHandler(
    dumpExceptions: true
    showStack: true
  )

app.configure "production", ->
  mongoose.connect 'mongodb://localhost/sample'
  app.use express.errorHandler()

app.get "/", routes.index
app.get "/login", routes.login
app.post "/login", routes.authenticate
app.get "/secret", routes.secret
app.get "/signup", routes.signup
app.post "/signup", routes.regist
app.get "/logout", routes.logout
app.listen 3000
console.log "Express server listening on port %d in %s mode", app.address().port, app.settings.env

routes/index.coffee(logoutのところ)

  logout: (req, res, next) ->
    req.session.user = undefined
    res.redirect '/' 

2012年3月5日月曜日

express.csrf でSafariでundefinedの件

昨日の続き。Safariではundefined、Chromeでは出力された。

Safari

ログイン画面

Cookieがない。。。キャッシュクリア、再起動してもダメ。

Tokenはundefined。

Chrome

ログイン画面

Cookieがちゃんとある。キャッシュクリア、再起動でもCookieある。

Tokenもちゃんとある。

さて、何が原因なのか。X-CSRF-Tokenあたりだろうか。僕が仕様を理解していないのだろうなあ。

2012年3月4日日曜日

expressのcsrfがundefinedになる件

ログイン機能を実装しています。CSRF対策として app.use express.csrf() を設定。app.dynamicHelpers に req.session._csrf を返すようにして、Viewでtokenを出力するプログラム。

何故か req.session._csrf に undefined が。。。CoffeeKupのテンプレートが悪いのかと思ったが、Jadeでも同じ。

CRSF protection middleware.

StackOverFlow - How do I generate CSRF tokens in Express?

npm lsでのパッケージ構成

├── bcrypt@0.5.0  extraneous
├─┬ coffeekup@0.3.1 
│ └── coffee-script@1.2.0 
├─┬ express@2.5.5 
│ ├─┬ connect@1.8.5 
│ │ └── formidable@1.0.9 
│ ├── mime@1.2.5 
│ ├── mkdirp@0.0.7 
│ └── qs@0.4.2 
├─┬ js2coffee@0.1.3 
│ ├── coffee-script@1.2.0 
│ └── underscore@1.3.1 
├─┬ mongoose@2.5.9  extraneous
│ ├── hooks@0.1.9 
│ └── mongodb@0.9.7-3-5 
└── mongoose-types@1.0.3  extraneous

app.coffee

fs = require('fs')
express = require("express")
routes = require("./routes")
mongoose = require('mongoose')

app = module.exports = express.createServer
  key:fs.readFileSync 'key.pem'
  cert:fs.readFileSync 'cert.pem'

app.configure ->
  app.register ".coffee", require("coffeekup").adapters.express
  app.set "views", __dirname + "/views"
  app.set "view engine", "coffee"
  app.use express.cookieParser()
  app.use express.session
    secret: "your secret here"
    secure: true
  app.use express.bodyParser()
  app.use express.query()
  app.use express.methodOverride()
  app.use app.router
  app.use express.static(__dirname + "/public")
  app.use express.csrf()

app.dynamicHelpers token:(req, res) ->
  console.log req.session._csrf  # undefined!
  return req.session._csrf

app.configure "development", ->
  mongoose.connect 'mongodb://localhost/sample'
  app.use express.errorHandler(
    dumpExceptions: true
    showStack: true
  )

app.configure "production", ->
  mongoose.connect 'mongodb://localhost/sample'
  app.use express.errorHandler()

app.get "/", routes.index
app.get "/login", routes.login
app.post "/login", routes.authenticate
app.get "/secret", routes.secret
app.get "/signup", routes.signup
app.post "/signup", routes.regist
app.get "/logout", routes.logout
app.listen 3000
console.log "Express server listening on port %d in %s mode", app.address().port, app.settings.env

CSRF対策できないと、使えんぞ。。。自分で実装するしかないか。