手把手教你防御 CSRF 攻击

242 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第12天,点击查看活动详情

之前已经写了两篇关于 CSRF 的文章,其中昨天的一篇手把手教你实现一次 CSRF 攻击 留下了防御的悬念,而今天这篇就是教导如何防御 CSRF 攻击

202212071826163.png

系列文章

  1. 手把手教你实现一次 CSRF 攻击
  2. 手把手教你防御 CSRF 攻击
  3. 面试题之 CSRF 攻击

CSRF 的触发方式

CSRF 本质上是 Cookie 的被利用(由于 sessionsessionid 通常也是使用 Cookie 传递,因此也可以被视为原因之一)

通常触发 CSRF 的攻击有如下

  1. 表单提交触发(POST
  2. Ajax 触发(POST
  3. GET 请求资源触发(比如图片或者 iframe

CSRF 的最终目的是保证复杂请求(有副作用)能够作用到服务器(并不强制要求有服务器的响应至客户端)

副作用:指对数据库做出修改:使用GET请求获取新闻列表,数据库中的记录不会做出改变,而使用PUT请求去修改一条记录,数据库中的记录就发生了改变。

复杂请求定义:

请求以 GET, HEAD 或者 POST 以外的方法发起请求。或者,使用 POST,但请求数据为 application/x-www-form-urlencoded, multipart/form-data 或者 text/plain 以外的数据类型。比如说,用 POST 发送数据类型为 application/xml 或者 text/xml 的 XML 数据的请求。 使用自定义请求头(比如添加诸如 X-PINGOTHER)

一旦归属于复杂请求,就会在发送复杂请求之前发送一次预检请求(option 请求)

简单请求定义:

只使用 GET, HEAD 或者 POST 请求方法。如果使用 POST 向服务器端传送数据,则数据类型(Content-Type)只能是 application/x-www-form-urlencoded, multipart/form-data 或 text/plain中的一种。 不能使用自定义请求头(类似于 X-Modified 这种)。

防御方式

此处就是八股文背诵阶段

规范

遵循良好的规范可以避免攻击,这也是一种“防御方式”

对于有副作用的接口,尽可能去使用 POST 请求而不是 GET 请求,并且避免使用简单请求而是使用复杂请求完成,使用预检请求来拦截可能的跨域请求

IMG

JWT/CSRF Token

如何在根本上终结 Cookie 利用?不用不就行了?而对应的鉴权就是使用 JWTJWT 是属于 CSRF Token 的两种实现的一种,是基于加密解密实现的有效性认证

注意,JWT 是基于的公钥私钥模块进行的加密解密而不是随机字符串,下面就是的作用原理(HTTPS 也是使用的公钥私钥原理)

  1. 登录时,后台拿到用户的鉴权信息,并结合三部分组成 token,分别为 Header|Payload|Signature,其中 Header 说明加密算法等,Payload 是用户信息,通常为用户 id,而 Signature 是使用自定义的私钥(PrivateKey 私钥只有你知道,泄露则被认为 JWT 失效!)加密 Header + Payload + PrivateKey 得到
  2. 鉴权时,Base64 解密 HeaderPayload,得到签名的不可逆加密算法,比如 HS256,并使用私钥加上加密算法重新加密 Header + Payload + PrivateKey 查看是否被篡改

通常登录后下发的 Token 由客户端存储,而浏览器中通常存在 LocalStorage 中,在发送请求时放在 Authentication 请求头中

参考资料

  1. [什么是JS跨域访问? - 前端私教年年的回答 - 知乎]www.zhihu.com/question/26…
  2. 使用Express模拟并理解csrf攻击 - 大地dadi - 掘金
  3. 前端安全系列(二):如何防止CSRF攻击? - 美团技术团队