加密钱包安全

谈谈与加密钱包相关的风险和威胁,然后转向设计问题和实施问题。

当您开发“安全”的加密钱包时会出什么问题?如何消除典型的安全错误,构建具有多层数据保护的安全应用程序,防止助记词泄露和交易伪造? 这篇文章将帮助开发人员构建更安全的加密钱包并避免加密钱包漏洞文章开头分享一个区块链安全和智能合约审计的交流群:741631068!

image.png 首先,让我们谈谈与加密钱包相关的风险和威胁,然后转向设计问题和实施问题。在金融风险方面,加密钱包的安全基线是 "一个古老的良好银行应用程序" ,这意味着OWASP ASVS L3MASVS L2, 和 PSD2是很好的起点。

1. 热钱包与冷钱包

托管和非托管区块链钱包之间的区别在安全方面非常简单。

托管加密钱包依赖第三方(后端)来存储用户的私钥,需要更高的用户信任度。非托管加密钱包完全由用户控制,使他们对代币的安全负责。通常,非托管加密钱包是开源的,以显示用户的信任和安全。

开源是一把双刃剑,因为攻击者可以轻松阅读实现细节并发现缺陷。

公链(Tezos, XRPL, Cardano, Bitcoin, Ethereum等)的加密钱包不“存储”除非托管钱包中的帐户密钥之外的任何用户数据:所有交易都是公开的,可以在公共分类账上查看。

冷加密钱包(离线、硬件、纸钱包)是持有加密货币最安全的方法之一,因为它们没有连接到互联网。但为了方便起见,人们更喜欢热(在线)钱包:移动应用程序或web扩展程序。

保护热加密钱包是权衡取舍的典型做法:安全性与可用性

2. 加密钱包的安全风险和威胁

将加密钱包视为区块链分类账的“网关”。

攻击面很广:它将特定于账本的安全问题与金融应用的典型风险和威胁相结合。此外,加密钱包的安全性在很大程度上取决于它们的实现:所选平台(web、移动端)和开发人员的编程选择。

了解各个层面的风险和威胁有助于在密码学、平台信任、分类账细节和钱包的确切实现的重叠中找到安全错误。

这种重叠隐藏了最有趣的问题。

去匿名化

在公链上,所有加密交易都是公开的。因此,用户身份和公共地址之间的可链接性(去匿名化)可能导致用户的身份或 IP 地址的泄露。请参阅Bitcoin P2P 网络中客户端的去匿名化

即使是像 Zcash 或 Monero 这样以隐私为中心的系统也会受到现有去匿名化技术的影响(详见ZCash 中匿名性的实证分析ZCash 中挖矿的隐私和可链接性Monero 区块链的可追溯性分析),尽管程度较小。公链容易受到通过交易图分析进行的用户去匿名化和通过观察节点连接进行的 IP 地址去匿名化的攻击。

加密钱包开发人员通常会忽视用户去匿名化。

这就是为什么我们建议对用户进行有关肩膀冲浪攻击(最大限度地减少屏幕上出现敏感数据的时间)和将朋友帐户添加到地址簿的风险提示。

拒绝服务 (DoS)

在极少数情况下,非托管钱包可以成为对单个节点甚至整个区块链的DoS攻击的组成部分。当加密货币解决方案缺少可以验证和过滤交易的中间件实体(例如加密钱包后端服务器)时,就会发生这种情况。

在这种情况下,格式错误的交易直接进入区块链,浪费节点的资源,并阻止有效交易的处理。

3. 加密钱包的应用程序安全漏洞

从appsec的角度来看,加密钱包只是应用程序。

它们具有与任何其他应用程序类似的威胁媒介,包括用户网络钓鱼、注入、MitM、暴力破解用户密码、重放攻击、逆向工程和恶意第三方库——所有可用于窃取钱包机密或虚假交易的东西。

所有非托管加密钱包的主要目的是存储钱包的秘钥并签署交易。

因此,用户身份验证和安全数据存储是每个钱包中最重要的安全控制措施。

用户身份验证

本地身份验证不仅仅是为钱包应用程序设置密码。

