令牌如何防止CSRF攻击?

34

我已经了解了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. 使用该令牌发起恶意请求。

我有遗漏什么吗?

2个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
21
攻击者无法使用JavaScript从站点读取令牌,因为这将是跨域请求,并且同源策略(MDNW3C)默认情况下会阻止访问其数据。

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

JS控制台报告:

XMLHttpRequest无法加载http://google.com/。请求的资源缺少'Access-Control-Allow-Origin'标头。


1
值得注意的是,您可以通过iframe、script或object标签发出成功的GET请求,但浏览器不允许您从JavaScript获取加载的文档内容(协议、域和端口必须匹配)。 - ptkoz
1
如果有人想知道为什么攻击者不能从网站获取任何旧令牌,并在其请求中使用它,那是因为该令牌也作为浏览器中的cookie存储,攻击者不知道该cookie的存在。因此,当他使用从网站刚刚获得的新令牌发送请求时,它与用户cookie上的令牌不匹配,请求将被拒绝。 - T0m
如果我使用命令行发送请求(例如CURL请求),那么是否可以绕过同源策略? - Sin Sopheak

-2

需要认识到的是,CSRF攻击只会发生在浏览器中。恶意服务器利用用户与目标服务器的会话来伪造请求。那么#1是如何发生的呢?有两种选择:你可以从恶意服务器发出#1请求,但这只会返回服务器会话的CSRF令牌,或者你可以使用AJAX发出#1请求,正如你正确地指出的那样,这将返回受害用户的CSRF令牌。

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

使用同步令牌是应用程序依赖同源策略防止 CSRF 的一种方式,通过维护一个秘密令牌来验证请求。

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

你应该了解一下跨源资源共享(CORS)。

Access-Control-Allow-Origin并不能防止CSRF攻击,它只是打开了同源策略所施加的限制。同源策略并不能阻止对您域名的请求,它只是阻止响应被读取。虽然同源策略可以防止同步令牌被读取,但它本身对于防止CSRF攻击是无用的。 - SilverlightFox
1
您必须使用 Access-Control-Allow-Origin 标头。不使用 Access-Control-Allow-Origin 标头是默认安全的,它可以保证数据的安全性。只有在您希望第三方网站能够读取您的数据时才需要使用 Access-Control-Allow-Origin - Quentin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,