Stackoverflow使用localstorage进行授权似乎不安全.这是否正确,我们如何加强它?

Sho*_*vik 34 javascript html5 authorization single-sign-on local-storage

我一直致力于一个认证和授权模块,类似于stackexchange的实现方式.现在我确信他们使用某种型号的oAuth或令牌生成服务器授权其各种站点使用.我尝试了一点实验.

登录到Stackoverflow后,我从开发者控制台删除了所有cookie.

我保留localstorage对象,其中包含se:fkey xxxxxxxxxxxxxxxxxxxxxxxxxstackoverflow域的密钥.

stackauth域还有另一个密钥 GlobalLogin: xxxxxxxxxxxxxxxxxxxxxxx

se.fkey,如果我用于会话劫持,没有任何反应.但是GlobalLogin,我能够复制并劫持我的会话.所以,我的查询是,S/O如何处理每个站点的授权后认证.此外,有没有办法在使用一次后使globalLogin无效?

{} EDIT1

所以,仅仅这一点globalLogin就足够了.如果您可以获得该密钥,只需打开一个私人浏览实例.在登录页面中的stackstuth的Localstorage中,创建key-value映射并刷新页面.你将登录.

{} EDIT2

globalLogin关键似乎是在多个会话保持一致.这是一天,没有刷新我的globalLogin钥匙.可以安全地假设,如果您的密钥被劫持,攻击者将无限期地访问您的个人资料.

{} EDIT3

对于投票的所有人而言,他们将投票支持这个问题而不是与编程相关的问题.让我这样说吧,我们如何安全地将SSO存储在带有localstorage的Web浏览器上,因为它们容易受到攻击,我们需要做些什么来防止它发生?我的一位同事足够体贴地给我他的GlobalLogin密钥,我能够从另一台计算机上劫持他的会话,尽管它在同一个网络上.

设置GlobalLogin密钥寿命

PS:这纯粹是出于理论上的理解,我这样做了.

irc*_*ell 16

好吧,让我们看看可能的攻击向量,而不是查看漏洞.我将在这里添加一个表作为TL/DR

Attacker      | Vulnerable?
Eavesdropper  | Yes
MITM          | Yes
Local Attack  | Yes
Server Attack | Yes
Run Code Online (Sandbox Code Playgroud)

是的,这是一个问题.

远程攻击者,可以观察流量,但不能修改流量

将此视为咖啡店中的被动攻击者.他们可以看到所有TCP级别的流量.

来回SO的请求是默认的 - 未加密.您可以通过HTTPS浏览,但默认情况下它只是HTTP.

因此,攻击者可以看到任何请求,并检查/窃取数据.

那么让我们看看GlobalLogin令牌是否曾在请求中发送过......

事实上,确实如此.在登录页面上,请求通过iframe发送到以下URL:

https://stackauth.com/auth/global/read?request=//snip//
Run Code Online (Sandbox Code Playgroud)

该URL返回一个脚本:

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);
}
Run Code Online (Sandbox Code Playgroud)

现在,请注意,它GlobalLogin是通过HTTPS发送到服务器的.因此,可以读取流量的远程攻击者将无法获取GlobalLogin令牌.

所以这GlobalLogin部分是免受窃听者的安全.

但请注意,它仍然非常容易嗅探会话cookie,因为它是通过HTTP发送的.

远程攻击者,可以修改流量(MITM)

嗯,这里的事情变得有趣.

如果你可以修改流量,你可以做一些非常有趣的事情.

初始页面创建一个iframe,通过HTTPS引入上述stackauth.com网址.好吧,如果你可以修改初始页面(也可以通过XSS),你可以将请求降级为HTTP.

而StackAuth.com就可以了.当它向stackauth.com发出请求时,您也需要拦截它,并将其ReadSessionURL 也更改为HTTP.

但是,您需要做的就是观看对ReadSessionURL 的调用,然后繁荣,您已经窃取了GlobalLogin令牌.

但无论如何流量都是HTTP,因此无关紧要,因为您不需要经历麻烦来窃取cookie.那为什么要这么麻烦?

本地攻击者

如果人可以访问计算机读取本地存储的文件,他们可以做的不如刚偷你的登录凭证.

有一类名为"中间浏览器"的攻击,浏览器中的妥协允许攻击者做任何他们想做的事情.

除了试图保持浏览器安全之外,没有真正有效的防范措施(你无法做到最好).

因此,如果攻击者可以获得对计算机的本地访问权限,那么游戏就结束了.

基于服务器的攻击者

如果攻击者可以访问StackOverflow的服务器,无论如何都是游戏......

结论

只要允许HTTP(因为MITM总是可以将连接降级到HTTP),没有什么可以保护的,因为会话机密总是可以通过窃听来窃取.

保护此信息的唯一方法是使用HSTS并在任何地方强制使用HTTPS.

值得注意的是,您可以GlobalLogin通过在stackauth.com上强制使用HSTS 来保护,使主站点可以通过HTTP访问.这不会阻止攻击的影响(会话劫持).但它会保护一个载体.

但是,仅通过HSTS到达HTTPS只是防止这类问题的最佳方式.其他任何东西都是枪伤上的绑带.

注意:在发布此内容之前,我确实与SO讨论了这个问题.