Javascript 堆栈溢出';s使用本地存储进行授权似乎不安全。这是正确的吗?我们如何加强它?
我一直在开发一个身份验证和授权模块,类似于stackexchange的实现方式。现在我确信他们使用了oAuth的某个模型或令牌生成服务器,该服务器授权使用他们的各个站点。我做了一个小实验 登录Stackoverflow后,我会从开发者控制台删除所有cookie 我保留了本地存储对象,该对象包含stackoverflow域的键Javascript 堆栈溢出';s使用本地存储进行授权似乎不安全。这是正确的吗?我们如何加强它?,javascript,html,authorization,local-storage,single-sign-on,Javascript,Html,Authorization,Local Storage,Single Sign On,我一直在开发一个身份验证和授权模块,类似于stackexchange的实现方式。现在我确信他们使用了oAuth的某个模型或令牌生成服务器,该服务器授权使用他们的各个站点。我做了一个小实验 登录Stackoverflow后,我会从开发者控制台删除所有cookie 我保留了本地存储对象,该对象包含stackoverflow域的键se:fkey xxxxxxxxxxxxxxxxxxxxxxxxx stackauth域GlobalIn还有另一个密钥:xxxxxxxxxxxxxxxxxxxx 如果我使用s
se:fkey xxxxxxxxxxxxxxxxxxxxxxxxx
stackauth域GlobalIn还有另一个密钥:xxxxxxxxxxxxxxxxxxxx
如果我使用sef.fkey进行会话劫持,则不会发生任何事情。但是GlobalLogin,我能够复制并劫持我的会话。所以,我的问题是,S/O如何处理每个站点的授权后身份验证。此外,是否有一种方法可以在使用一次globalLogin后使其无效
{EDIT1}
因此,仅使用globalloin
就足够了。如果您可以获得该密钥,只需打开一个私有浏览实例。登录页面时,在stackauth的Localstorage中,创建键值映射并刷新页面。您将登录
{EDIT2}
globalwin
键在多个会话中似乎是一致的。我的globalloin
键已经一天没有刷新了。可以安全地假设,如果您的密钥被劫持,攻击者将无限期地访问您的配置文件
{EDIT3}
对于所有正在投票并将投票支持此问题的人,请将其视为与编程无关的问题。让我这样说吧,我们如何使用localstorage安全地将SSO存储在web浏览器上?既然它们很容易受到破坏,我们需要做些什么来防止这种情况发生?我的一位同事很体贴地给了我他的GlobalIn密钥,我能够从另一台计算机上劫持他的会话,尽管它在同一个网络上
PS:这纯粹是为了从理论上理解我做了这件事。好吧,与其看漏洞,不如看可能的攻击向量。我将在这里添加一个表作为TL/DR
Attacker | Vulnerable?
Eavesdropper | Yes
MITM | Yes
Local Attack | Yes
Server Attack | Yes
是的,这是一个问题
远程攻击者,可以观察流量,但不能修改流量
将其视为咖啡馆中的被动攻击者。他们可以看到所有TCP级别的流量
在默认情况下,向SO来回的请求是不加密的。您可以通过HTTPS进行浏览,但默认情况下它仅为HTTP
因此,攻击者可以看到任何请求经过,并检查/窃取数据
因此,让我们看看是否在请求中发送了globalloin
令牌
事实上,的确如此。在登录页面上,通过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);
}
现在,请注意,globalloin
通过HTTPS发送到服务器。因此,能够读取流量的远程攻击者将无法获取globalwin
令牌
因此,globalloin
部分是安全的,不会被窃听
但是,请注意,它仍然很容易嗅探会话cookie,因为它是通过HTTP发送的
远程攻击者,可以修改流量(MITM)
嗯,这就是事情变得有趣的地方
如果你可以修改流量,你可以做一些真正有趣的事情
初始页面创建一个iframe,通过HTTPS引入上述stackauth.com URL。如果可以修改初始页面(也可以通过XSS),那么可以将请求降级为HTTP
StackAuth.com也会接受的。当它向stackauth.com发出请求时,您还需要拦截它,并将其ReadSession
URL更改为HTTP
但是,你所需要做的就是观察对ReadSession
URL的调用,然后砰的一声,你偷了globalwin
令牌
但是不管怎么说,流量是HTTP的,所以这并不重要,因为你不需要费劲去偷cookie。那为什么要麻烦呢
本地攻击者
如果此人有权访问计算机以读取本地存储文件,那么他们所做的远比窃取您的登录令牌更糟糕
有一种称为“中间浏览器”的攻击类型,浏览器中的漏洞允许攻击者做任何他们想做的事情
除了努力保持浏览器的安全(从你的角度来说,你无能为力),没有什么真正有效的保护措施可以防止它
因此,如果攻击者可以在本地访问计算机,游戏就结束了
基于服务器的攻击者
如果攻击者可以访问StackOverflow的服务器,游戏就结束了
结论
只要允许HTTP(因为MITM总是可以降级到HTTP的连接),就没有什么需要保护的,因为会话机密总是可以通过窃听窃取的
保护此信息的唯一方法是在任何地方使用并强制使用HTTPS
值得注意的是,您可以通过在stackauth.com上强制HST来保护GlobalLogin
,从而使主站点可以通过HTTP访问。这不会阻止攻击的效果(会话劫持)。但它会保护一个载体
但是,在任何地方都只通过HST使用HTTPS将是防止此类问题的最佳且真正唯一的方法。其他任何东西都会是枪伤上的绷带
注意:我在发布这篇文章之前确实和SO谈过这件事 我已经在我的系统上尝试了你的建议,这看起来像一个笑话,很简单。无论如何,这都不是一个安全的实现,您只需在5分钟内使用一个受损的系统,复制对给定用户保持不变的GlobalLogin密钥,然后使用该用户的GlobalLogin随时从任何使用匿名浏览的系统登录