dtvp3625 2015-11-12 18:06
浏览 173
已采纳

大猩猩CSRF与AngularJS

I'm trying to get AngularJS to work with Gorilla CSRF for my web applciation, but there aren't many documentation around that I can find, so I'm not sure where exactly to start. Should I set a X-CSRF-Tokenfor every GET request or should I just do it when the user visits the home page like I'm doing now? Also, how do I make AngularJS CSRF protection work with Gorilla CSRF? Do I need to do some sort of comparisons? Any example codes would be appreciated.

Here is my code:

package main

import (
    "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条回答 默认 最新

  • dongliang9576 2015-11-12 18:42
    关注

    You're question might be a bit broad but overall you're misusing the tools so I'm just going try and explain the basic ideas. The application you're using uses a 'double submit' pattern for CSRF protection. This requires changes in both the client and server code bases. The server should not be setting the X-CSRF-Token header, that is the role of the client. I've actually implemented a couple from scratch anti-CSRF solutions recently and they're pretty simple (both double submit pattern). I also used a few packages from vendors like MSTF and Apache (had to implement CSRF across like 20 years of applications on all kinds of stacks).

    In the double submit pattern the server should be setting a cookie with a random value (like a guid), the cookie must be marked as secure. You can make it httponly as well, however it will require you to do a lot more work on your front end resources. On the client side, the simplest way to deal with this is to implement some JavaScript that reads the cookie value and adds it as a header before any POST request. You don't need to protect GET's typically. You could, but if your GET's are doing constructive/destructive things server side, then you're misusing the HTTP verb and I would correct that by making those requests POSTS rather than trying to protect every single request.

    On the server side, it's best to do the CSRF check up front, in a common place where all requests come in. When a POST comes in, the server should read the cookie value, check for the header value and compare them. If they're equal then the request should be allowed to pass through, if they're not then you should boot them out with a 403 or something. After doing so the server should rewrite the cookie value (best to make it one use only).

    Your client side script can have something like the code below, just make sure the resource is on every page load and you don't use form submits and this will cover everything. If you submit forms you'll need some other code like this to handle that. Some approaches prefer to write the value in the DOM server side. For example in .NET the CSRF library makes the value HTTPOnly and Secure and expects the devs to put a place holder token in every single form in every single cshtml file in their project... I personally think that is very stupid and inefficient. No matter how you do this, you're probably gonna have to do some custom work. Angular isn't going to implement the front end for gorillas CSRF library. gorilla probably isn't going to come with JavaScript for your client since it's an API library. Anyway, basic JavaScript example;

    // 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 "";
    }
    

    Now, if you can narrow your question a bit I can provide some more specific guidance but this is just a guess (maybe I'll read their docs when I have a minute). Gorilla is automatically going to set your cookie and do your server side check for you if you use csrf.Protect. The code you have setting the header in Go, that is what you need the JavaScript above for. If you set the header on the server side, you've provided no security at all. That needs to happen in the browser. If you send the value along with all your requests, Gorilla will most likely cover the rest for you.

    Some other random thoughts about the problem space. As a rule of thumb, if an attacker can't replay a request, they probably can't CSRF you. This is why this simple method is so effective. Every incoming request has exactly one random GUID value it requires to pass through. You can store that value in the cookie so you don't have to worry about session moving across servers ect (that would require a shared data store server side if you're not using the double submit pattern; this cookie-header value compare business). There's no real chance of this value being brute forced with current hardware limitations. The single origin policy in browsers prevents attackers from reading the cookie value you set (only scripts from your domain will be able to access it if it's set as secure). The only way to exploit that is if the user has previously been exploited by XSS which I mean, kind of defeats the purpose of doing CSRF since the attacker would already have more control/ability to do malicious things with XSS.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 2020长安杯与连接网探
  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么
  • ¥15 banner广告展示设置多少时间不怎么会消耗用户价值
  • ¥16 mybatis的代理对象无法通过@Autowired装填
  • ¥15 可见光定位matlab仿真
  • ¥15 arduino 四自由度机械臂
  • ¥15 wordpress 产品图片 GIF 没法显示
  • ¥15 求三国群英传pl国战时间的修改方法
  • ¥15 matlab代码代写,需写出详细代码,代价私
  • ¥15 ROS系统搭建请教(跨境电商用途)