加密钱包经常错过有关密码和身份验证流程的关键控制:密码策略、轮换、防御密码暴力、执行敏感操作之前的额外身份验证步骤、生物识别验证、将生物识别身份验证绑定到钥匙串/密钥库等。

缺乏这些控制降低了攻击者的门槛,并且时不时地为助记词和凭据泄露提供了机会。

本地数据存储

由于非托管钱包需要在本地存储助记词、种子和私钥,因此了解本地存储的工作原理以及针对它的常见攻击有哪些至关重要。

在存储数据之前,开发人员应该获得以下问题的答案:

  • 应该使用什么样的存储来提供最好的安全保证?想想浏览器本地存储与会话存储,Keychain/Keystore 与存储在 plist/首选项中。
  • 存储是否可以作为文件访问?其他应用程序可以访问它吗?
  • 你能验证这种存储的真实性吗?是否可以从一个钱包“窃取”存储空间并将其毫无问题地放入另一个钱包?
  • 是否有任何完整性检查?或者任何人都可以更改存储的数据,而加密钱包不会发现?
  • 存储是否提供加密(甚至硬件支持的加密),或者数据是否以明文形式存储?
  • 在将数据存储之前是否应该使用应用程序级加密来加密数据?如果是这种情况,加密密钥将存储在哪里以及如何导出它?

image.png 尽管 000003.log 它不是日志文件,而是 Web 扩展的本地存储。它可以复制粘贴并放入另一个web扩展中,大多数人甚至不会注意到。

4. 移动加密钱包的平台信任问题

加密货币钱包的安全性在很大程度上取决于其平台(Web,移动,桌面)的安全性以及应用程序和平台之间安全控制的紧密集成。

加密钱包支持的平台越多,可能出现的相关安全问题就越多。始终牢记威胁模型,让我们研究一下移动平台安全性的各个方面。

例如,加密钱包移动应用程序通常不会检查设备是否受信任:它是否已root或越狱,是否安装了可能有害的应用程序或逆向工程工具等。现有的移动恶意软件可用于从应用程序的内存中窃取用户的凭据、助记词或私钥(请参阅 Pegasus、远程 iOS 和 Android 间谍软件)。

OWASP MASVS L2 建议对财务、支付和其他运行高度敏感数据的应用实施针对逆向工程和篡改的保护。它还建议通知用户设备不受信任,因为他们可能不知道。

移动平台(iOS,Android)确实提供设备级安全控制。要求用户设置设备级密码是一项简单的功能,会给攻击者带来重大障碍。如果未安装密码,任何人都可以解锁手机并窃取钱包数据,甚至访问钥匙串/密钥库。加密钱包应该要求使用设备级密码,或者至少通知用户应该设置它。

不信任平台的另一个很好的例子是在将钱包的数据放入钥匙串/密钥库之前对其进行加密。因此,即使手机受到攻击并且攻击者可以访问钥匙串/密钥库,数据也会在那里加密(请参阅应用程序级加密)。

image.png 即使没有越狱,也只需要 objection工具的命令即可在未锁定的iOS设备上显示钥匙串内容。 虽然移动设备和操作系统的漏洞超出了开发人员的范围,但他们可以限制应用程序在越狱/root设备上的功能,不支持旧设备,使用本机安全存储,限制敏感数据的生命周期,从而降低成功攻击和数据泄露的风险。

OWASP(MASVSMSTG)和NIST(SP 800-57,SP 800-63SSDF等)描述了经过验证的行业指南和最佳实践。

5. web加密钱包的平台信任问题

网络加密钱包的安全性在某些假设下运行,即存储的数据是安全的并且不会泄漏。但是 Web 扩展(和用户)没有运行时代码完整性的概念,因此可以随时修改用户计算机上运行的任何内容。

Web恶意软件的可能性是无限的:当用户尝试向其朋友发送令牌时,通过显示恶意版本的“导入帐户”或“发送交易”屏幕或替换剪贴板的内容以利用复制粘贴操作来网络钓鱼用户。

