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:
- 向站点发送 GET 请求
- 收到 html 包含申请表的文本。
- 在 html 文本中搜索 CSRF 令牌。
- 使用该令牌发出恶意请求。
我遗漏了什么?
重要的是要认识到 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.
我已了解 CSRF 以及如何使用不可预测的同步器令牌模式来防止它。我不太明白它是如何工作的。
让我们来看这个场景:
用户使用此表单登录站点:
<form action="changePassword" method="POST">
<input type="text" name="password"><br>
<input type="hidden" name="token" value='asdjkldssdk22332nkadjf' >
</form>
服务器还在会话中存储令牌。发送请求时,它会将表单数据中的令牌与会话中的令牌进行比较。
当黑客可以编写 JavaScript 代码时,这如何防止 CSRF:
- 向站点发送 GET 请求
- 收到 html 包含申请表的文本。
- 在 html 文本中搜索 CSRF 令牌。
- 使用该令牌发出恶意请求。
我遗漏了什么?
重要的是要认识到 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.