链下签名也能钓走你的 Token?—— Permit 签名分析
By:Lisa
背景
5 月 11 日,推特用户 "pineapple.eth" 发推表示自己因误点钓鱼网站(syncswap[.]network)致钱包被盗,损失超 100 美元。
(https://twitter.com/0xBigPineapple/status/1656420711919960065)
虽然损失数额不算大,但这里面藏着巨大的安全风险,受害者往往会因为 “看不见” 这 “不起眼” 的签名风险损失巨大资产。这也是我们写这篇文章的原因。
根据受害者的描述,被盗交易如下:
(https://etherscan.io/tx/0xc65093b52fcf395f23fb7195a6fd5758b9a3eb1ccd0e3572754690d3a2a2c27c)
从这两笔交易来看,合约调用者(0x00002…d0000)通过调用 TransferFrom 函数,将受害者地址(0xA4089…82C3)上的 34.87 USDC 转移到(0x8256…D6B8),将 81.36 USDC 转移到(0x5A69…1C17)。如果光看 transferFrom 函数,不难发现这个函数的作用是:允许第三方发起一笔交易,将相关数字资产从所有者账户转移到接收者账户。
接着分析合约调用者地址(0x00002…d0000),发现多了一笔 permit 操作,而这在受害者的交易记录中是没有的。那 permit 有什么作用呢?
(https://etherscan.io/tx/0x7c06a33bd6bb913fb64e56e8a1381e1957d85cae78ca3305bdfa9561fc7bc611)
Permit 是什么?
据官方介绍,permit 在 EIP-2612 被引入到 ERC20 的协议中,用户不用事先授权,就能通过附加一个授权签名(permit)与应用合约交互。具体来说,我们都知道在 ERC20 币种的交易中,A 可以调用 approve 函数来对 B 进行授权,即将 A 指定的代币授权给另一个账户操作,并且必须是这个账户的 owner 才可以调用 approve 函数。而 permit 函数的作用是,A 提前在链下对授权对象进行签名,得到的签名告知给 B,B 就可以拿着这个签名去调用 permit 来实现 A 的授权操作(获得 allowance 使用 transferFrom 来进行转账),A 在不发送交易的情况下就能对指定代币进行转账,并且无论是不是这个账户的 owner 都可以执行 permit 进行授权操作。另外,Uniswap 已发布了新的 Token 授权标准 Permit2。
以下是 approve 和 permit 的对比:
function approve(address usr, uint wad) external returns (bool)
{
allowance[msg.sender][usr] = wad;
…
}
function permit(
address holder, address spender,
uint256 nonce, uint256 expiry, bool allowed,
uint8 v, bytes32 r, bytes32 s
) external {
…
allowance[holder][spender] = wad;
…
}
了解了基础知识,再回到钓鱼事件本身,可以发下此 permit 函数有 7 个参数:
owner:被授权的地址
spender:授权给谁
value:授权给定的代币的数量
deadline:是一个时间戳,仅在给定的时间之前有效
v, r, s:签名数据
其中 deadline 为 1714509304969,value 为 116239404,也就是说授权在 56300 年 8 月 22 日 0 点 42 分(GMT)前都有效,几乎是无限期了。且这笔授权的代币数量为 116.239404 USDC,与受害者被盗的数额相同。v, r, s 值即为用户(owner)在钓鱼网站进行签名后的签名数据,permit 函数会验证签名数据的有效性。签名验证通过后就会将用户的代币授权给黑客(spender)。
整个过程很清晰了:受害者签名后传给了钓鱼网站但不上链,黑客拿到这个签名信息后上链提交 permit,也就是调用了 approve 进行了授权。签名是在链下进行的,无需花费任何 gas。不过需要明确的是,这里的无 gas 不是没有 gas 消耗,而是签名方(受害者)不需要为授权和转账来支付 gas。
毫无疑问,与 approve 授权钓鱼类似,permit 比 approve 授权钓鱼更加危险,毕竟只要窃取到了签名就获得了授权。例如 dex 里的挂单功能,只需要用户对某个消息进行签名,用户就可以在不支付 gas 的情况下将资产委托给 dex 处理,但如果这个 dex 是个钓鱼网站,伪造了恶意消息让用户签名,用户的资产就有可能丢失。据我们了解,一些钱包会对 approve 授权钓鱼的签名信息进行解码展示,但钱包对 permit 签名钓鱼的警告几乎没有,用户遭受攻击的风险更高。同时,permit 签名作为链下行为,用户也很难注意到自己的签名是否已经泄露。
MistTrack
目前黑客地址已经被 MistTrack 标记为恶意钓鱼地址。
地址 1:0x00002644e79602F056B03235106A9963826d0000
地址 2:0x82563Ba592986Cb277d67B2E7c56ab3BB3FDD6B8
地址 3:0x5A697967F0791d12db8A0f92344Abc6DD07a1C17
受害者的两笔 USDC 均被换成 ETH。
使用 MistTrack 对 ETH, WBTC, USDT, USDC, SHIB, DAI, WETH, DAI, stETH, APE 币种进行分析,目前地址 1 获利约 12 万美元,地址 2 获利约 20 万美元,地址 3 获利约 2,000 美元。此外,据 Web3 反诈骗平台 Scam Sniffer 的分析,截止 5 月 9 日,一共有 300 多名受害者被基于 Permit2 的恶意签名盗取了约 69 万美金的资产,从 Uniswap 推出 Permit2 到 5 月 9 日 为止,以太坊主网上已经有近 67 万个地址授权过 Permit2 了。当然,这个数据针对这个团伙的全貌来说只是冰山一角,本文重点不在此,故不再深究。
总结
本文主要以一个实际被盗案例入手,介绍了 permit 签名的风险。慢雾安全团队提醒请勿随意打开来历不明的网站进行操作,在与 DApp 交互时注意控制授权给合约的 Token 数量并认真检查签名内容,不定期使用授权工具如 RevokeCash(https://revoke.cash)查看是否有异常授权,也可以使用针对 Uniswap Permit2 的授权管理工具(https://app.scamsniffer.io/permit2)进行查看,若有异常授权,请及时取消授权。更多的安全知识建议阅读慢雾出品的《区块链黑暗森林自救手册》:https://github.com/slowmist/Blockchain-dark-forest-selfguard-handbook/blob/main/README_CN.md
参考链接:
https://eips.ethereum.org/EIPS/eip-2612
往期回顾
慢雾导航
慢雾科技官网
https://www.slowmist.com/
慢雾区官网
https://slowmist.io/
慢雾 GitHub
https://github.com/slowmist
Telegram
https://t.me/slowmistteam
https://twitter.com/@slowmist_team
Medium
https://medium.com/@slowmist
知识星球
https://t.zsxq.com/Q3zNvvF