神锁离线版插件的安全设计

是时候放弃插件密码管理器,改用密码管理器插件了 一文中,我们提到插件密码管理器不够安全。

我们做了一个演示:将恶意JS代码注入到 Github一个无需登录的网页 中,通过引诱用户点击关闭广告,偷取了用户的Github密码。

Talk is cheap. Show me the video.

为了演示效果,将登录框、LastPass填充框都设置成了半透明。实际攻击中,可以设置为很低的透明度,肉眼不可见。

这个演示没有利用任何浏览器漏洞。如果利用合适的漏洞,无需用户点击就可以自动偷取密码。

互联网上绝大多数网页都包含大量第三方内容,特别是广告,很难保证所有内容都安全。一旦第三方内容含有恶意代码,插件密码管理器可能就存在泄密的风险。

产品需求

神锁离线版用户很早就强烈要求提供Windows版,把神锁离线版领先的安全保护能力带到Windows上。可惜桌面平台没有完善的沙盒保护,恶意软件不仅可以读取app存储的数据,还可以通过 Keylogger 或者扫描内存数据等方法偷取主密码。而且,桌面平台没有普遍配置安全芯片,密钥管理远不如智能手机安全。

Independent Security Evaluators 去年发布的一份研究报告发现桌面端密码管理器可以通过扫描内存找到主密码 Password Managers: Under the Hood of Secrets Management。华盛顿邮报报道并公开了一个演示视频 Password managers have a security flaw. But you should still use one.

安全研究员 Adrian Bednarek 提取1Password主密码的视频

桌面端上常见的密码管理器技术方案有两种:

  1. 桌面客户端

    大约在十几年前,PBKDF 算法开始成熟,第二代密码管理器 允许用户设置主密码,将主密码转换为密钥来加密保护用户的数据,为密码管理带来了真正的保护。直到今天,大多数密码管理器仍然基于这一技术。

  2. 插件密码管理器

    桌面端软件通常都可以记住密码,输入一次密码后,用户很少需要再次输入。而运行在浏览器中的网站则经常需要用户输入密码,所以在电脑端,用户大多时候是在登录网页时会用到密码管理器。

    插件密码管理器,是基于浏览器插件技术实现的密码管理器客户端,通常与其他平台客户端保持云端同步。它不仅具备桌面客户端的主要功能,而且能辅助填充网页中的密码框,因此深受用户喜爱。

    不建议使用浏览器自带的密码管理器,它们大多属于第一代密码管理器——有管理,无保护。

我们经过深入调研后发现,这两种技术方案在安全性上都不理想。因此没有采用它们,而是独创设计了扫码远程加密填充方案,让用户在电脑端浏览器上也能安全地填充密码。

技术设计

不采用插件密码管理器技术

大多数插件密码管理器,都基于浏览器插件接口实现完整的客户端,包括:用户交互界面,自动填充,加密解密,密码数据库存储,云端同步数据库等模块。

插件密码管理器架构

除了桌面平台本身缺少完善的沙盒保护和安全芯片这些不足之外,基于浏览器平台的插件密码管理器,还面临更多严重的安全威胁:

独创的插件设计

设计逻辑

在研究技术方案过程中,我们逐步探索出这样的设计逻辑:

系统架构

是时候放弃插件密码管理器,改用密码管理器插件了 一文介绍了插件的使用方法。其设计原理如下:

架构图

序列图

