Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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 server that authorizes uses to their various sites. I tried a little experiment.

Once I am logged into Stackoverflow, I delete all my cookies from the developer console.

I leave my localstorage object intact which contains a key se:fkey xxxxxxxxxxxxxxxxxxxxxxxxx for stackoverflow domain.

there is another key for stackauth domain GlobalLogin: xxxxxxxxxxxxxxxxxxxxxxx

the se.fkey if I used for a session hijack, nothing happened. but the GlobalLogin, I was able to copy and hijack my session. So, my query would be, how does S/O deal with the authorization post authentication for each one of the sites. Also, is there a way to invalidate the globalLogin for them after it is used once?

{EDIT1}

So, just the globalLogin alone is enough. If you can get that key, just open a private browsing instance. In the Localstorage for stackauth when you are in the login page, create the key-value mapping and refresh the page. You will be logged in.

{EDIT2}

The globalLogin key seems to be consistent across multiple sessions. It has been a day and no refresh of my globalLogin key. Safe to assume if you key is hijacked, the attacker will have access to your profile indefinitely.

{EDIT3}

For everyone who is voting and will vote for this question as not a programming related question. Let me put it this way, how do we store SSO's on the web browser with localstorage safely and since they are prone to get compromised, what do we need to do prevent it from happening? One of my colleagues was considerate enough to give me his GlobalLogin key, I was able to hijack his session from a different computer albeit it was on the same network.

Set the GlobalLogin key life this

PS: This is purely for theoretical understanding that I did this.

like image 824
Shouvik Avatar asked Nov 12 '14 15:11

Shouvik


People also ask

Why localStorage is not secure?

On the downside, localStorage is potentially vulnerable to cross-site scripting (XSS) attacks. If an attacker can inject malicious JavaScript into a webpage, they can steal an access token in localStorage. Also, unlike cookies, localStorage doesn't provide secure attributes that you can set to block attacks.

Is it safe to store auth token in local storage?

If you store it inside localStorage, it's accessible by any script inside your page. This is as bad as it sounds; an XSS attack could give an external attacker access to the token. To reiterate, whatever you do, don't store a JWT in local storage (or session storage).

Is local storage safe for JWT?

A JWT needs to be stored in a safe place inside the user's browser. Any way,you shouldn't store a JWT in local storage (or session storage). If you store it in a LocalStorage/SessionStorage then it can be easily grabbed by an XSS attack.


1 Answers

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.

like image 151
ircmaxell Avatar answered Oct 02 '22 11:10

ircmaxell