由于浏览器扩展沙箱,其他扩展程序、网站和浏览器外进程通常无法访问钱包进程内存和读取敏感数据。请参阅突破 Chrome WebExtension 沙盒

但是,浏览器是漏洞利用的目标攻击者提供内存访问权限。

根据谷歌安全博客,影响浏览器的安全漏洞中有大约70%是内存问题。

Specter和Meltdown攻击由谷歌零项目于 2018 年发布;它们允许通过侧信道攻击读取特权内存。

尽管没有任何措施可以 100% 防止 0 day和未知漏洞,但有一些安全准则可以帮助开发人员减少成功利用已知错误的机会。

Chrome 团队建议开发者启用网站隔离,使用无嗅探内容类型标头,并防止 Cookie 进入渲染的进程内存。OWASP ASVSWSTG 和备忘单也是行业最佳实践的良好灵感来源。

6. 加密钱包的加密缺陷

非托管钱包执行许多加密操作:它们加密存储钱包的秘密,签署交易,并使用安全协议与去中心化应用程序进行通信。

一些加密选择是由社区决定的(因此,BIP39通常用于生成助记词,XRPL使用XLS-12),但加密钱包开发人员仍然有很大的产生漏洞的可能。

当人们听说加密货币钱包时,他们假设开发人员是“加密”方面的专家,他们将其与“密码学”混淆。

但通常情况下,加密钱包开发人员与从事区块链加密核心工作的人不同。

通常,他们是常规的web、移动和桌面开发人员,他们了解加密货币的概念,但不是现代应用密码学的专家。因此,他们的加密代码存在常见的设计缺陷和实现错误。

为特定用例使用正确的加密原语是一项单独的技能,需要额外的知识和经验

加密钱包中最常见的加密问题是:

  • 从没有任何KDF的低熵秘密中派生加密密钥或选择较差的KDF参数(考虑使用500轮的PBKDF2从用户密码生成加密密钥,而不是 argon2, scrypt, or PBKDF2 with 310000 rounds)。
  • 错误和异常处理不当,导致salt、nonce或IV误用或泄漏。
  • 将不合适的加密原语用于所需目的(MD5 而不是 Argon2DI,AES-OFB 而不是 AES-GCM,SHA-256 而不是 HMAC-SHA256);
  • 使用不合适的分组密码模式进行数据加密(AES-CBC 不提供完整性检查,最好使用 AES-GCM)。
  • 犯典型的加密错误:AES-CBC与zero IV,自制自己的加密协议,使用math.random而不是crypto.random,使用base64作为“加密”,等等。
  • 密钥管理不佳(以明文形式存储加密密钥与数据;缺少密钥轮换、过期;将加密密钥用于多种不同目的)。
  • 敏感信息的内存管理不正确(在应用程序代码中“随处可见”敏感数据,不限制其在内存、存储和屏幕上的生命周期)。
  • 以明文形式存储钱包的敏感数据

image.png 当使用来自 react-native-aes-crypto 生成 IV 时,不要忘记处理randomKey()``IV == nil这种情况。

错误的加密选择的组合会导致灾难

1.钱包数据的弱存储方案

我们看到的最有趣的加密问题是设计和实现错误或错误选择的组合。

让我们看看几个小问题如何结合起来可以简化发现钱包的助记词——这是所有非托管加密钱包的核心。

一个加密钱包将敏感数据存储在一个文件中,加密但格式非常人性化。每个存储字段都有一个可理解的名称。

文件本身存储在用户计算机上的文件夹中,好奇的眼睛和系统中的任何其他应用程序都可以访问。

wallet_mnemonics:
encrypted_data: "4198fbf....aaca6d"
iv: "e84c2e2bb7c...904f6a16bbad9"
salt: "da2111aeab1182...0c30614931"

password_check:
encrypted_data: "12e1a2ba2c...8492e9"
iv: "521a231a21a...a1bb123c86"
salt: "73aac01746d4d...928da60adb4"

加密钱包将数据存储在一个文件中,并按字段加密。

加密方案如下:

image.png 这意味着每个数据字段都使用 AES-256-GCM 和每个字段派生的唯一加密密钥进行加密。所有加密密钥都是使用不同的盐从相同的用户密码派生出来的。

