为了账号安全,请及时绑定邮箱和手机立即绑定

使用 AngularJS 的 Gorilla CSRF

使用 AngularJS 的 Gorilla CSRF

Go
慕虎7371278 2021-11-22 15:40:55
我正在尝试让 AngularJS 与 Gorilla CSRF 一起用于我的网络应用程序,但是我找不到很多相关文档,所以我不确定从哪里开始。我应该X-CSRF-Token为每个GET请求设置一个还是应该像我现在这样在用户访问主页时才设置?另外,我如何使 AngularJS CSRF 保护与 Gorilla CSRF 一起工作?我需要做一些比较吗?任何示例代码将不胜感激。这是我的代码:package mainimport (    "github.com/gorilla/csrf"    "github.com/gorilla/mux")func main() {    r := mux.NewRouter()    r.HandleFunc("/", Home).Methods("GET")    // Other routes handling goes here    http.ListenAndServe(":8000",        csrf.Protect([]byte("32-byte-long-auth-key"))(r))}func Home(w http.ResponseWriter, r *http.Request) {    w.Header().Set("X-CSRF-Token", csrf.Token(r))}// More routes
查看完整描述

1 回答

?
LEATH

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 值(如果设置为安全,则只有来自您域的脚本才能访问它)。


查看完整回答
反对 回复 2021-11-22
  • 1 回答
  • 0 关注
  • 162 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信