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
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.
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.
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?
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.
If an attacker can get access to StackOverflow's servers, it's game over anyway...
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.