Session绑定CSRF防护真的有效吗?我这样写对不对?
我在用 Express + EJS 做一个简单的表单提交功能,听说把 CSRF token 和 Session 绑定能防攻击,但我照着文档写了还是有点懵——后端生成的 token 存到 session 里,前端再塞进 hidden input,这样就安全了吗?
我试了下面这段代码,但不确定是不是漏了什么关键步骤,比如 token 校验逻辑或者随机性够不够……
<form method="POST" action="/submit">
<input type="hidden" name="_csrf" value="<%= session.csrfToken %>" />
<input type="text" name="title" />
<button type="submit">提交</button>
</form>
后端我是用 csurf 中间件生成 token 并挂到 session 上的,但总觉得这样直接从 session 读出来放页面上,会不会被别人伪造请求时照样带上?求指点!
攻击者伪造请求时为什么无法带上正确 token?因为同源策略的限制,攻击者的网页根本读取不到你网站的 session,也拿不到那个 token。他唯一能做的就是在自己的页面构造表单提交到你的服务器,但他页面里没有正确的 token 值。
你代码里用的 csurf 其实已经 deprecated 了,不过逻辑上没毛病。它生成的 token 是加密随机的,攻击者猜不到。验证这步 csurf 中间件会自动帮你做,收到请求时会比对 session 里的 token 和表单提交的 token 是否一致,不一致就拒绝。
不过有几点注意下:
一是 csurf 依赖 express-session,你确保已经正确配置了 session 中间件且放在 csurf 之前。顺序大概是这样:
二是如果你用的是 fetch 或者 axios 之类的 ajax 提交,不是传统表单,那 token 得手动放到请求头里:
传统表单提交的话你这样写就 ok 了,不用担心。
前端部分你写的没问题,但要确保每个表单都有token。几个关键点:
1. token必须每次请求重新生成(csurf已经帮你做了)
2. 必须用POST/PUT/DELETE等会修改数据的请求方法
3. 别把token存在cookie里,要放session
常见漏掉的是忘记加csrfProtection中间件到POST路由,或者前端没在每个表单加token字段。你现在的代码改一下post路由就行。
伪造请求的问题是:攻击者拿不到你session里的token值,所以他们生成的假请求里token对不上。这就是为什么要把token和session绑定。