sequenceDiagram participant User participant LoginPage participant Extension participant MobileBrowser participant IDGuardOffline note over Extension: make ECC key pair Extension ->> LoginPage: 1. show QR code User ->> IDGuardOffline: 2. scan QR code on page note over IDGuardOffline: show matched account for page User ->> IDGuardOffline: 3. select account note over IDGuardOffline: make ECC key pair and make ECDH agreed secret note over IDGuardOffline: encrypt username and password IDGuardOffline ->> MobileBrowser: 4. encrypted data MobileBrowser ->> Extension: 5. send via Cloud note over Extension: make ECDH agreed secret and decrypt Extension ->> LoginPage: 6. fill
  1. 插件检测到页面登录框后,生成椭圆曲线密钥对(ECC密钥对,elliptic-curve public–private key pair),将公钥和网址等信息编码成二维码,展示在页面上

  2. 用户使用神锁离线版App扫码后,App会让用户选择要填充的账号

    选择填充账号

  3. 用户选择账号后,神锁离线版App就会:

    a. 生成ECC密钥对 b. 使用ECDH算法生成共享密钥 c. 使用共享密钥加密用户名、密码等信息

  4. 神锁离线版App启动手机浏览器,将加密数据以及ECC公钥发送到插件

  5. 插件使用ECDH算法生成共享密钥,解密得到用户名和密码

  6. 插件将用户名和密码填充到登录框中

通过App端到插件端的ECDH密钥协商,实现了端到端加密,确保用户密码不会由于云端传输而被黑客甚至内部员工偷取。

使用神锁离线版自动填充时,用户需要在手机上操作两次。和插件密码管理器不同的是,桌面或者网页中的恶意程序无法攻击手机App。

插件程序组件介绍

插件架构

典型的Chrome浏览器插件有4大组件

每个组件都隔离在独立的进程中运行,提升安全性。组件之间使用插件平台提供的消息机制通信。

神锁离线版插件的UI ElementsOptions Page 比较简单,就不讨论了。Content ScriptBackground Script 的工作原理如下:

sequenceDiagram participant BackgroundScript participant ContentScript participant WebPage participant IDGuardOffline ContentScript ->> WebPage: detect login form ContentScript ->> BackgroundScript: make ECC key pair BackgroundScript ->> ContentScript: public key ContentScript ->> WebPage: show QR code(public key) IDGuardOffline ->> WebPage: scan QR code(by user) note over IDGuardOffline: select account to fill(by user) note over IDGuardOffline: make ECC key pair note over IDGuardOffline: make shared secret key and encrypt IDGuardOffline ->> BackgroundScript: encrypted data, public key via H5 app/cloud note over BackgroundScript: make shared secret key and decrypt BackgroundScript ->> ContentScript: username, password ContentScript ->> WebPage: fill

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发送过来的加密密码,是远程自动填充框架的核心。因此我们做了非常多的安全设计,包括:

