首先明确一点,攻击者在进行跨站攻击的时候是无法读取其他域名下的Cookie,那为什么CSRF攻击仍然有效?那是因为浏览器在发起请求时会自动附带与请求目标域名相关的Cookie,他们可以诱导用户的浏览器自动发动请求。
具体关于CSRF的介绍我就不说了,这里主要就预防措施展开。
CSRF预防措施
1. Cookie属性
-
设置cookie的
SameSite属性为Strict(完全禁止跨站请求携带cookie)或Lax(在部分跨站请求情况下允许携带cookie,但在GET请求时会被允许),防止第三方网站发起跨站请求。 -
设置cookie的属性
httpOnly属性为true,防止攻击者通过js获取Cookie。
2. 检查Referer或Origin头
-
服务器端验证请求的Referer或Origin头是否来自可信任的源。
-
注意:Referer头可以被一些浏览器隐藏或被用户禁用,不完全可靠。
3. CSRF_Token双重校验
这里拿Express+Vue3举例:
- Express中:
//配置csurf中间件
let csrfProtection = csurf({ cookie: true })//未设置ignoreMethods属性时,get请求不走csurf校验
//获取csrftoken并设置cookie
app.get('/csrf-token', csrfProtection, (req, res) => {
const token = req.csrfToken()
res.cookie('_csrf_token', token, { httpOnly: true, sameSite: 'strict' })
res.json({ csrfToken: token })
})
// 动态应用CSRF保护中间件
app.use((req, res, next) => {
if (req.path === '/csrf-token') {
return next();
}
csrfProtection = csurf({ cookie: true, ignoreMethods: ['HEAD', 'OPTIONS'] })//设置ignoreMethods使get请求也经过csurf校验
csrfProtection(req, res, next);//将除'/csrf-token'路由的接口都引入csrfProtection中间件
});
//csurf错误处理
app.use((err, req, res, next) => {
if (err.code !== 'EBADCSRFTOKEN') return next()
res.status(403);
res.cc('无权限', 403)
})
- Vue3中,在根组件中获取csrfToken并存入store里,在封装的httpApi中将csrfToken加入请求拦截判断并写入请求头中,这样当服务端接收到客户端请求时,csurf会自动比对请求头和cookie中的csrfToken,由于页面每次刷新或打开时都会生成新的csrfToken并且攻击者无法读取其他域名下的cookie,以此来起到防御作用
结尾
此篇为web前端就CSRF学习笔记,如有错误及不足,欢迎指正