在我看来,CSRF 的主要目标是确认发出请求的客户端是我们期望的客户端。
我经常看到的解决方案是:
- 服务器生成随机 CSRF Token
- 服务器在 cookie 中设置 CSRF 令牌
- 服务器在生成表单时将 CSRF 令牌注入表单或
- 服务器将 CSRF 令牌传递给 javascript,并且 javascript 将 CSRF 令牌作为 XMLHTTPRequests 上的标头注入
- 收到请求时,通过检查 cookie 中的 CSRF 令牌是否与标头/表单值中的 CSRF 令牌匹配来验证请求。
服务器为 (3)(1) 生成 CSRF 对我来说很有意义,但我无法想出为什么 (3)(2) 需要它的原因。
相反,如果客户端是纯 javascript,我相信这是安全的:
- Javascript 生成随机 CSRF 令牌
- Javascript 在 cookie 中设置 CSRF 令牌
- Javascript 在发出 XMLHTTPRequest 时在标头中传递 CSRF 令牌
- 服务器检查标头和 cookie 中的 CSRF 令牌是否匹配
我的理解是 3 和 4 都是攻击者不能做的事情,所以这也足以阻止攻击。那是对的吗?
如果那是安全的,我们甚至需要执行步骤(1)和(2)吗?由于同源策略(假设 cors 配置正确),这是否也是安全的?
- Javascript 在 XMLHTTPRequest 中设置一个 'CSRF-Safe: true' 标头
- 服务器检查标头 CSRF-Safe 是否存在并设置为“true”