提升加密钱包安全性的案例
现代加密诈骗剖析
当今大量加密诈骗涉及某种形式的钓鱼攻击,用户被诱骗访问可疑或恶意网站并连接其钱包。主要目标是欺骗用户签署交易,最终使攻击者控制用户的代币。
通常,这一切始于一条推文或某个Telegram群组或Slack频道中的帖子,其中发送了一个链接,宣传具有高年化收益率的新收益农场协议或刚刚开始铸造的新NFT项目。为了与网站互动,用户需要连接其钱包并执行一些确认或授权步骤。
让我们看看常见的NFT授权诈骗。用户被引导至恶意NFT网站,宣传其新NFT系列的限量预铸。然后提示用户连接钱包并签署交易以确认铸造。然而,由于某种原因,交易失败。下一次尝试也是如此。随着每次失败尝试,用户变得越来越沮丧,认为问题导致他们错过了铸造机会。他们的注意力和焦点从关注交易略微转移到错过了一个大好机会。
此时,钓鱼攻击全面展开。经过几次失败尝试后,受害者上钩了。
(图片借自《骗子如何操纵智能合约进行盗窃以及如何避免》)
最终交易不是调用铸造函数,而是调用setApprovalForAll,这实质上将使用户的代币控制权交给恶意行为者。此时用户处于盲目确认交易的状态,希望铸造不会结束。
不幸的是,最后一笔交易成功了。对受害者来说游戏结束。攻击者现在要做的就是迅速行动,在受害者意识到发生了什么之前将代币从用户的钱包转移走。
这类攻击在今天非常普遍。用户偶然发现一个提供新盈利机会的项目链接,他们连接钱包,错误地将代币交给恶意行为者。虽然可以主张用户教育、责任和在与项目互动前进行研究,但我们认为软件也扮演着重要角色。
提升加密钱包安全性的案例
没有人能否认基于区块链的技术和Web3的引入对世界产生了巨大影响。其中许多提供了以下常见功能集:
- 资金转移
- 无需许可的货币交换
- 去中心化治理
- 数字收藏品
无论用于构建这些平台的技术栈如何,最终都是用户构成了平台。这意味着用户需要一种方式与他们选择的平台互动。如今,与基于区块链的平台互动的最用户友好方式是使用加密钱包。简单来说,加密钱包是一种软件,便于使用用户的私钥签署区块链交易。有多种类型的钱包,包括软件、硬件、托管和非托管钱包。出于本文目的,我们将重点关注基于软件的钱包。
在继续之前,让我们短暂绕道Web2。在那个世界中,我们可以说平台(也称为服务、门户或服务器)主要使用基于TCP/IP的技术构建。为了让用户能够与它们互动,他们使用用户代理,也称为Web浏览器。说到这里,我们可以与Web3进行以下类比:
| 技术 | 通信协议 | 用户代理 |
|---|---|---|
| Web2 | HTTP/TLS | Web浏览器 |
| Web3 | 区块链JSON RPC | 加密钱包 |
与加密钱包相比,Web浏览器无疑是更复杂的软件——这是有充分理由的。随着互联网的发展,人们发现了如何在其上放置不同的媒体,网页允许动态和可脚本化的内容。随着时间的推移,HTML和CSS技术的进步改变了单个页面上可以显示的内容和方式。互联网成为人们社交、寻找娱乐和购物的场所。浏览器需要进化以支持新的技术进步,这反过来增加了复杂性。与所有软件一样,复杂性是敌人,而复杂性是错误和漏洞的诞生地。浏览器需要实施控制措施,以帮助减轻基于Web的漏洞,如欺骗、XSS和DNS重绑定,同时仍有助于通过加密的TLS连接促进安全通信。
接下来,让我们看看普通用户的典型加密钱包互动可能是什么样子。
Web3世界的现状
如今使用Web3平台通常意味着用户正在与一个Web应用程序(Dapp)互动,该应用程序包含与用户钱包和属于平台的智能合约互动的代码。该通信流程中的步骤通常如下:
1. 打开Dapp
在大多数情况下,用户将导航其Web浏览器到托管Dapp的URL(例如Uniswap)。这将加载包含Dapp代码的网页。一旦加载,Dapp将尝试连接到用户的钱包。
2. 授权Dapp
加密钱包实施的一些保护措施包括在能够访问用户账户之前需要授权,以及请求签署交易。在EIP-1102之前情况并非如此。然而,实施这些功能有助于保持用户匿名、阻止Dapp垃圾邮件,并为用户提供管理受信任和不受信任Dapp域的方法。
如果所有先前步骤都成功完成,用户可以开始使用Dapp。
当用户决定执行操作(进行交易、购买NFT、质押代币等)时,用户的钱包将显示一个弹出窗口,询问用户是否确认该操作。交易参数由Dapp生成并转发给钱包。如果确认,交易将被签署并发布到区块链,等待确认。
除了最初连接到Dapp时的授权弹出窗口外,用户不会看到太多关于应用程序或平台的额外信息。这最终使用户负担验证Dapp的合法性和可信度,不幸的是,这需要一定程度的技术知识,通常超出大多数普通用户的能力范围。虽然进行自己的研究是Web3世界的常见 mantra,但一步失误可能导致重大资金损失。
既然如此,现在让我们再次绕道Web2世界,看看类似的互动是什么样子。
Web2世界如何处理类似情况?
与前面的例子一样,我们将看看当用户想要使用Web2应用程序时会发生什么。假设用户想要检查他们的电子邮件收件箱。他们将首先导航浏览器到电子邮件域(例如Gmail)。在后台,浏览器执行TLS握手,尝试与Gmail的服务器建立安全连接。这将使用户的浏览器和Gmail的服务器之间建立加密通道,消除任何窃听的可能性。如果握手成功,将建立加密连接并通过浏览器的UI传达给用户。
安全连接基于为用户尝试访问的域颁发的证书。证书包含用于建立加密连接的公共密钥。此外,证书必须由称为证书颁发机构(CA)的受信任第三方签名,赋予颁发的证书合法性并保证其属于被访问的域。
但是,如果不是这种情况会发生什么?当证书由于某种原因被浏览器拒绝时会发生什么?嗯,在这种情况下,会显示一个巨大的红色警告,向用户解释发生了什么。
当无法建立安全连接、主机的证书不受信任或证书过期时,将显示此类警告。浏览器还尝试以人类可读的方式显示尽可能多的有关错误的有用信息。此时,由用户选择是否信任该站点并希望继续与之互动。浏览器的任务是告知用户潜在问题。
可以做什么?
加密钱包应向用户显示尽可能多的关于正在执行的操作的信息。用户应看到有关他们正在互动的域/Dapp的信息。有关实际交易内容的详细信息,例如正在调用的函数及其参数,应以用户可读的方式显示。
比较前面的两个例子,我们可以注意到当今加密钱包中缺乏验证和显示的信息。这进而提出了一个问题:可以做什么?存在许多公开可用的项目健康和合法性指标。我们认为将这些传达给用户可能是解决这个问题的一个好步骤。让我们快速浏览一下。
智能合约所有权证明
证明一个域对其互动的智能合约拥有所有权非常重要。目前,这种机制似乎不存在。然而,我们认为我们有一个好的解决方案。类似于Apple执行商家域验证的方式,可以使用简单的JSON文件或dapp_file来验证所有权。该文件可以存储在Dapp域的根目录下,路径为.well-known/dapp_file。JSON文件可以包含以下信息:
- Dapp正在互动的智能合约地址
- 显示文件生成时间的时间戳
- 内容签名,验证文件的有效性
此时,读者可能会说:“这如何显示合约的所有权?”关键是签名。即,签名是通过使用部署合约的账户的私钥生成的。区块链的透明度可用于获取部署者地址,然后可用于验证签名(类似于以太坊智能合约在链上验证签名的方式)。
这种机制能够在智能合约和Dapp之间创建明确的关联。该关联以后可用于执行额外的验证。
域注册记录
当购买或注册新域时,会在公共注册机构中创建公共记录,表明该域由某人拥有且不再可供购买。域名由域名服务或DNS使用,将其(例如www.doyensec.com)转换为机器友好的IP地址(例如34.210.62.107)。
DNS记录的创建日期显示Dapp的域最初购买的时间。因此,如果用户尝试与一个早已建立的项目互动,并遇到一个声称是该项目但具有最近创建的域注册记录的域,这可能是潜在欺诈活动的信号。
TLS证书
TLS证书的创建和过期日期可以以类似于DNS记录的方式查看。然而,由于由Let’s Encrypt等服务颁发的证书持续时间短,Dapp的访问者很可能会看到相对较新的证书。
然而,TLS证书可以被视为验证正确网站设置的一种方式,其中所有者采取了额外步骤以允许用户与其应用程序之间的安全通信。
智能合约源代码验证状态
发布和验证的源代码允许对智能合约的功能进行审计,并可以快速识别恶意活动。
智能合约部署日期
智能合约的部署日期可以提供有关项目的额外信息。例如,如果攻击者设置了一个假的Uniswap网站,恶意智能合约最近部署的可能性很高。如果与一个早已建立的合法项目互动,这种差异应警告用户潜在的恶意活动。
智能合约互动
项目的可信度可以看作是与其项目智能合约互动次数的函数。一个健康的项目,拥有庞大的用户群,很可能具有大量与项目合约的独特互动。少量互动,无论是独特的与否,都表明相反的情况。虽然对于新项目来说是典型的,但它也可能是设置为冒充合法项目的智能合约的指标。此类智能合约将没有原始项目的大量用户群,因此与项目的互动次数将很低。
总体而言,长时间内与智能合约的大量独特互动可能是项目健康及其生态系统健康的有力指标。
我们的建议
虽然当钱包连接到未知域时实施了授权步骤,但我们认为有改进的空间。连接和交易签名过程可以进一步更新,以显示有关正在访问的域/Dapp的用户可读信息。
作为概念验证,我们实现了一个简单的Web服务https://github.com/doyensec/wallet-info。该服务利用公共信息,如域注册记录、TLS证书信息和通过Etherscan的API可用的数据。数据被检索、验证、解析并返回给调用者。
该服务提供对以下端点的访问:
/host?url=<url>/contract?address=<address>
这些端点返回的数据可以在用户互动的两个点集成到加密钱包中。
初始Dapp访问
当用户最初连接到Dapp时,可以使用/host端点。Dapp的URL应作为参数传递给端点。该服务将使用提供的URL收集有关网站及其配置的信息。此外,该服务将检查站点根目录上是否存在dapp_file并验证其签名。一旦处理完成,服务将响应:
|
|
这些信息可以显示给用户在对话框UI元素中,例如:
作为一个具体例子,让我们看看在撰写本文时活跃的这个假Uniswap网站。如果用户尝试将其钱包连接到在该站点上运行的Dapp,将向用户返回以下信息:
|
|
响应中缺失的信息反映了在该域上未找到dapp_file。这些信息随后将反映在UI上,通知用户Dapp的潜在问题:
此时,用户可以查看信息并决定是否愿意给予Dapp访问其钱包的权限。一旦Dapp被授权,这些信息就不需要再显示。不过,偶尔重新显示这些信息将是有益的,以便Dapp或其域的任何更改都能传达给用户。
进行交易
交易可以分为两组:转移原生代币的交易和智能合约函数调用的交易。根据正在执行的交易类型,可以使用/contract端点检索有关转移资产接收者的信息。
对于我们的情况,智能合约函数调用是更有趣的交易组。钱包可以检索有关将调用函数的智能合约的信息,以及代表接收者的函数参数。例如,approve(address spender, uint256 amount)函数调用中的spender参数。这些信息可以根据正在执行的函数调用逐个检索。
广泛使用的函数的签名是可用的,并且可以在钱包中实现为一种允许或安全列表。如果签名未知,应通知用户。
验证接收者使用户有信心他们正在将代币转移或允许访问其代币给已知的合法地址。
给定地址的示例响应将如下所示:
|
|
在后台,Web服务将收集有关地址类型(EOA或智能合约)、代码验证状态、地址互动信息等的信息。所有这些都应作为交易确认步骤的一部分显示给用户。
可以在此处提供指向智能合约和任何额外信息的链接,帮助用户执行额外的验证(如果他们愿意)。
对于原生代币转移,大部分验证包括输入有效的to地址。这不是一个适合自动验证的任务。对于这个用例,钱包提供了“地址簿”类似的功能,应利用该功能以最小化初始化交易时的任何用户错误。
结论
本文的重点是强调当今加密钱包实现的缺点,提出想法,并就如何改进它们提出建议。这个领域正在积极工作中。最近,MetaMask更新了他们的确认UI以显示额外信息,通知用户潜在的setApprovalForAll诈骗。这是朝着正确方向迈出的一步,但还有很长的路要走。可以在此基础上构建和增强这些功能,直到用户可以进行交易并高度确定他们不会犯错或被诈骗。
还有像WalletGuard和ZenGo这样的第三方团体已经实施了本文中描述的类似验证。这些功能应该是每个加密钱包的标准和必需,而不仅仅是需要安装的额外软件。
就像Web2的用户代理Web浏览器一样,Web3的用户代理应尽可能多地告知和保护其用户。
我们对wallet-info Web服务的实现只是如何将公共信息汇集在一起的一个例子。这些信息结合良好的UI/UX设计,将大大改善加密钱包的安全性,进而改善整个Web3生态系统的安全性。
Dapp验证是否完全解决了钓鱼/诈骗问题?不幸的是,答案是否定的。提议的更改可以帮助用户区分合法项目和潜在诈骗,并指导他们做出正确的决定。 dedicated的攻击者,如果有足够的时间和资金,将始终能够生成一个智能合约、Dapp或网站,使用上述指标看起来无害。这对于Web2和Web3世界都是如此。
最终,由用户决定是否愿意将其登录凭据交给网站,或将其加密钱包的访问权交给Dapp。所有软件能做的就是指引他们走向正确的方向。