CSRF Token 确实会对网站安全起到一些积极作用,但我想讨论 CSRF Token 对于一个网站是否是必要的。
例如如果已经要求所有非幂等的请求都用 POST 方法提交,是否 CSRF Token 就不必要了呢?
CSRF 和 CORS 的关系又是怎样的呢?
感谢大家的回答,我已经理解了这个问题,我也惊讶于我对这个问题的理解一直以来都是错误的。但我觉得对于我的疑问,大家的回答都不是很恰当,因此我自己来回答一下这个问题。
我之前错误的理解是「form 和 XHR 发起的 POST 请求都受到 CORS 的限制,因此只要非幂等请求不是 GET, 就可以防范 CSRF」,而我今天才发现,原来 form 发起的 POST 请求并不受到 CORS 的限制,因此可以任意地使用其他域的 Cookie 向其他域发送 POST 请求,形成 CSRF 攻击。
我还针对这个问题请教了 @c4605 , 他对防御 CSRF 提出了两种解决方案:
- 在每个表单中包含一个 CSRF Token.
- 不将用于认证的 Token 或 Seesion ID 储存在 Cookie 中,而是将其储存在 localStorage 中,在每次发起请求时手动将 Token 添加到请求中。
其中我比较偏好第二种解决方案,似乎各位并没有提到,因此在这里与大家分享一下。
CSRF 是什么?
Cross-site request forgery 跨站请求伪造,也被称为 “one click attack” 或者 session riding,通常缩写为 CSRF 或者 XSRF,是一种对网站的恶意利用。CSRF 则通过伪装来自受信任用户的请求来利用受信任的网站。
CSRF 攻击类似 XSS 攻击,都是在页面中嵌入特殊部分引诱或强制用户操作从而得到破坏等的目的,区别就是迫使用户 访问特定 URL / 提交表单
还是执行 javascript 代码。
为什么叫
跨站请求
攻击?
从字面意思就可以理解:当你访问 fuck.com
黑客页面的时候,页面上放了一个按钮或者一个表单,URL/action 为 http://you.com/delete-myself
,这样引导或迫使甚至伪造用户触发按钮或表单。在浏览器发出 GET 或 POST 请求的时候,它会带上 you.com
的 cookie,如果网站没有做 CSRF 防御措施,那么这次请求在 you.com
看来会是完全合法的,这样就会对 you.com
的数据产生破坏。
如何防止 CSRF ?
CSRF 主流防御方式是在后端生成表单的时候生成一串随机 token ,内置到表单里成为一个字段,同时,将此串 token 置入 session 中。每次表单提交到后端时都会检查这两个值是否一致,以此来判断此次表单提交是否是可信的。提交过一次之后,如果这个页面没有生成 CSRF token ,那么 token 将会被清空,如果有新的需求,那么 token 会被更新。
攻击者可以伪造 POST 表单提交,但是他没有后端生成的内置于表单的 token,session 中有没有 token 都无济于事。