细节决定成败。如果攻击者可以访问该文件,他们只需要解密一个字段:wallet_mnemonics. 攻击者知道加密数据的 salt 和 IV,这使得暴力破解非常简单。 人性化的名称确实可以帮助攻击者快速找到所需的字段。

2.用同一个密码加密多个字段

使用password_check字段可以更快地强制执行。这是一个特殊的实用程序字段,加密钱包使用它来确定用户是否输入了正确的密码。如果此字段的解密成功,则用户密码是正确的。

password_check字段的原始(明文)值为“null”。因此,开发人员实际上是用用户的密码加密“null”,将其加密存储,然后解密并比较是否解密==null。

由于所有字段都是由同一密码派生的密钥加密的,因此攻击者可以通过首先解密password_check值来优化暴力。攻击者知道salt、IV和明文null的值。由于已知且短的明文,暴力强制password_check将比暴力强制wallet_mnemonics更快。

成功的暴力会产生一个用户密码,攻击者使用该密码来解密wallet_mnemonics字段(已经知道其salt和IV)。

3. KDF 选择不当和参数薄弱

通常,一个强大的基于密码的KDF应该可以防止暴力强制,使其非常长,因为KDF被设计得很慢。然而,这个特定的加密钱包使用了PBKDF2-HMAC-SHA256,只有1000次迭代(而不是NIST 和 OWASP 目前推荐的310000 次迭代)。

众所周知,PBKDF2存在弱点、CPU 和 GPU 优化以实现更快的暴力破解。像John-the-Ripper这样的工具已经为破解 PBKDF2-HMAC-SHA256 提供了 GPU 支持。

使用“老式”PBKDF2 是一个糟糕的选择,它使暴力破解变得更加容易。使用哪个 KDF?

4. 允许低熵用户密码

下一道防线是用户密码。低熵密码,如“Password1”或“Qwerty123”,非常常见。这个加密钱包使用了以下密码规则:8个字符长度,1个数字,1个大写字母和1个小写字母,看起来不错。

但是,它没有检查密码是否是低熵字符串(如“Aa11111”)或字典单词(“Matrix12”),或者是否曾被泄露。请参见NIST SP 800-63b

因此,暴力破解更直接的密码所需的时间更少。

组合

在这个例子中,错误选择的组合可能会导致——在不幸的情况下——窃取和逆转加密钱包的助记词。文件的位置、它的人性化格式、IV 和盐与加密数据放在一起,使用“null”字段进行检查,使用从每个字段的相同密码派生的加密密钥,选择 PBKDF2 并使用太少的迭代为此,允许使用弱密码,最后成为一个开源钱包。

7. 与去中心化应用程序的通信

加密钱包的功能越多,它们的攻击面就越大,威胁模型也就越复杂。

这种典型的钱包功能之一是与第三方去中心化应用程序交互(取决于区块链,它们被称为 dApps 或 xApps)。一些加密钱包允许与预定义的 dApp 列表快速交互,而其他加密钱包则将 dApp 作为 WebView 嵌入。

此通信引入了以下威胁向量:

  • 钱包和 dApp 之间的通信。如果没有适当的身份验证、传输中的数据加密和交易数据的授权,攻击者可能会拦截和修改请求——例如更改交易金额或收件人地址。
  • 恶意 dApp。大多数区块链都有数十个由社区创建的 dApp,其中一些突然流行起来,另一些则被忽视。即使 dApp 来自可信来源,也不意味着它没有漏洞。此外,没有什么可以阻止通过修改后变成恶意的 dApp 攻击用户(参考 DApp 引起的典型漏洞)。
  • dApps 集成到钱包中的方式。例如,如果加密钱包是一个移动应用程序,dApps 可以在 WebView 中作为常规网页打开。因此,它们带来了所有与web相关的风险:注入、劫持和泄漏。

为了减轻这些威胁媒介,我们建议在加密钱包和 dApp(TLS 1.3 或特定协议,如Tezos 生态系统的 Beacon) 之间使用强大的传输加密,进行适当的会话管理和相互身份验证,并观察集成点。

