Cobo 安全团队:区块链安全交易指南
作者:Cobo 安全团队
前言
随着比特币 ETF 的通过,区块链市场开始回暖。币价的回升让行业逐渐恢复了往日的繁荣。与此同时黑客活动也开始活跃起来。Cobo 安全团队观察到近一两个月钓鱼案件发生的频率也有所增加。
近期 Restaking, BTC L2 等新的应用热点开始涌现,链上交易逐渐成为 Web3 用户日常不可或缺的一部分,越来越多的用户资金也在往链上转移。
而与交易所等中心化应用不同,链上应用的账户安全需要通过用户自己保障。安全地进行区块链交易是 Web3 原住民最基本的能力。尽管很多基础设施如浏览器插件钱包,甚至浏览器本身都对针对钓鱼有一定的风险提醒,但用户因不安全交易导致资产损失的事件还是时有发生(如私钥泄露,签名钓鱼等)。
Cobo 安全团队通过整理链上交易过程中常见的风险点,编写了交易安全的执行准则,旨在让用户在交易过程中规避风险,保障资金安全,防范钓鱼攻击。
在开始介绍之前,Cobo 安全团队为大家总结了安全交易的核心准则,如下:
1、拒绝盲签,不理解的交易、消息不签名;
2、不厌其烦,反复验证。
如何进行安全交易
一个完整的 DApp 交易流程包含多个环节:钱包安装、访问 DApp 、连接钱包、消息签名、交易签名、交易后处理。其中每个环节都存在一定的安全风险,下面将依次介绍实际操作中的注意事项。
注:本文主要介绍以太坊及各 EVM 兼容链上的安全交互流程,其他非 EVM 链使用的工具和具体的技术细节可能不同。
钱包安装
目前 DApp 的主流使用方式是使用浏览器插件钱包进行交互。EVM 链使用的主流钱包有 Metamask 和 Rabby 等。
Cobo 安全团队在深度体验后,基于风险提示的角度,推荐使用 Rabby 插件钱包来作为主要的链上交互钱包。其原因在于:相较于 Metamask 钱包,Rabby 钱包提供交易数据解析、交易模拟执行、交易风险预警、授权查询和历史签名数据查询等功能,在针对钓鱼防范上会比 Metamask 钱包具有更大的优势。
安装 Chrome 插件钱包,需要确认从 Chrome 应用商店中下载安装,不要从第三方网站安装钱包,避免安装有后门的钱包软件。
有条件的用户建议联合使用硬件钱包,在私钥保管上可以更大程度地提高整体的安全性。
访问 DApp
网页钓鱼是 Web3 攻击中的常见攻击手法,典型案例是以空投名义诱导用户访问钓鱼 DApp 应用,在用户连接钱包后诱导用户签署代币授权、转账交易或代币授权签名,导致用户资产遭受损失。
因此在访问 DApp 时,用户需要保持警惕,避免进入网页钓鱼的陷阱。
在访问 DApp 前应该确认 DApp 网址的正确性。建议:
-
尽量不要从 Google 搜索关键字第一名直接进行访问,钓鱼攻击者可通过购买广告位使自己的钓鱼网站搜索排名置顶,因此第一名不一定是官方网站。
-
避免直接点击 x.com 及各类社交软件中其他用户的评论、消息中发布的网址,这类网址很可能是钓鱼链接。
-
反复确认 DApp 网址正确性后进行访问,可根据 DefiLlama 等 DApp 市场、项目方官方 X 账号、Google 搜索结果多方校对。
-
确认安全的网站添加过浏览器收藏夹中,后续直接从收藏夹中访问。
在已经打开 DApp 网页之后,也需要对地址栏进行安全检查:
-
检查域名、网址。通常 DApp 会使用比较简洁的域名和网址。如 https://app.uniswap.org/;如果遇到特别长的域名,形如 https://zk-polyhedra.network-8jb.xyz/或与知名网站名称类似的域名,如 https://pufffer.fi(注意多了一个 f),则很可能是登入的钓鱼网站,应立刻退出。识别域名时也要特别注意 1il, oO0 等各类形近字符的情况。
-
检查浏览器 https 链接情况。目前主流 DApp 均使用 https 链接,浏览器应该显示🔒状标志。如果不是 https 链接或浏览器提示证书异常的情况,则访问的可能不是官方网站或遭遇了劫持攻击,应该立刻停止访问。
目前市面上主流浏览器插件钱包都已经集成了一定的风险提示功能,如 Metamask/Phantom 等。在访问一些位于黑名单中的风险网址时,浏览器插件钱包甚至 Chrome 浏览器本身都可能会展示强安全提示(见下图)。
进入 DApp 后,可能会自动或在主动点击 Connect 后触发连接钱包的操作。插件钱包会针对当前 DApp 的进行一些检查、信息展示等。
以下是 Rabby 钱包给出的网页审查信息,可用来辅助进行 DApp 真实性的判断。
在连接钱包后,通常在用户没有其他操作时,DApp 不会主动唤起插件钱包。如果网站在登入后 DApp 频繁唤起钱包要求签名消息、签署交易,甚至在拒绝签名后仍会不断弹出签名的情况,那么也很可能是钓鱼网站的情况,需要谨慎处理。
消息签名
在极端情况下,比方说攻击者攻击了协议的官方网站或通过前端劫持等攻击,对页面内容进行了替换。普通用户很难在这种场景下对网站安全性进行甄别。
此时插件钱包的签名是用户保存自身资产的最终屏障。只要拒绝掉恶意签名,就能保障自身资产不受损失。用户在签名任何消息和交易时都应该仔细审查签名内容,拒绝盲签。
从技术上讲,目前以太坊中常见的签名类型有三类:
-
哈希签名 eth_sign:针对某个数据的原始 hash 进行签名。hash 的原始数据可能是消息甚至以太坊交易。
-
消息签名 personal_sign:针对数据明文进行签名,在用户登录验证或许可协议确认时最为常见。
-
结构化数据签名 eth_signTypedData(EIP-712):针对 DeFi 协议中使用的数据对象的签名,常见的如 ERC20 Permit 授权签名、NFT 挂单签名等。
针对消息签名的风险判别,用户可遵循以下准则:
-
自然语言签名通常可以放行。这类签名通常 personal_sign,用于登录确认或者确认产品须知,为大段的自然语言描述(而非数字、十六制等形式)。此类消息因为包括自然语言,字符串比较复杂,智能合约处理比较困难,因此通常不会用于链上鉴权,只是网站用于确认地址身份。因此相对风险较低。
-
禁止直接签名 16 进制原始 hash。这类签名通常是 eth_sign 签名,这类签名最为危险,因为用户无法判断 hash 原本的数据内容是什么。因此大部分钱包已经禁用了针对原始哈希(16 进制数据)签名的功能。Metamask 钱包,可在 设置 ->高级 -> Eth_sign 请求 选项卡中确认其配置为关闭状态。Rabby 钱包,相关配置默认禁用的,无需额外配置。
-
结构化数据签名仔细检查签名内容。如 ERC20 Permit 授权签名则要检查其中 spender 地址是否符合预期,如为 EOA 地址则很可能是点击了钓鱼签名,应该立即拒绝。
针对消息签名,这里需要额外注意的是,尽管在浏览器插件钱包中 eth_sign 操作是默认禁止的,但钱包仍可通过 personal_sign 对 hash 类的数据进行签名。这类签名不会导致 permit 授权或发起交易。但个别协议(如一些 AA 钱包)仍可能使用 personal_sign 签名进行鉴权。为避免损失原则上还是不对 16 进制数据进行签名。这类签名效果如下:
签名交易要遵循不盲签的原则。目前许多插件钱包会针对待签名消息进行解码并展示相关内容,如下是 Rabby 钱包对一笔 DEX 交易的解析示例:
其中用户可以查看交易的目标地址的一些相关信息,如是否为 EOA地址、地址余额以及合约部署时间等。用户可以根据这些信息对要签署的交易进行风险判断。例如如果交互的地址为 EOA 地址,或交互的合约部署时间小于 7 天,则可以认为该操作具有较大风险,应充分调查后再进行操作。
对于开源协议,主流的浏览器插件钱包已经支持对交易数据的解析,通过查看 ABI 解码后的交易内容,可以更加清楚地了解当前在进行什么操作。合约调用的函数名可以提供一些其功能的参考:如 approve、swap、transfer、deposit 和 withdraw 等。
Rabby,imToken 钱包还集成了模拟执行功能,用户在交易确认前可以直接看到交易执行结果,通过交易模拟执行,用户可以查看到当前交易会导致的各种资金转移情况。用户应该仔细检查,对于不符合预期执行结果拒绝签名。
对于有一定技术储备的用户,在自动化工具无法顺利解析交易的情况,也可使用一些常见的人工检查方法:
-
通过复制交互目标合约地址到区块链浏览器如 etherscan 中进行审查,审查内容主要包括合约是否开源,近期是否存在大量交易和 Etherscan 是否为该地址打上官方标签或恶意标签。
-
在遇到插件钱包无法识别的交易,可以通过手动复制原始交易数据(raw_data,通过 16进制数据展示)中的前8位数字到 https://openchain.xyz/signatures 进行查询,得到原始的函数名称,以大概确定交易的行为。
-
使用 Phalcon, Tenderly 和 Dedaub 等交易模拟工具进行模拟执行,查看交易具体执行细节。
交易后处理
在躲过了钓鱼网页和恶意签名后并不意味着万事大吉,交易后也仍需进行风险管理。
交易后应及时查看交易的上链情况,确认其与签名时预期的状态是否一致。如果发现异常及时进行资产转移、授权解除等止损操作。
ERC20 Approval 授权管理也十分重要。有些案例中用户对某些合约进行了代币授权后,多年后这些合约遭受攻击,攻击者利用了被攻击合约的代币授权额度来窃取用户资金。
为避免此类情况 Cobo 安全团队建议用户遵循以下标准来进行风险防范:
-
最小化授权。当进行代币授权时,应根据交易的需求有限量的授权相应的代币数量。如某次交易需要授权 100 USDT,则本次授权数量即限制为 100 USDT,而不要使用默认的无限授权。
-
及时撤销不需要的代币授权。通过 Rabby 钱包的 Approval 功能或者登录 revoke.cash 查询对应的地址的授权情况,撤销较长时间没有交互的协议的授权,防止协议后续存在漏洞导致利用用户的授权额度造成资产损失。
其他技巧
除了上述交易流程中的风险外,合理利用通过某些工具中集成的功能也可以规避一些风险。
-
某些钱包内置钱包导入功能(如 Rabby)。可以通过导入其他移动端钱包的地址,在进行交易时可以进行强制的二次确认(需要唤醒钱包、扫码和输入密码确认)来减缓钓鱼风险。同时享有移动端钱包的交易安全检查(白名单、模拟执行和钓鱼提示等)
-
某些钱包支持导入的观察者钱包(如 Rabby,OneKey,TokenPocket,imToken 等),通过观察者钱包进入一些陌生的网站。仍会正常唤起消息签名或发起交易的页面,此时可仔细查看待签名内容。同时因为没有私钥,不必担心误操作确认的情况。
-
通过 Rabby 钱包的 Approvals 功能查询地址的授权情况,及时撤销高危授权。Tips: Rabby 在该功能中使用了多个维度(历史授权链接总金额/24h 取消授权数量/授权时间/授权资产数量)来对授权风险进行评判,可以更有效帮助用户识别授权风险。
-
误操作签名后,通过 Rabby 钱包的 Signature Record 功能及时检查自己签名过的交易和文本数据,及时排查授权风险。
在具备了风险意识和做了充足的风险防范的情况下,也仍要进行有效的资金隔离,在极端情况下降低资金的受损程度。Cobo 安全团队推荐大家使用以下方案来进行资金存放:
-
使用 Gnosis Safe 多签钱包或冷钱包存放大资金;
-
使用浏览器钱包生成的地址或者其他 EOA 钱包存放小资金用户交互,并定期更换热钱包地址。
如果不小心真的发生被钓鱼的情况,可以立即执行以下操作来降低损失:
-
Revoke.cash 及时取消授权;
-
如果签名了钓鱼 permit 消息且资金未被转走,则立刻签名新的消息并发起 permit 调用使钓鱼消息 nonce 失效;
-
必要时转移账号资金。
如何安全领取空投
发放空投是目前项目方用于吸引用户的常见方式,同时也是用户被钓鱼攻击的重灾区。为此,基于上文的安全交易准则,Cobo 安全团队为大家整理了一套用于领取链上空投的安全交互流程:
-
先使用 Rabby 观察者钱包测试一遍交互流程,确认无代币授权、代币转账类交易。
-
领取空投过程中不进行 Permit 类消息签名。不进行 Approve 合约调用。
-
尽量使用「小号」领取空投。
-
领空投交易查看模拟执行结果,确认无代币转出。
插件工具选取
区块链安全守则的内容很多,有可能不是每次交互都能做到细致的检查,那么是否存在一种好用的浏览器插件来辅助我们做出风险判断呢?
Cobo 安全团队体验了市面上较为主流的交易风险检查插件,并从「钓鱼网页拦截」、「恶意授权地址检查」和「是否开源」三个维度整理成表格,大家可以根据自身情况选择使用,如下: