Stackoverflow's use of localstorage for Authorization seems unsafe. Is this correct else how do we strengthen it?

后端 未结 1 764
不知归路
不知归路 2021-01-30 13:40

I have been working on a Authentication and authorization module similar to how stackexchange is in place. Now I am sure they use a certain model of oAuth or a token generation

相关标签:
1条回答
  • 2021-01-30 14:17

    Well, rather than looking at the vulnerability, let's look at the possible attack vectors. I'll add a table here as a TL/DR

    Attacker      | Vulnerable?
    Eavesdropper  | Yes
    MITM          | Yes
    Local Attack  | Yes
    Server Attack | Yes
    

    So yes, it is an issue.

    Remote Attacker, can observe traffic, but cannot modify traffic

    Consider this a passive attacker in a coffee shop. They can see all of the TCP level traffic.

    The requests back and forth to SO are -by-default- not encrypted. You can browse via HTTPS, but by default it's HTTP only.

    So an attacker can see any request go by, and inspect/steal the data.

    So let's see if the GlobalLogin token is ever sent in a request...

    As a matter of fact, it is. On the login page, a request is sent via an iframe to the following URL:

    https://stackauth.com/auth/global/read?request=//snip//
    

    That URL returns a script:

    var data = {
        "ReadSession":"https://stackauth.com/auth/global/read-session",      
        "Request":"//snip//",
        "Nonce":"//snip//",
        "Referrer":"//snip//",
        "StorageName":"GlobalLogin"
    };
    
    var toMsg = window.parent;
    var obj = localStorage.getItem(data.StorageName);
    
    if(obj != null) {
        var req = new XMLHttpRequest();
        req.open(
            'POST', 
                data.ReadSession+
                'request='+encodeURIComponent(data.Request)+
                '&nonce='+encodeURIComponent(data.Nonce)+
                '&seriesAndToken='+encodeURIComponent(obj), 
            false
        );
        req.send(null);
    
        if(req.status == 200){
            toMsg.postMessage(req.responseText, data.Referrer);
        }else{
            toMsg.postMessage('No Session', data.Referrer);
        }
    }else{
        toMsg.postMessage('No Local Storage', data.Referrer);
    }
    

    Now, notice that the GlobalLogin is sent over HTTPS to the server. So a remote attacker, who can read traffic will not be able to get the GlobalLogin token.

    So the GlobalLogin portion is safe from eavesdroppers.

    However, note that it's still quite vulnerable to sniffing the session cookie, since it's sent over HTTP.

    Remote Attacker, can modify traffic (MITM)

    Well, here's where things get interesting.

    If you can modify traffic, you can do something really fun.

    The initial page creates an iframe bringing in the above stackauth.com URL via HTTPS. Well, if you can modify the initial page (also possible via XSS), you can downgrade the request to HTTP.

    And StackAuth.com will be just fine with that. When it makes the request to stackauth.com, you would need to intercept that as well, and change its ReadSession URL to be HTTP as well.

    But then, all you need to do is watch the call to the ReadSession URL, and boom, you've stolen the GlobalLogin token.

    But the traffic is HTTP anyway, so it doesn't matter since you don't need to go through that trouble to steal the cookie. So why bother?

    Local Attacker

    If the person has access to the computer to read the local storage file, they can do FAR worse than just steal your login token.

    There's a class of attack called "Browser In The Middle", where a compromise in the browser allows an attacker to do whatever they want.

    And there's no real effective protection against it other than to try to keep the browser secure (there's nothing you can do from your end).

    So if an attacker can get local access to the computer, it's game over.

    Server-Based Attacker

    If an attacker can get access to StackOverflow's servers, it's game over anyway...

    Conclusion

    As long as HTTP is allowed (since a MITM can always downgrade the connection to HTTP), there's nothing to protect as session secrets always be stealable via eavesdropping.

    The only way of protecting this information is to use HSTS and force HTTPS everywhere.

    It's worth noting that you could protect GlobalLogin by forcing HSTS on stackauth.com, leaving the main site accessible over HTTP. This wouldn't prevent the effect of the attack (session hijacking). But it would protect the one vector.

    But going HTTPS only via HSTS everywhere would be the best and really only way to prevent these kinds of problems. Anything else would be a bandaid on a gunshot wound.

    Note: I did talk to SO about this prior to posting this.

    0 讨论(0)
提交回复
热议问题