token如何防止csrf攻击?

How to does the token prevent csrf attack?

我已了解 CSRF 以及如何使用不可预测的同步器令牌模式来防止它。我不太明白它是如何工作的。

让我们来看这个场景:

用户使用此表单登录站点:

<form action="changePassword" method="POST">
   <input type="text" name="password"><br>
   <input type="hidden" name="token" value='asdjkldssdk22332nkadjf' >
</form>

服务器还在会话中存储令牌。发送请求时,它会将表单数据中的令牌与会话中的令牌进行比较。

当黑客可以编写 JavaScript 代码时,这如何防止 CSRF:

  1. 向站点发送 GET 请求
  2. 收到 html 包含申请表的文本。
  3. 在 html 文本中搜索 CSRF 令牌。
  4. 使用该令牌发出恶意请求。

我遗漏了什么?

重要的是要认识到 CSRF 攻击只发生在浏览器中。用户与目标服务器的session被恶意服务器用来伪造请求。那么#1 是如何发生的呢?两种选择:您可以从恶意服务器发出 #1 请求,但这只是 return 服务器的 session 的 CSRF 令牌,或者您可以使用 AJAX 的 #1 请求,正如您正确识别的那样,它将 return 受害者用户的 CSRF 令牌。

正是出于这个原因,浏览器实现了 HTTP 访问控制。您必须使用 Access-Control-Allow-Origin header 来限制哪些域可以向您的服务器发出 AJAX 请求。换句话说,您的服务器将确保浏览器不会让恶意站点执行#1。不幸的是,我读过的关于此事的文档并不是很清楚,但我认为这是因为默认情况下服务器不会发送 Access-Control-Allow-Origin header 除非配置为这样做。如果您确实需要允许 AJAX 请求,您必须信任 header 中的任何来源不会执行 CSRF 攻击,您可以有选择地锁定应用程序的敏感部分以不允许 AJAX 请求,或使用其他 Access-Control-* header 来保护自己。

Using a Synchronizer Token is one way that an application can rely upon the Same-Origin Policy to prevent CSRF by maintaining a secret token to authenticate requests

https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet

您应该阅读 Cross-Origin Resource Sharing (CORS)。

攻击者无法使用 JavaScript 从站点读取令牌,因为这将是一个跨源请求,并且从中访问数据会被同源阻止(默认情况下)政策(MDN, W3C)。

以此为例:

var xhr = new XMLHttpRequest();
xhr.open("GET", "http://google.com");
xhr.addEventListener('load', function (ev) {
    console.log(this.responseText);  
});
xhr.send();

JS 控制台报告:

XMLHttpRequest cannot load http://google.com/. No 'Access-Control-Allow-Origin' header is present on the requested resource.