1 回答
TA贡献1936条经验 获得超6个赞
你的问题可能有点宽泛,但总的来说你在滥用这些工具,所以我只是尝试解释基本的想法。您正在使用的应用程序使用“双重提交”模式来保护 CSRF。这需要更改客户端和服务器代码库。服务器不应该设置X-CSRF-Token标头,这是客户端的角色。我最近实际上从头开始实施了几个反 CSRF 解决方案,它们非常简单(都是双重提交模式)。我还使用了一些来自 MSTF 和 Apache 等供应商的软件包(必须在各种堆栈上实现大约 20 年的应用程序的 CSRF)。
在双重提交模式中,服务器应该设置一个带有随机值的 cookie(如 guid),cookie 必须标记为安全的。您也可以将其设置为 httponly,但是它需要您在前端资源上做更多的工作。在客户端,处理这个问题的最简单方法是实现一些 JavaScript,它读取 cookie 值并将其添加为任何 POST 请求之前的标头。您通常不需要保护 GET。您可以,但是如果您的 GET 正在服务器端做建设性/破坏性的事情,那么您就在滥用 HTTP 动词,我会通过将这些请求设为 POST 来纠正这一点,而不是试图保护每个请求。
在服务器端,最好在所有请求进入的公共位置预先进行 CSRF 检查。当 POST 进入时,服务器应该读取 cookie 值,检查标头值并比较它们。如果它们相等,那么应该允许请求通过,如果它们不相等,那么你应该用 403 或其他东西启动它们。这样做之后,服务器应该重写 cookie 值(最好只使用一次)。
您的客户端脚本可以包含类似于以下代码的内容,只需确保资源在每个页面加载上并且您不使用表单提交,这将涵盖所有内容。如果您提交表单,您将需要一些其他类似这样的代码来处理它。有些方法更喜欢在 DOM 服务器端写入值。例如,在 .NET 中,CSRF 库生成 HTTPOnly 和 Secure 的值,并希望开发人员在他们项目的每个单独的 cshtml 文件中的每个表单中放置一个占位符令牌......我个人认为这是非常愚蠢和低效的。无论您如何执行此操作,您都可能需要进行一些自定义工作。Angular 不会为 gorillas CSRF 库实现前端。gorilla 可能不会为您的客户端提供 JavaScript,因为它是一个 API 库。反正,
// three functions to enable CSRF protection in the client. Sets the nonce header with value from cookie
// prior to firing any HTTP POST.
function addXMLRequestCallback(callback) {
var oldSend;
if (!XMLHttpRequest.sendcallback) {
XMLHttpRequest.sendcallback = callback;
oldSend = XMLHttpRequest.prototype.send;
// override the native send()
XMLHttpRequest.prototype.send = function () {
XMLHttpRequest.sendcallback(this);
if (!Function.prototype.apply) {
Function.prototype.apply = function (self, oArguments) {
if (!oArguments) {
oArguments = [];
}
self.__func = this;
self.__func(oArguments[0], oArguments[1], oArguments[2], oArguments[3], oArguments[4]);
delete self.__func;
};
}
// call the native send()
oldSend.apply(this, arguments);
}
}
}
addXMLRequestCallback(function (xhr) {
xhr.setRequestHeader('X-CSRF-Token', getCookie('X-CSRF-Cookie'));
});
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') c = c.substring(1);
if (c.indexOf(name) == 0) return c.substring(name.length, c.length);
}
return "";
}
现在,如果你能稍微缩小你的问题,我可以提供一些更具体的指导,但这只是一个猜测(也许我会在有时间的时候阅读他们的文档)。Gorilla 会自动设置您的 cookie 并在您使用csrf.Protect. 您在 Go 中设置标题的代码,这就是您需要上述 JavaScript 的内容。如果您在服务器端设置标头,则根本没有提供任何安全性。这需要在浏览器中发生。如果您将价值连同您的所有请求一起发送,Gorilla 很可能会为您完成其余部分。
关于问题空间的其他一些随机想法。根据经验,如果攻击者无法重放请求,他们可能无法对您进行 CSRF。这就是为什么这个简单的方法如此有效。每个传入请求都有一个它需要通过的随机 GUID 值。您可以将该值存储在 cookie 中,这样您就不必担心会话在服务器之间移动等(如果您不使用双重提交模式,则需要共享数据存储服务器端;此 cookie-header 值比较业务)。在当前的硬件限制下,这个值不可能被强制使用。浏览器中的单一来源策略可防止攻击者读取您设置的 cookie 值(如果设置为安全,则只有来自您域的脚本才能访问它)。
- 1 回答
- 0 关注
- 162 浏览
添加回答
举报