看我如何绕过Lastpass双因素验证机制
当你在使用账号密码登录所需要的服务时,往往都会在获得访问权限之前,面临一个挑战——一个每30秒更改一组6位数的临时代码。比如Google验证器、Authy和Toopher这些基于RFC6238和RFC4226的2FA方案,Lastpass也同样支持。
临时代码是基于几个变量生成,包括秘密种子(secret seed)和时间戳。秘密种子能够使其安全和独特,而时间则是使其以30秒的间隔更改。服务器需要与客户端共享秘密种子,以便能够设置和同步代码生成过程。这通常是通过使用你的2FA应用程序扫描的QR码编码种子来完成的。
LastPass 2FA的实现方式
在寻找绕过2FA的方法时,我研究的第一件事是看QR码如何存储,不过后来我却意外发现了生成有效临时代码的秘诀。因此如果我能以某种方式进行窃取,那么我将能够彻底进行登录(因为我已经拥有密码)。
我在测试帐户中启用了Google身份验证器,当我被提示扫描QR码时,我查看了源代码。
正如你所看到的,QR码是一个img标签,其源属性指向:
/google_auth_qr_code.php?iterations=1&passwordhash=TOKEN
我以前研究过Lastpass,并在Blackhat EU做过演讲,因此当看到参数“passwordhash”时我马上就知道这是什么了。 passwordhash是LastPass用于认证的登录哈希,它由用户密码加盐哈希并使用SHA256-PBKDF2保存。Lastpass使用PBKDF2保护保管库与主密码的加密密钥。由于Lastpass不知道你的加密密钥,所以它们应用了一轮PBKDF2,并将其用作登录哈希参数。
存在的问题
这是什么意思呢? Lastpass将2FA秘密种子存储在可以将你的密码导出的URL下了。所以看起来这真的是打破了2FA的真正目的,如上所述,它应该是一种安全防范,用以防范那些已经拥有密码登录的攻击者。但是按这种情况,你试着想想如果自己有一个安全的房子,保存着最宝贵的财物,而门和保险箱拥有同一把锁是个好主意吗?门钥匙如果打开了保险箱怎么办?
虽然我们知道如何获取获取QR码的秘密网址,但它还有一层身份验证的请求。这意味着我们需要进行身份验证才能检索QR码。因为我们还没有认证(我们需要QR码),所以我们又无法检索。看起来这就像是个鸡和鸡蛋谁先存在的问题。
这个时候我们怎么办呢?——事实上我们可以强制受害者向我们提出请求,这被称为跨站点请求伪造(CSRF)漏洞。通常,目标是“状态更改请求”(更新,创建或删除资源的操作),因为同源策略(SOP)是不会让攻击者看到响应的。不幸的是,Lastpass作为纯图像文件是可以提供QR码的。攻击者可以在他的域上设置一个“img”标签,其中“src”属性指向2FA URL。
还有一点值得注意的是,攻击者没有必要潜伏受害者访问他的恶意网站,他们可以使用像Facebook或Gmail这样的受害者信任的站点上的任何XSS来添加有效载荷来窃取QR码并将其发送回他的服务器。
对于永久的2FA设计还有其他后果。如上所述,通过将登录哈希作为URL参数传递来检索QR码,这几乎相当于在URL中传递密码。另外一点就是登录哈希与解密保管库的主密钥不同,不过1轮SHA256-PBKDF2比较特别。
传递URL中的秘密其实是一个非常不好的安全措施,因为URL是由网络服务器记录的。 Lastpass可以保护存储所有用户数据的数据库,但是它们对日志也会应用相同的安全标准,而攻击者通常会针对性的寻找秘密的日志。
URL也在缓存、代理、引用标头甚至浏览器历史记录中被泄漏。
使用CSRF禁用2FA
事实上,写这篇文章的原因是因为我想强调将密码和2FA作为“独立实体”的重要性。但真相是,我发现另一种更直接的方式是来禁用2FA,但在技术上却没啥意思。
真正的长久之计其实是重新生成2FA秘密种子。该功能的实现有3个问题:
重新生成种子不要求你通过要求临时代码来验证设置;
重新生成种子会自动禁用2FA(而不是使其启用但使用新的种子);
再生种子的要求容易受到CSRF漏洞的影响;
所有这些问题的结合使得攻击者有可能禁用受害者的2FA保护。
禁用2FA的请求如下所示:
GET /google_auth_regenerate_key.php HTTP / 1.1
Host:lastpass.com
Cookie:PHPSESSID=REDACTED
典型的CSRF是指在没有CSRF令牌的状态改变请求的GET请求,访问攻击者控制站点的受害者可能被迫提出请求并禁用2FA。
LastPass修复方案
Lastpass在报告当天就推出了初步修复方案,目前正在努力确定所有CSRF的脆弱性要求(还有更多),并通过添加CSRF令牌来修复通过CSRF漏洞禁用2FA。
在不安全的2FA设计方面,他们推出了一个初始修复程序来检查Origin标题。这将确保获得QR码的请求只能来自lastpass.com。这是一个很好的立即修复,但不支持旧浏览器不支持Origin标头。
他们还停止使用登录哈希检索QR码,并使用“uidhash”。 uidhash是“uid的SHA256哈希与服务器密码相结合的随机每用户盐(基于用户的uid查找)。我们还在数据库中存储值的哈希值,所以我们可以在X分钟后强制执行该值,并确保用户实际请求释放该信息。”
看我如何绕过Lastpass双因素验证机制相关推荐
- 什么是双因素验证 2FA,如何用 Python 实现?
传统的用户名密码方式,容易泄漏,并不安全. 你说,加上短信验证码不就安全了,其实短信验证码也是不安全的,容易被拦截和伪造,SIM 卡也可以克隆,已经有案例,先伪造身份证,再申请一模一样的手机号码,把钱 ...
- GitHub 再次呼吁用户采取双因素认证机制
聚焦源代码安全,网罗国内外最新资讯! 编译:代码卫士 软件仓库平台 GitHub 再次鼓励用户启用双因素 (2FA) 认证机制,更好地保护账户安全. GitHub 支持2FA 机制已有8年的时间,目 ...
- 如何为SSH登录建立双因子验证机制(谷歌身份验证器)?
前言 默认情况下,SSH已经在远程机器之间使用安全的数据通信;但是如果你想为自己的SSH连接添加另外某种安全层,可以添加谷歌身份验证器(Google Authenticator)双因子验证模块,该模块 ...
- ASP.NET Core 双因素验证2FA 实战经验分享
必读 本文源码核心逻辑使用AspNetCore.Totp,为什么不使用AspNetCore.Totp而是使用源码封装后面将会说明. 为了防止不提供原网址的转载,特在这里加上原文链接: 双因素认证 双因 ...
- 关于github双因素验证问题解决方案
一.问题描述 由于最近github最近的改动使得node_modules依赖出现无法下载的问题,为了避免将来遇到或是现在出现无法解决因此做一篇文档帮助大家解决问题. 二.解决步骤 1.首先进入GitH ...
- otp远程服务器,通过 Yubico OTP 进行双因素认证(服务端)
使用 Yubico OTP 进行双因素验证(服务端) 提高环境安全的第一步是提高客户端安全性(利用 PIV 进行 SSH 认证)和简化服务器上的管理任务(通过用户证书进行 SSH 认证),不过它们依然 ...
- token登录验证机制
jwt: json web token 数据 前端 秘钥 前端 请求数据的时候. 需要通过秘钥生成命令令牌. Token token是oAuth Token,提供的是认证和授权,认证针对用户,授权是针 ...
- 区块链项目开发:双因素身份验证应用程序如何帮助保护你的加密帐户
2019独角兽企业重金招聘Python工程师标准>>> 如果你使用任何加密数字资产交换,你将需要使用某种形式的双因素身份验证来保护你的帐户.简单来说,双因素身份验证是第二层安全性,涉 ...
- 知名密码管理应用LastPass启用双因素认证
如果你真的关心在线账号的安全,那么你可能已经了解并使用多因素认证.今天知名密码管理软件LastPass宣布了名为"LastPass Authenticator"的应用程序,这家已经 ...
最新文章
- ThinkPHP框架学习之CRUD
- 领扣(LeetCode)最长公共前缀 个人题解
- 【64QAM同步】基于FPGA/MATLAB的64QAM同步系统的实现
- 最老程序员创业札记:全文检索、数据挖掘、推荐引擎应用41
- 并发服务器模型——多进程服务器
- ssh框架 验证码实现
- 问题二十八:ray tracing中的散焦模糊(defocus blur)
- jquery 获取 radio值 与 jQuery filter() 方法
- 四平方和蓝桥杯Java_蓝桥杯-四平方和问题
- matlab信源编码,常见无失真信源编码算法及Matlab实现比较(27页)-原创力文档
- 一位五年工作经验架构师的感悟
- SPOJ PHT Pigeonhole Tower 预处理+二分 || 找规律
- @property基本概念
- 解读2018:13家开源框架谁能统一流计算?
- 直播平台接入美颜SDK已成刚需,它将带来哪些影响?
- JPEG算法解密 JPEG原理详解 (转载 by jinchao)
- 多目标遗传算法NSGA-II原理详解及算法实现
- java 二进制转换成十六进制字符串_将二进制字符串转换为十六进制字符串JAVA
- centos7 apache 虚拟目录 You don't have permission to access / on this server 解决方法
- ERROR: cannot launch node of type [fake_localization/fake_localization]: fake_localization