插件接收到云端发送过来的ECC公钥和加密的数据后,接下来:

  1. 协商加密密钥

    采用标准的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-GCMIV(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 神锁离线版插件 插件密码管理器
网络 N Y Y
持久存储 Y N Y
交互界面 Y Y Y
Web DOM N Y Y

插件密码管理器会暴露4个攻击面,而神锁离线版App只暴露2个,插件暴露3个。

神锁离线版App和插件将两个风险最大的攻击面彻底分离——存储数据不联网、联网不存储数据

神锁离线版App数据存储在手机端,充分利用手机的安全特性,比插件密码管理器安全很多,不用多说。

那么,神锁离线版插件相比插件密码管理器在各个攻击面上做了哪些改进呢?

  1. 网络攻击

    神锁离线版插件虽然也无法彻底杜绝恶意代码、插件等偷取正在填充的密码,但是不可能泄漏所有密码,因为它们保存在更安全的手机系统中,完全不会受桌面端的影响。

  2. 持久存储

    Windows上运行的很多其他程序,都可以读取Chrome浏览器存储的数据,插件密码管理器存储的数据也在其中,包括加密的密码数据库,插件密码管理器登录服务的cookie,以及其他重要数据。

    如果用户选择保存主密码,恶意程序就可以解密出所有密码。如果没有保存,恶意程序需要的也仅仅剩一个主密码了。虽然主密码应该很长很复杂很唯一,但是很多用户仍然会使用弱密码作为主密码,仍然会重用主密码,恶意程序还可以通过 Keylogger 技术偷取用户输入的主密码。

    当然,这还是比Chrome自带的密码管理器要安全很多,毕竟它连主密码都不要。

    HackBrowserData, 国人当自强

    神锁离线版插件没有暴露这个攻击面。

  3. 交互界面

    Sean Cassidy 在 LostPass 中展示了一项技术:利用像素级模仿密码管理器界面,偷取用户的主密码。

    Pixel-perfect Phishing

    钓鱼攻击往往利用容易忽略或难以分辨的细节,来误导用户将密码输入到恶意程序/网页中。与浏览器集成度越高的插件,往往越容易被恶意程序钓鱼。我们都知道,制作这种像素级完全一致的界面并没有技术上的障碍。

    浏览器没有为插件提供很多特别的界面支持,不能让插件密码管理器的界面显得特别,不能帮助用户分辨和防范针对密码管理器的钓鱼攻击。这就尴尬了:

    本来应该防范钓鱼的密码管理器,也可以被钓鱼!

    神锁离线版插件和App一样,没有账号,无需注册,无需登录,无需主密码,无鱼可钓

  4. Web DOM

    这是浏览器插件独有的攻击面。开头演示的视频,就是利用浏览器的DOM编程接口,操纵了插件密码管理器展示的界面,偷取了用户密码。如果可以利用合适的漏洞,甚至都不需要用户操作,偷密码于无形之中。

    使用神锁离线版插件填充密码,需要用户手动扫码,所以用户必然知道自己正在登录网站。恶意程序不可能在用户没有意识的情况下,发动攻击,自动偷取密码。

其他安全增强

安全设计总结

神锁离线版支持桌面浏览器,安全设计主要表现在这几个方面:

  1. 密码存储

    插件不保存任何用户密码,密码仍然全部存储在更安全的手机端App——采用了第四代安全存储设计

    超过95%的安全事故都涉及网络,神锁离线版App仍然保持离线,没有暴露这个最大的攻击面,不受网络相关攻击的影响。

  2. 密码传输

    用户在手机端选择要填充的密码,密码被加密后传输到插件,插件解密密码并填充到登录框中。神锁离线版插件采用了以下技术,确保传输的密码安全:

    • 密钥管理后台进程隔离
    • 使用ECDH 高强度椭圆曲线密码学算法,协商端到端密钥
    • 私钥不可提取
    • 一次一密
    • 采用 AES-256-GCM 高强度加密,且防数据篡改
    • 底层通信采用 HTTPS/WSS
    • 限制密钥有效时间仅2分钟

    大家知道,HTTPS/TLS也广泛采用ECDH/AES来确保数据安全,大多数密码管理器云端同步都会基于HTTPS/TLS。而神锁离线版插件实现的ECDH/AES算法比HTTPS/TLS更安全,下一篇做详细对比分析

  3. 防欺诈

    神锁离线版一向非常重视防欺诈能力,在插件上同样延续了这个优良传统,做出了不少创新设计:

    • 需用户手动扫码

      尽管Web DOM的攻击面几乎无法杜绝,给恶意程序留下了很多欺诈机会,但神锁离线版App管理的密码无论如何都不会凭空飞到桌面浏览器中。用户手动扫码这个操作,既让用户明确意识到密码会发送到桌面浏览器,又限制了发送密码的速度。程序可以每秒执行数百万次,手动扫码是不可能的。即使用户不小心上当受骗,这个设计也能帮助限制泄密的数量和速度。

    • 请求限速

    • 继承App原来的高级防欺诈功能

      在手机上选择账号填充时,App会清晰地展示当前正在填充的网址、是否需要填充密码等信息。如果用户选择填充的账号存在泄密风险,还会弹框提醒。例如,用户打开了一个像素级复刻的钓鱼网站 faceb00k.com ,在手机端选择 facebook 账号填充时,App就会提醒用户这个是钓鱼网站。

    • 检测网页是否使用了不安全的HTTP传输协议

    • 检测登录域名是否与当前网页域名不一致

特别指出:通过插件填充密码,无法避免密码被恶意插件或者网页中的恶意JS脚本通过网页DOM读取。对此,技术上还没有办法杜绝,即使是用户手动输入密码,也同样无法避免。

原文已发表于 InfoQ


神锁离线版插件系列文章