8. 用户是单点故障

只要用户保持安全,非托管加密钱包就是安全的。因此,除了应用内安全工作外,让用户了解他们的责任是每个加密钱包开发团队的使命。

无论应用程序的安全控制有多严格,如果用户很容易被网络钓鱼攻击欺骗或者只是丢失了钱包的秘钥。

开发人员应在应用程序中包含快速安全提示和提示,尤其是当用户与关键功能交互时(例如将他们的代币转移到新地址)。

image.png

Coinbase 和Bitcoin钱包等流行钱包有多种用户提示方法。 提醒用户,因为攻击者通常不需要任何技术技能即可通过攻击获取某人的敏感信息,即观察他们的计算机或移动设备屏幕和键盘。

用户可能知道区块链是什么,当前的货币汇率是多少,如何发送交易,但他们可能不知道它是如何工作的或者账户助记词和私钥是什么以及为什么需要它。用户可能不知道助记词应该与信用卡 CVV 一样对待。

在为加密钱包构建新功能时,请始终考虑用户可能如何误用和滥用应用程序。

尽可能对用户进行提醒,否则他们可能成为钱包安全机制中最薄弱的环节。

9.供应链风险

供应链攻击对加密钱包构成重大风险。供应链风险随着应用程序中使用的外部依赖性的增加而增加。

加密钱包可能有许多可以访问钱包敏感数据的依赖项,例如加密库( ECC)、区块链中使用的特定协议或标准的官方库( BIP39 或 BIP32),以及用于各种可能目的的实用实用程序库( npm)。

我们已经看到具有 110 个外部依赖项的加密钱包。由于每个依赖都有它的依赖,因此依赖总数为 1838(由 yarn audit 估算)。

如果某些依赖项是封闭源代码的,则依赖项混淆攻击可能是相关的。

image.png 典型加密钱包 React Native 应用程序中的第 3 方库

这些库中的任何一个漏洞都是整个钱包的潜在漏洞。 虽然添加另一个依赖项似乎可以节省开发人员的时间,但它可能不是安全相关功能的最佳选择(请参阅NIST SSDF PW.7)。某些依赖项存在可能影响其安全性的未解决问题和 PR。

例如,@elliptic已打开未合并的 PR 以修复 EC 点解码,而 Stanford JavaScript 加密库有 98 个未解决的问题,其中一些问题自 2010 年以来一直存在。

另一个例子是依赖项可能没有所需的安全功能。例如,react-native-fingerprint-scanner不处理生物特征变化的回退操作,react-native-webview不正确清除 WebView 缓存。

我们建议仔细培养外部依赖项、补丁和分叉,定期更新它们,并使用自动化工具来支持该过程(NIST SSDF PW.1、PO.3)。

依赖地狱

研究依赖关系有时会打开一个意想不到的地狱洞。

让我们来看看适用于 iOS 和 Android 的 React Native 加密钱包。它生成用于加密和私钥生成的随机值:

const random = generateRandomValues();

此方法调用mvayngrib/react-native-crypto(现在已弃用并重命名为tradle/react-native-crypto)。mvayngrib/react-native-crypto 有一个 peerDependency react-native-randombytes。反过来,react-native-randombytes 依赖于相当过时的Stanford Javascript Crypto Library (SJCL)。

根据react-native-randombytes 文档,它支持两种生成伪随机字节的方式:同步调用和异步调用。

对于异步生成,该库使用原生 CPRNG:iOS 上的 SecRandomCopyBytes 和 Android 上的 SecureRandom API。对于同步生成,该库使用 SJCL 库中的 CPRNG。

人们之前曾质疑过这个选择。例如,在本期中,一位 React-Native-crypto 维护者确认同步生成不如异步生成安全。但他们计划使用更安全的生成随机值的同步方式进行更新(此更新尚未发生)。

SJCL是最古老的 JavaScript 库之一,最初创建于 2010 年 5 月。SJCL 没有依赖项,这是 javascript 中加密原语的纯粹实现。在WebAPI crypto.getRandomValues可用之前,SJCL 最初是为 Web 浏览器设计的。

