CSRF対策とインジェクション対策は別途対応しないといけない
少しソースを変更することになるので早めに対応すること
CSRF(クロスサイトリクエストフォージェリ)とは
攻撃者の用意したサイトより意図しないリクエストが送信され誤って処理してしまうこと。
例えばECサイトなどでログイン済みだった場合など、
外部サイトから実装上適切な購入処理がリクエストされると
ユーザが意図せず商品を購入してしまうというもの
対策するためには
- 画面表示時にサーバで生成したトークンを埋め込む
- POSTした時にトークンも一緒に送信
- サーバ側で突合
csurfを使用したcsrf対策
環境はNode.js * Express * Pug
csurfはセッションとクッキーを利用しているそうなので一緒にインストールする
npm install --save cookie-parser
npm install --save express-session
npm install --save csurf
npm install --save express-session
npm install --save csurf
app.jsに以下を追記
csurfはクッキーとセッションの後に指定すること
var cookieParser = require("cookie-parser") var session = require("express-session") var csurf = require('csurf') // ... // クッキー app.use(cookieParser()) // セッション管理 app.use(session({ secret: "任意の文字列", resave: false, saveUninitialized: false })); // csrf app.use(csurf({ cookie: true })) /// ...
req.csrfToken() でランダムなトークンを取得できる
このトークンをフォームの隠しフィールドに仕込む
ブラウザからポストされた時にトークンのチェックを実行してくれる
攻撃者からトークンが盗まれない限り安全
デフォルトだとGETはそのまま通ってしまう
データ更新が発生するPOSTだけで問題ない?
以下具体例
route login
const express = require("express") const router = express.Router() /* GET home page. */ router.get("/", (req, res, next) => { const title = "ログイン" res.render("index", { title: title, csrfToken: req.csrfToken() }) }) module.exports = router
html
form(methos="POST", action="next") input(type="text" name="id") input(type="password" name="pass") input(type="hidden", name="_csrf" value=csrfToken)formからpostする場合form内にトークンを入れること
ログイン先のサーバ処理
const express = require("express") const router = express.Router() router.post("/", (req, res, next) => { const title: string = "ログイン後の画面" req.session.loginid = req.body.id res.render("customer", { title: title, csrfToken: req.csrfToken() }) })
javascriptのXMLHttpRequest を使用する場合はヘッダにトークンを埋め込むといい
const xhr = new XMLHttpRequest() xhr.open("POST", url) xhr.setRequestHeader("X-XSRF-Token", document.getElementById("csrfToken").value)
共通画面(ヘッダ)などに埋め込んで置くとスマート
トークンが2つ埋め込まれていても動作には影響しない
参考
https://github.com/expressjs/csurf
http://dev.classmethod.jp/server-side/node-js_csrf/
あとはインジェクションか
NoSQLは対応が必要なのだろうか?