以下文章转自InfoQ
在《是时候放弃插件密码管理器,改用密码管理器插件了》一文中,我们谈到插件密码管理器的安全性不够。
我们做了一个演示:将恶意JS 代码注入到 Github 一个无需登录的网页中,通过引诱用户点击关闭广告,偷取用户 Github 密码。
Talk is cheap. Show me the video.
为了演示效果,将登录框、LastPass 填充框都设置成了半透明。在实际攻击中,可以设置为很低的透明度,肉眼不可见。
这个演示没有利用任何浏览器漏洞。如果利用合适的漏洞,无需用户点击就能自动偷取密码。
互联网上绝大多数网页都包含大量第三方内容,特别是广告,很难保证所有内容都是安全的。一旦第三方内容含有恶意代码,插件密码管理器就可能存在泄密风险。
一、产品需求
神锁离线版的用户很早就强烈要求提供 Windows 版,将神锁离线版的安全保护能力带到 Windows 上。不过,桌面平台没有完善的沙盒保护,恶意软件不仅可以读取 app 存储的数据,还能通过 Keylogger 或者扫描内存数据等方法偷取主密码。而且,桌面平台没有普遍配置安全芯片,密钥管理远远不如智能手机安全。
Independent Security Evaluators 去年发布的一份研究报告发现,桌面端密码管理器可以通过扫描内存找到主密码。《华盛顿邮报》报道相关事情并公开了一个演示视频。
安全研究员 Adrian Bednarek 提取1Password 主密码的视频
桌面端上常见的密码管理器技术方案有两种:
1. 桌面客户端
大约在十几年前, PBKDF 算法开始成熟,第二代密码管理器允许用户设置主密码,将主密码转换为密钥来加密保护用户的数据,这为密码管理带来了真正的保护。直到今天,大多数密码管理器仍然基于这一技术。
2. 插件密码管理器
桌面端软件通常都可以记住密码,输入一次密码后,用户很少需要再次输入。而运行在浏览器中的网站则经常需要用户输入密码,所以在电脑端,用户大多时候是在登录网页时会用到密码管理器。
插件密码管理器是基于浏览器插件技术实现的密码管理器客户端,通常与其他平台客户端保持云端同步。它不仅具备桌面客户端的主要功能,而且能辅助填充网页中的密码框,因此深受用户喜爱。
不建议使用浏览器自带的密码管理器,它们大多属于第一代密码管理器——有管理,无保护。
我们经过深入调研后发现,这两种技术方案在安全性上都不理想。因此没有采用它们,而是独创设计了扫码远程加密填充方案,让用户在电脑端浏览器上也能安全地填充密码。
二、技术设计
1. 不采用插件密码管理器技术
大多数插件密码管理器,都基于浏览器插件接口实现完整的客户端,包括:用户交互界面、自动填充、加密解密、密码数据库存储和云端同步数据库等模块。
除了桌面平台本身缺少完善的沙盒保护和安全芯片等这些不足之处外,基于浏览器平台的插件密码管理器,还面临更多严重的安全威胁:
- 主密码泄漏风险
桌面客户端可以采用一些系统底层技术,防止 Keylogger 程序偷取主密码,但是基于 Web 技术的插件密码管理器程序,无法访问操作系统的底层接口,完全依赖浏览器的密码输入框,无法防范Keylogger
攻击。
- 浏览器漏洞
数据来源:CVE Details
浏览器天然联网的特性,让很多漏洞更容易被黑客远程利用。基于浏览器平台的插件密码管理器也很容易被攻击。黑客不论是在操作系统上植入恶意程序,还是攻破浏览器的保护,都很容易破解插件密码管理器。
- 浏览器插件技术暴露难以控制的攻击面
安全研究员 Martin Vigo 曾在 Even the LastPass Will be Stolen, Deal with It! 中演示了破解 LastPass 插件的方法,其中基于插件客户端的方法就有 4 种。
浏览器的插件开发接口基于 Web 技术,非常开放灵活。恶意程序通过 Web DOM/JS(Document Object Model/Javascript),几乎可以访问和控制页面中的任何内容。著名安全研究员 Sean Cassidy 在他的博文Browser Extension Password Managers Should Not Be Used中认为无法避免插件密码管理器的风险。
2. 独创的插件设计
设计逻辑
在研究技术方案过程中,我们逐步探索出这样的设计逻辑:
- 基于浏览器的插件技术
浏览器插件可以方便解析必要信息,例如网页中是否有登录框、当前网址;帮助用户自动填充密码时,也可以使用 DOM/JS 技术,将用户名和密码填入文本框中。所以,基于插件技术才能更好地帮助用户。
- 插件不管理用户密码
浏览器插件平台在安全上的诸多风险难以克服,因此索性就不做密码管理,直接将插件作为神锁离线版 app 在浏览器中的延伸。插件不管理也不保存用户密码,不暴露这个攻击面,不给黑客留下攻击的机会。
相当于基于插件技术实现一个远程自动填充框架,而不是一个密码管理器。
- 获取填充信息
自动填充的原理是:先从网页中获取需要填充密码的相关信息(网址等),再从神锁离线版 app 中选择对应账号。App 没有网络权限,不能访问网络,那如何将网页中得到的信息传输到 app 中呢?我们没有给神锁离线版 app 增加网络权限,而是改变了信息的传输方式:
a. 插件将网页信息编码成二维码,展示在屏幕上
b. 神锁离线版 app 扫码获取信息,无需使用网络
- 填充
同样,没有网络权限的神锁离线版又怎样将用户所选的账号密码发送到插件呢?
是否可以使用电脑上的摄像头扫码手机 app 呢?使用电脑摄像头扫码虽然可行,但操作起来实在不方便。
智能手机都安装有手机浏览器,可以通过浏览器运行云端的 H5 网页程序把数据发送到插件。发送的数据作为 H5 网页的参数输入,H5 网页也能方便查看源代码,用户完全可以自行审计整个数据传输的安全性。
系统架构
《是时候放弃插件密码管理器,改用密码管理器插件了》一文介绍了插件的使用方法。其设计原理如下:
- 插件检测到页面登录框后,生成椭圆曲线密钥对 (ECC 密钥对,elliptic-curve public–private key pair) ,将公钥和网址等信息编码成二维码,展示在页面上。
- 用户使用神锁离线版 app 扫码后,app 会让用户选择要填充的账号。
3. 用户选择账号后,神锁离线版 app 就会:
a. 生成 ECC 密钥对
b. 使用 ECDH 算法生成共享密钥
c. 使用共享密钥加密用户名、密码等信息
4. 神锁离线版 app 启动手机浏览器,将加密数据和 ECC 公钥发送到插件
5. 插件使用 ECDH 算法生成共享密钥,解密得到用户名和密码
6. 插件将用户名和密码填充到登录框中
通过 app 端到插件端的 ECDH 密钥协商,实现了端到端加密,确保用户密码不会由于云端传输而被黑客甚至内部员工偷取。
使用神锁离线版自动填充时,用户需要在手机上操作两次。和插件密码管理器不同的是,桌面或者网页中的恶意程序无法攻击手机App。
3. 插件程序组件介绍
插件架构
典型的 Chrome 浏览器插件有 4 大组件:
Background Script
背景脚本负责处理事件和消息UI Elements
包括插件 icon 上的 popup,以及其他界面元素Content Script
可以访问网页中的内容Options Page
允许用户设置一些选项参数等
每个组件都隔离在独立的进程中运行,提升安全性。组件之间使用插件平台提供的消息机制通信。
神锁离线版插件的UI Elements
和Options Page
比较简单,这就不讨论了。Content Script
和Background Script
的工作原理如下:
Content Script
主要负责检测页面中的登录框,以及将接收到的用户名和密码填充到登录框中。它提供了两方面的安全防护:
1. 防欺诈
自动填充虽然方便,但也暴露了一个攻击面,黑客可能利用自动填充偷取用户密码。今年的一篇论文 Revisiting Security Vulnerabilities in Commercial Password Managers ,重点研究了一些密码管理器自动填充的防欺诈能力,发现它们普遍做得都不够好。而神锁离线版 App 的高级防欺诈能力可以有效防范这些欺诈。
神锁离线版插件继承了app 已有的防欺诈能力, Content Script
结合登录页面的信息,还提供了更多的欺诈检测能力:
- 网页使用了不安全的 HTTP 传输协议,填充和提交密码可能会泄密
- 登录域名与当前网页域名不一致,填充和提交密码也可能会泄密
为什么登录域名应该与当前网页域名一致?
互联网平台的账号管理服务,内容一般比较精简,不会包含第三方内容,执行更加严格的安全审计流程,甚至由专业的独立团队负责。
业务网页以功能为主,内容丰富,包含很多第三方资源,甚至大量第三方广告。开发流程也不像账号管理那样严格,很难保证页面中所有内容的安全,存在盗号风险。
2. 防破解
目前来说,ECC 算法是很安全的,暴力破解非常困难。而另一方面,量子计算已经显示出未来破解 ECC 算法的潜力。无论是为了防范哪种风险,都很有必要限制 ECC 密钥的暴露时间,所以我们给二维码设置了 2 分钟的有效期,2 分钟后自动关闭扫码框。神锁离线版 App 再扫描 2 分钟之前的二维码,会提示过期,不会执行自动填充操作。
2 分钟时间一般够用户拿出手机扫码填充,而无需手忙脚乱;即使将来量子计算破解 ECC 算法成熟了,预计也很难在 2 分钟以内完成破解,传统的计算机就更不可能破解了。
Background Script
负责密钥管理和接收 app 发送过来的加密密码,这是远程自动填充框架的核心。因此我们做了很多的安全设计,包括:
- 密钥管理后台进程隔离
密钥管理和云端通信都在插件后台进程中运行,与前端页面完全隔离。
这意味着页面中的恶意 JS 代码无法通过 DOM 接口访问到后台进程中的加密数据。
- 请求限速
某些密码管理器大量泄露用户密码的原因之一就是对数据请求没有限制,恶意代码可以模拟网页登录,偷取大量网站用户的密码。
为此,我们设计了请求限速算法,限制创建密钥对和二维码的速度,直接拒绝明显超出正常操作的请求。
- 高强度椭圆曲线密码学算法
采用非对称高强度椭圆曲线算法,协商加密密钥,实现对填充数据的端到端(神锁离线版 app 端到插件端)二次加密,即使是内部员工也无法偷看填充密码。
通常可以选择的 ECC 曲线有 P-256、P-384、P-521 等,兼顾安全性和兼容性,我们选择了 ECC P-384。
- 私钥不可提取
const curve = {name: "ECDH", namedCurve: "P-384"};
page.keyPair = await window.crypto.subtle.generateKey(curve, false, ["deriveKey"]);
在调用Webcrypto
API 生成密钥时,设置extractable
参数 false,禁止提取私钥。
恶意程序即使突破了浏览器的进程隔离,也仍然无法读取不可导出的私钥,除非它还能更进一步突破浏览器的密钥管理保护。
- 一次一密
不存储、不重用 ECC 密钥对。不仅每个页面会生成独立的密钥对,而且同一个页面每次打开扫码框都会重新生成。
结合Content Script
的 2 分钟二维码有效期限制,极大提升了破解成本。黑客即使破解某次加密,也无法破解另一次填充。
插件接收到云端发送过来的 ECC 公钥和加密数据后,接下来:
- 协商加密密钥
采用标准的ECDH
算法,生成共享的AES-256-GCM
密钥。
const curve = {name: "ECDH", namedCurve: "P-384"};
const publicKey = await window.crypto.subtle.importKey('spki', keyBytes, curve, true, []);
const ecdh = {name: "ECDH", public: publicKey};
const aes = {name: "AES-GCM", length: 256};
const secretKey = await window.crypto.subtle.deriveKey(ecdh, page.keyPair.privateKey, aes, true, ["encrypt", "decrypt"]);
2. 解密数据
解析出AES-256-GCM
的IV(Initial Vector)
参数和密文后,调用webcrypto
API 得到原文。
const ivBytes = Uint8Array.from(window.atob(encrypted.iv), c => c.charCodeAt(0));
const cipherBytes = Uint8Array.from(window.atob(encrypted.cipher), c => c.charCodeAt(0));
const aesParams = {name: "AES-GCM", iv: ivBytes};
const bytes = await window.crypto.subtle.decrypt(aesParams, secretKey, cipherBytes);
选用AES-256-GCM
模式,在解密时还可以校验数据是否被篡改过。相比AES-CBC
等其他模式,进一步提升安全性。
当然,网络通信必须全部采用 HTTPS/WSS 协议,再增加一层安全防护。
三、安全对比分析
大多数插件密码管理器是一个完整的云同步客户端,神锁离线版对浏览器的支持,拆解成了两个协同工作的组件:
- 手机端神锁离线版 app:利用手机系统的安全特性(网络权限、沙盒保护、安全芯片等)保护好用户密码
- 浏览器插件:充分利用浏览器提供的开发接口,实现远程自动填充框架,确保通信数据安全并防止欺诈
将功能分解且分散在不同的终端,有效减小了攻击面,能够更有效地保护用户数据安全。
攻击面总体对比
攻击面 | 神锁离线版 App | 神锁离线版插件 | 插件密码管理器 |
---|---|---|---|
网络 | N | Y | Y |
持久存储 | Y | N | Y |
交互界面 | Y | Y | Y |
Web DOM | N | Y | Y |
插件密码管理器会暴露 4 个攻击面,而神锁离线版 App 会暴露 2 个,插件暴露 3 个。
神锁离线版 App 和插件将两个风险最大的攻击面彻底分离——存储数据不联网、联网不存储数据。
那么,相比插件密码管理器,神锁离线版插件在各个攻击面上做了哪些改进呢?
1. 网络攻击
- 网页中的恶意代码、恶意插件等,可能利用插件程序的安全漏洞来偷取用户存储的密码。
- 服务商云端。服务商内部“坏员工”,或者黑客入侵服务商云端,都可能从云端实施攻击。比如在插件加载云端网页中的程序代码时,植入恶意代码,就可能偷取用户输入的主密码 / 密钥。而用户数据库早已同步到云端,就缺这把钥匙了。
神锁离线版插件虽然也无法彻底杜绝恶意代码、插件等偷取正在填充的密码,但是不会泄漏所有密码,因为它们保存在更安全的手机系统中,不会受桌面端的影响。
2. 持久存储
Windows 上运行的很多其他程序,都可以读取 Chrome 浏览器的存储数据,插件密码管理器存储的数据也在其中,包括加密的密码数据库,插件密码管理器登录服务的 cookie,以及其他重要数据。
如果用户选择保存主密码,恶意程序就可以解密出所有密码。如果没有保存,恶意程序需要的也仅仅剩一个主密码了。虽然主密码应该很长、很复杂、唯一,但很多用户仍然会使用弱密码作为主密码,仍然会重用主密码,恶意程序还可以通过Keylogger
技术偷取用户输入的主密码。
当然,这还是比 Chrome 自带的密码管理器要安全很多,毕竟它连主密码都不要。
HackBrowserData, 国人当自强
神锁离线版插件没有暴露这个攻击面。
3. 交互界面
Sean Cassidy 在 LostPass 中展示了一项技术:利用像素级模仿密码管理器界面,偷取用户主密码。
钓鱼攻击往往利用容易忽略或难以分辨的细节,误导用户将密码输入到恶意程序 / 网页中。与浏览器集成度越高的插件,往往越容易被恶意程序钓鱼。我们都知道,制作这种像素级完全一致的界面并没有技术上的障碍。
浏览器没有为插件提供很多特别的界面支持,不能让插件密码管理器的界面显得特别,不能帮助用户分辨和防范针对密码管理器的钓鱼攻击。这就尴尬了:
本来应该防范钓鱼的密码管理器,也可以被钓鱼!
神锁离线版插件和 App 一样,没有账号,无需注册,无需登录,无需主密码,无鱼可钓。
4.Web DOM
这是浏览器插件独有的攻击面。开头演示的视频,就是利用浏览器的 DOM 编程接口,操纵了插件密码管理器展示的界面,偷取了用户密码。如果可以利用合适的漏洞,甚至都不需要用户操作,偷密码于无形之中。
使用神锁离线版插件填充密码,需要用户手动扫码,所以用户必然知道自己正在登录网站。恶意程序不可能在用户没有意识的情况下,发动攻击,自动偷取密码。
其他安全增强
- 防欺诈能力
论文《 Revisiting Security Vulnerabilities in Commercial Password Managers 》中使用了多种欺诈方法攻击多款流行的密码管理器,没有一款可以躲过所有的欺诈。
神锁离线版插件增强的防欺诈,再结合 App 端的高级防欺诈,可以有效识别出论文中提到的各种欺诈。
- 权限要求
查看插件manifest.json
,可以看到神锁离线版插件要求的权限很少,不能读取用户浏览历史记录,不能监控网络通信。所以,神锁离线版插件既不能偷取用户这些数据,也不会因为被黑客攻破而泄露用户隐私。
- 连接域名
同样在manifest.json
中,很多插件密码管理器会声明连接的服务域名,还有不受自己控制的第三方域名。服务商要确保很多个服务 / 域名的安全,甚至是第三方服务的安全,难度可以想像。
神锁离线版不会连接第三方服务,也仅仅开放一个连接域名,相比要安全很多。
四、安全设计总结
神锁离线版支持桌面浏览器,安全设计主要表现在这几个方面:
密码存储
插件不保存任何用户密码,密码仍然全部存储在更安全的手机端 app——采用了第四代安全存储设计。
超过 95% 的安全事故都涉及网络,神锁离线版 App 仍然保持离线,没有暴露这个最大的攻击面,不受网络相关攻击的影响。
密码传输
用户在手机端选择要填充的密码,密码被加密后传输到插件,插件解密密码并填充到登录框中。神锁离线版插件采用了以下技术,确保传输的密码安全:
- 密钥管理后台进程隔离
- 使用 ECDH 高强度椭圆曲线密码学算法,协商端到端密钥
- 私钥不可提取
- 一次一密
- 采用
AES-256-GCM
高强度加密,且防数据篡改 - 底层通信采用 HTTPS/WSS
- 限制密钥有效时间仅 2 分钟
大家知道,HTTPS/TLS 也广泛采用 ECDH/AES 来确保数据安全,大多数密码管理器云端同步都会基于 HTTPS/TLS。而神锁离线版插件实现的 ECDH/AES 算法比 HTTPS/TLS 更安全,下一篇再做详细对比分析。
防欺诈
神锁离线版一向非常重视防欺诈能力,在插件上同样延续了这个优良传统,做了不少新设计:
- 需用户手动扫码
无法杜绝 Web DOM 的攻击面,这给恶意程序留下了很多欺诈机会,但神锁离线版 app 管理的密码无论如何都不会凭空飞到桌面浏览器中。用户手动扫码这个操作,既让用户明确意识到密码会发送到桌面浏览器,又限制了发送密码的速度。程序可以每秒执行数百万次,手动扫码是不可能的。即使用户不小心上当受骗,这个设计也有助于限制泄密的数量和速度。
- 请求限速
- 继承 App 原来的高级防欺诈功能
在手机上选择账号填充时,App 会清晰地展示当前正在填充的网址、是否需要填充密码等信息。如果用户选择填充的账号存在泄密风险,还会弹框提醒。例如,用户打开了一个像素级复刻的钓鱼网站faceb00k.com
,在手机端选择facebook
账号填充时,App 就会提醒用户这个是钓鱼网站。
- 检测网页是否使用了不安全的 HTTP 传输协议
- 检测登录域名是否与当前网页域名不一致
特别指出:通过插件填充密码,无法避免密码被恶意插件或者网页中的恶意 JS 脚本通过网页 DOM 读取。对此,技术上还没有办法杜绝,即使是用户手动输入密码,也同样无法避免。
本文转自InfoQ,作者:神锁离线版
原文链接:https://www.infoq.cn/article/c4hSUF2MmYROFPllXRe7
未经许可不得转载
未完待续......
- 神锁离线版插件端到端加密比HTTPS更安全
神锁离线版插件的加密传输有多安全?比银行都在使用的HTTPS还安全。
- 验证神锁离线版的安全机制