Csurf 无效的 csrf 令牌 Express / nodejs
Csurf invalid csrf token Express / nodejs
我有这种奇怪的行为,我在第一次加载页面时遇到错误,基本上是 'EBADCSRFTOKEN' 我一直在努力弄清楚为什么会这样仅在页面第一次加载时发生,如果我点击刷新并获得新令牌,一切正常。
当我删除 csurf cookie、点击刷新并获得一个新令牌时,同样的情况发生了,但第一次总是失败我不确定为什么预期的字符串和令牌不匹配。
一段代码(我正在使用 MEANJS 堆栈):
app.use(busboy());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json({limit: '50mb'}));
app.enable('jsonp callback');
var cp = cookieParser;
app.use(cp());
var mStore = new mongoStore({
db: db.connection.db,
collection: config.sessionCollection
});
app.use(session({
secret: config.sessionSecret,
store: mStore,
cookie: {httpOnly: false},
key:config.cookieKey,
}));
app.use(csrf());
//setting up a middleware
var middlewareFiles = [
'csrf-rule.server.js',
'secure-routes.server.js'
];
middlewareFiles.forEach(function(routeSecure){
require(path.resolve('./app/middleware/'+routeSecure))(app);
});
app.use(function(err, req, res, next) {
if (!err) return next();
if(err.code === 'EBADCSRFTOKEN'){
res.json(484, {data: 'invalid csrf token.'});
return;
}
// Error page
res.status(500).render('500', {
error: err.stack
});
});
中间件:
module.exports = function(app) {
app.use(function(req, res, next){
res.cookie('x-xsrf-token', req.csrfToken());
res.locals.csrftoken = req.csrfToken();
next();
});
};
令牌的不同值:
Cookie
fgeHcu6v-hgdCMuRjnmE9BYV_QrvrfzwJoeA
req.csrfToken()(在中间件请求中)
fgeHcu6v-hgdCMuRjnmE9BYV_QrvrfzwJoeA
预期(在 csurf 库中)
fgeHcu6v-T9CuTWL8hVGHMtSskeh0yzqaP0k
令牌(在 csurf 库中)
fgeHcu6v-hgdCMuRjnmE9BYV_QrvrfzwJoeA
似乎预期与令牌相似,但它们在破折号之后有所不同,有什么想法吗?
更新:
基本上,我按照@shakiba 的建议删除了我的自定义中间件,让 csurf 库处理它。
我将配置更改为:
app.use(csrf({ cookie: true }));
现在我得到了一个名为_csrf的cookie,现在这个issue有点不一样了,token值和库中的secret token一样,所以当库“转换” 秘密令牌成为预期令牌 它们不匹配。
这些是一些示例值:
Cookie
BDir8-6hkdy-_YsXNb305IIx
秘密
BDir8-6hkdy-_YsXNb305IIx
令牌
BDir8-6hkdy-_YsXNb305IIx
预计
BDir8-zbwt4-K_Uv8t1TtmxxctkfcMN1M
我相信你没有正确使用 csurf,csurf 为你设置了 cookie,你不应该自己设置,它的值与 csrfToken() 值不同。据我从文档和源代码中了解到,csrfToken() 值是使用 csurf 为 cookie 设置的值生成的,因为它们 state 可以减轻 BREACH 攻击。
我制作了更简单的 csurf 版本,它只使用 cookie,对 BREACH 攻击没有做任何事情,因为 BREACH 攻击在我看来是一个独立的问题,应该在独立的 module/library 中解决。我会在 github 上分享,如果你喜欢可以使用它。
我有这种奇怪的行为,我在第一次加载页面时遇到错误,基本上是 'EBADCSRFTOKEN' 我一直在努力弄清楚为什么会这样仅在页面第一次加载时发生,如果我点击刷新并获得新令牌,一切正常。
当我删除 csurf cookie、点击刷新并获得一个新令牌时,同样的情况发生了,但第一次总是失败我不确定为什么预期的字符串和令牌不匹配。
一段代码(我正在使用 MEANJS 堆栈):
app.use(busboy());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json({limit: '50mb'}));
app.enable('jsonp callback');
var cp = cookieParser;
app.use(cp());
var mStore = new mongoStore({
db: db.connection.db,
collection: config.sessionCollection
});
app.use(session({
secret: config.sessionSecret,
store: mStore,
cookie: {httpOnly: false},
key:config.cookieKey,
}));
app.use(csrf());
//setting up a middleware
var middlewareFiles = [
'csrf-rule.server.js',
'secure-routes.server.js'
];
middlewareFiles.forEach(function(routeSecure){
require(path.resolve('./app/middleware/'+routeSecure))(app);
});
app.use(function(err, req, res, next) {
if (!err) return next();
if(err.code === 'EBADCSRFTOKEN'){
res.json(484, {data: 'invalid csrf token.'});
return;
}
// Error page
res.status(500).render('500', {
error: err.stack
});
});
中间件:
module.exports = function(app) {
app.use(function(req, res, next){
res.cookie('x-xsrf-token', req.csrfToken());
res.locals.csrftoken = req.csrfToken();
next();
});
};
令牌的不同值:
Cookie
fgeHcu6v-hgdCMuRjnmE9BYV_QrvrfzwJoeA
req.csrfToken()(在中间件请求中)
fgeHcu6v-hgdCMuRjnmE9BYV_QrvrfzwJoeA
预期(在 csurf 库中)
fgeHcu6v-T9CuTWL8hVGHMtSskeh0yzqaP0k
令牌(在 csurf 库中)
fgeHcu6v-hgdCMuRjnmE9BYV_QrvrfzwJoeA
似乎预期与令牌相似,但它们在破折号之后有所不同,有什么想法吗?
更新:
基本上,我按照@shakiba 的建议删除了我的自定义中间件,让 csurf 库处理它。
我将配置更改为:
app.use(csrf({ cookie: true }));
现在我得到了一个名为_csrf的cookie,现在这个issue有点不一样了,token值和库中的secret token一样,所以当库“转换” 秘密令牌成为预期令牌 它们不匹配。
这些是一些示例值:
Cookie BDir8-6hkdy-_YsXNb305IIx
秘密 BDir8-6hkdy-_YsXNb305IIx
令牌 BDir8-6hkdy-_YsXNb305IIx
预计 BDir8-zbwt4-K_Uv8t1TtmxxctkfcMN1M
我相信你没有正确使用 csurf,csurf 为你设置了 cookie,你不应该自己设置,它的值与 csrfToken() 值不同。据我从文档和源代码中了解到,csrfToken() 值是使用 csurf 为 cookie 设置的值生成的,因为它们 state 可以减轻 BREACH 攻击。
我制作了更简单的 csurf 版本,它只使用 cookie,对 BREACH 攻击没有做任何事情,因为 BREACH 攻击在我看来是一个独立的问题,应该在独立的 module/library 中解决。我会在 github 上分享,如果你喜欢可以使用它。