现在,SJCL 有许多未解决的问题,它已经好几年没有更新了,并且围绕着关于其随机函数安全性的讨论:bitwiseshiftleft/sjcl#77bitwiseshiftleft/sjcl#178stackoverflow

SJCL 使用random.js从熵池中收集熵,依赖于“鼠标移动”和“键盘监听器”之类的东西。当然,移动设备不像桌面设备那样拥有鼠标和键盘。

以上所有内容使我们认为 SJCL 不是用于移动应用程序的 CPRNG 的合适选择。它不是为了从移动设备获取熵而设计的,没有安全的默认设置并且有一段时间没有更新。

强烈建议密切关注加密伪随机值的来源,因为低熵值会导致导出脆弱且可预测的加密材料,从而使攻击者的工作更容易。

image.png 引入“React-Native-crypto”库也带来了它的许多依赖项。

10. 加密钱包安全实用技巧

用户将相当数量的代币(~钱)信任给加密钱包。他们期望获得与其他金融应用程序、银行应用程序或更好的安全级别相同的安全级别。

一些已经构建了广受欢迎的钱包的团队缺乏安全和密码学专业知识,无法理解他们的实施会给用户带来问题。一些自行车棚的安全控制是Schneier 定律的惊人例子。这不是他们的错,因为他们的业务不同。

负责任的开发人员应该了解何时责任变得困难。或许,当钱包采用达到一定程度时,选择审查和提高安全性应该成为当务之急。

以下是提高加密钱包安全性的一些实用技巧:

  • 从了解风险和威胁开始:加密钱包的风险格局是区块链相关和平台相关风险、密码学和应用程序安全缺陷的组合。
  • 提醒用户。对于非托管加密钱包,用户是系统中最薄弱的环节。尽最大努力防止网络钓鱼攻击:添加提示、屏蔽字段、显示警告并在采取关键操作之前询问用户密码。
  • 遵循密码学的最佳实践:不要实施自己的密码和协议,使用强加密,并注意密钥管理。
  • 不要犹豫,使用开箱即用的平台安全控制:它们允许以最低的开发成本为攻击者“提高标准”。
  • 在 CI 管道中使用自动静态代码分析工具 (SAST)。
  • 在下一个版本公开之前,持续审核您正在使用的所有依赖项并实施适当的修复。在 CI 管道中使用自动化依赖管理工具。
  • 专注于大规模的攻击。虽然您可以涵盖单个案例,但大规模的攻击可能会破坏加密钱包甚至加密货币的声誉。加密货币的声誉等于其成本。
  • 遵循安全编码最佳实践(例如OWASP 安全编码实践):数据最小化、输入验证和清理、最小特权原则等。

11. 加密钱包安全注意事项

加密货币钱包的安全性是一头棘手的野兽。我们发现的所有很酷的加密钱包漏洞和潜在问题都存在于多个缺陷的交汇处:密码学、对本地存储的访问、缺乏身份验证和缺乏输入验证。每个都相对较小,但它们结合起来会打开意想不到的攻击向量。

从防御者的角度来看,加密钱包的攻击面是巨大的。但从攻击者的角度来看,组合 3-4 个缺陷并不难,特别是如果加密钱包的代码是开源的。

因此,不仅要着眼于特定的缺陷,还要着眼于它们的协同作用。不仅通过安全编码和合适的加密原语,而且通过正确的安全设计、使用经过验证的构建块并正确集成它们来防止安全漏洞。

尽早推动安全并遵循安全软件开发周期 (SSDLC) 可以节省花在安全上的时间和预算,并保持良好的声誉。

加密钱包的应用程序安全故障允许比易受攻击的移动银行应用程序更快地窃取资金。与银行不同,公共区块链没有庞大的反欺诈系统或可以恢复交易的客户支持。

点赞 0
收藏 3
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Polaris_tow
Polaris_tow
0x215B...F2F1
欢迎一起学习哦,web3世界的守护者! 交流群:741631068 可以加v:zz15842945138 twitter:https://twitter.com/Polaris_tow