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

标签 javascript html authorization local-storage single-sign-on

我一直在研究类似于 stackexchange 的身份验证和授权模块。现在我确信他们使用某种模型的 oAuth 或 token 生成服务器,授权使用他们的各种站点。我尝试了一个小实验。

登录 Stackoverflow 后,我会从开发人员控制台中删除所有 cookie。

我保留我的 localstorage 对象完好无损,其中包含用于 stackoverflow 域的 key se:fkey xxxxxxxxxxxxxxxxxxxxxxxxx

stackauth 域还有另一个 key GlobalLogin: xxxxxxxxxxxxxxxxxxxxxxx

se.fkey 如果我用于 session 劫持,则什么也没有发生。但是 GlobalLogin,我能够复制和劫持我的 session 。所以,我的问题是,S/O 如何处理每个站点的授权后验证。还有,有没有办法让他们的globalLogin用一次就失效?

{EDIT1}

因此,仅 globalLogin 就足够了。如果您可以获得该 key ,只需打开一个隐私浏览实例即可。当您在登录页面时,在用于 stackauth 的 Localstorage 中,创建 key-value 映射并刷新页面。您将登录。

{EDIT2}

globalLogin 键似乎在多个 session 中是一致的。已经一天了,我的 globalLogin key 没有刷新。可以安全地假设,如果您的 key 被劫持,攻击者将可以无限期地访问您的个人资料。

{EDIT3}

对于所有正在投票并将投票给这个问题而不是编程相关问题的人。让我这样说吧,我们如何使用 localstorage 安全地将 SSO 存储在 Web 浏览器上,并且由于它们很容易受到损害,我们需要做些什么来防止它发生?我的一位同事很体贴,把他的 GlobalLogin key 给了我,我能够从另一台计算机劫持他的 session ,尽管它在同一网络上。

Set the GlobalLogin key life this

PS:我这样做纯粹是为了理论上的理解。

最佳答案

好吧,与其查看漏洞,不如查看可能的攻击向量。我将在此处添加一个表格作为 TL/DR

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

所以是的,这是一个问题。

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

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

来回发送给 SO 的请求在默认情况下是未加密的。您可以通过 HTTPS 浏览,但默认情况下仅使用 HTTP。

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

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

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

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

该 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);
}

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

所以 GlobalLogin 部分是安全的,不会被窃听。

但是,请注意它仍然很容易嗅探 session cookie,因为它是通过 HTTP 发送的。

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

嗯,这就是事情变得有趣的地方。

如果您可以修改流量,您就可以做一些非常有趣的事情。

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

而 StackAuth.com 就可以满足这一要求。当它向 stackauth.com 发出请求时,您还需要拦截它,并将其 ReadSession URL 也更改为 HTTP。

但是,您需要做的就是观察对 ReadSession URL 的调用,然后砰的一声,您已经窃取了 GlobalLogin token 。

但是无论如何,流量都是 HTTP,所以这并不重要,因为您不需要经历那么多麻烦来窃取 cookie。那么何必呢?

本地攻击者

如果此人有权访问计算机以读取本地存储文件,他们可以做FAR比窃取您的登录 token 更糟糕的事情。

有一类称为“中间浏览器”的攻击,浏览器中的妥协允许攻击者为所欲为。

除了尝试保持浏览器安全之外,没有真正有效的保护措施(您对此无能为力)。

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

基于服务器的攻击者

如果攻击者可以访问 StackOverflow 的服务器,那么游戏就结束了...

结论

只要允许 HTTP(因为 MITM 总是可以将连接降级为 HTTP),就没有什么需要保护的,因为 session secret 总是可以通过窃听窃取。

保护此信息的唯一方法是使用 HSTS并在所有地方强制使用 HTTPS。

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

但是在任何地方都只通过 HSTS 使用 HTTPS 将是防止此类问题的最佳且真正唯一的方法。任何其他东西都可以作为枪伤的创可贴。

注意:在发布之前我确实与 SO 讨论过这个问题。

关于javascript - Stackoverflow 使用 localstorage 进行授权似乎不安全。这是正确的,否则我们如何加强它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26891083/

相关文章:

java - 如何将带有html元素的jsonArray输出到JSP中

html - CSS 中子选择器的 CSS 属性

ASP.NET Core - AddJwtBearer - 权限 URL,它是如何工作的?

javascript - 使用 Vanilla js 删除或禁用表行的 onclick 监听器

node.js - Passport.js - 是否可以将参数传递到路由器验证功能中?

asp.net-mvc - 如果 Roles 为空,则使 AuthorizeAttribute 默认拒绝用户

javascript - 即使 javascript 表单验证失败,表单也会提交

javascript - 指令链接函数中的 "Scope"是根作用域,而不是指令作用域

javascript - Google App Scripts 是否应该存储在像 GitHub 这样的版本控制中

javascript - 在 Fabric.js Canvas 上添加网格