前端安全之跨站请求伪造CSRF攻击

178 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第22天,点击查看活动详情

跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。

CSRF 就是利用用户的登录态发起恶意请求。

如何攻击

原理就是攻击者构造出一个后端请求地址,诱导用户点击或者通过某些途径自动发起请求。如果用户是在登录状态下的话,后端就以为是用户在操作,从而进行相应的逻辑。

假设网站中有一个通过 GET 请求提交用户评论的接口,那么攻击者就可以在钓鱼网站中加入一个图片,图片的地址就是评论接口。

<img src="http://www.domain.com/xxx?comment='attack'"/>

使用 POST 方式提交请求是不是就没有这个问题了呢?其实并不是,使用这种方式也不是百分百安全的,攻击者同样可以诱导用户进入某个页面,在页面中通过表单提交 POST 请求。

具体操作示例:

  1. 用户在A网站登录接口是get,登录后正常访问
  2. 此时有一个B网站(危险网站)中有一个钓鱼图片地址就是A网站,用户打开B网站img自动发起请求
  3. 此时会带上A网站的cookie,B网站就窃取了用户在A网站的信息
// 1. 假设A网站是taobao.com,登录接口是http://taobao.com/api/login,用户已登录
// 2. 在B网站中
<body>
  <!-- 利用img自动发送get请求 -->
  <img src="http://taobao.com/api/login" />
</body>
// 此时会带上A网站的cookie

在A网站下发cookie的时候,加上sameSite=strict,这样B网站在发送A网站请求,就不会自动带上A网站的cookie,保证了安全

res.setHeader('Set-Cookie', `username=poetry2;sameSite = strict;path=/;httpOnly;expires=${getCookirExpires()}`)
// NAME=VALUE    赋予Cookie的名称及对应值
// expires=DATE  Cookie 的有效期
// path=PATH     赋予Cookie的名称及对应值
// domain=域名   作为 Cookie 适用对象的域名 (若不指定则默认为创建 Cookie 的服务器的域名) (一般不指定)
// Secure        仅在 HTTPS 安全通信时才会发送 Cookie
// HttpOnly      加以限制,使 Cookie 不能被 JavaScript 脚本访问
// SameSite      Lax|Strict|None  它允许您声明该Cookie是否仅限于第一方或者同一站点上下文

如何防御

  • Get 请求不对数据进行修改
  • 不让第三方网站访问到用户 Cookie
  • 阻止第三方网站请求接口
  • 请求时附带验证信息,比如验证码或者 token
  • SameSite Cookies:可以对 Cookie 设置 SameSite 属性。该属性表示 Cookie 不随着跨域请求发送,可以很大程度减少 CSRF 的攻击,但是该属性目前并不是所有浏览器都兼容。
  • 验证Referer:对于需要防范 CSRF 的请求,我们可以通过验证 Referer 来判断该请求是否为第三方网站发起的。

CSRF 特点

  • 攻击一般发起在第三方网站,而不是被攻击的网站。
  • 攻击是利用受害者在被攻击网站的登录凭证,冒充受害者提交操作,仅仅是“冒用”,而不是直接窃取数据。
  • 攻击者预测出被攻击的网站接口的所有参数,成功伪造请求。

CSRF攻击中,就Cookie相关的特性:

  • http请求,会自动携带Cookie。
  • 携带的cookie,还是http请求所在域名的cookie。

CSRF攻击,仅仅是利用了http携带cookie的特性进行攻击的,但是攻击站点还是无法得到被攻击站点的cookie。这个和XSS不同,XSS是直接通过拿到Cookie等信息进行攻击的