警惕!恶意攻击者滥用ERC20授权窃取你的代币

本文详细分析了恶意攻击者如何利用ERC20标准的approve()函数漏洞窃取用户代币,揭示了针对Chainlink持有者的钓鱼攻击手法,并提供了具体的智能合约代码分析和安全防护建议。

恶意攻击者滥用ERC20授权窃取你的代币!

概述

以太坊上的许多代币都使用ERC/EIP20标准。这是一个代币合约的标准接口,详细说明了合约属性、函数、函数参数和函数返回类型。

其中一个标准函数是function approve(address _spender, uint256 _value) public returns (bool success)。这允许第三方代表你从你的账户发送代币。如果你曾经通过AMM(如Uniswap)进行过交换,你就会认识这种模式,因为在交换之前,你必须批准AMM花费你的代币。

恶意攻击者已经学会了如何利用这个函数,因为对于那些毫无戒备的用户来说,当他们只期望遇到直接索要私钥的骗局(就像通常那样)时,这种攻击更难避免。利用代币授权是一种聪明的方法,因为用户通常认为:“如果他们没有我的密钥,他们就无法签署交易,所以他们无法窃取我的资产。“虽然这通常是准确的,但当我们谈论ERC20代币(和其他代币标准)时,情况并非如此。

目前,至少在我的雷达上,有一个针对Chainlink代币持有者的骗局活动(Chainlink的市值为110亿美元,拥有约45万持有者)。这个骗局活动的渠道是一个邮件列表——检查你的收件箱中是否有来自communitychainlink@substack.com的邮件,删除并取消订阅(保持警惕,因为他们可能会转售这个邮件列表或再次使用它)。

这个恶意活动详细描述了一个虚假的代币升级,承诺减少68%的gas费用,支持元交易,并允许你参与未来的投票。

减少gas费用的承诺旨在让用户产生FOMO心理,让他们不假思索地尽快"升级”——这是利用了当前以太坊网络上高gas费用和人们希望减少交易费用的心理。

攻击手法

骗局电子邮件活动详细说明了如何升级,恶意攻击者在链上发布了一个经过验证的合约,使其看起来更合法。然而,如果用户阅读合约,他们就会理解代币授权调用是如何被滥用来窃取他们的代币的。

该指南是通用的、冗长的,并包含了如何使用流行UI(如MyCrypto和MyEtherWallet)执行此升级的截图。当提示用户为其合约地址设置1,000,000,000个代币的approve()时,骗局就达到了最终形式。这意味着恶意攻击者将有权从批准该授权的账户中提取最多1,000,000,000个Chainlink代币(或任何被针对的协议代币)。

他们希望用户批准的支出者是一个智能合约(0x7AE7D6E2E61FBF0BE780DD19B6A01F5D44BEDE89),这是一个中继,允许合约所有者(0x71899b741e2316b756ad98cdf425d84f996017a0)在Chainlink代币智能合约上调用transferFrom(),使他们能够"清空"用户的账户余额。

在撰写本文时,已有4个独立地址签署了approve()交易:

  • 0x2a5c6607ef091f96ee1fca635db56eff18ad1fc8
  • 0x7923338eb2c6b8b43407f8fd3fd75826c1c64c8c
  • 0xc744a98c2e745c5da9338f9a82fdedbf6778a96d
  • 0xf7db1796ee8603f3a5de43793581e038027fb9fb

一旦恶意攻击者从用户授权中获得足够高的Chainlink资金额度,他们将在其合约地址上调用transferFrom(),并将代币从毫无戒备的用户账户转移到他们控制的地址。

智能合约分析

以下是以太坊主网上的已验证智能合约代码。值得注意的是,这个合约LessGasProxy是代币无关的,所以这个活动可能针对其他代币社区。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
pragma solidity 0.6.12;

interface IERC20Token {
    function allowance(address _owner, address _spender) external view returns (uint256);
    function transferFrom(address _from, address _to, uint256 _value) external returns (bool);
}

contract LessGasProxy {
    address public owner;
    
    constructor() public {
        owner = msg.sender;
    }
    
    function transferFrom(IERC20Token _token, address _sender, address _receiver) external returns (bool) {
        require(msg.sender == owner, "access denied");
        uint256 amount = _token.allowance(_sender, address(this));
        return _token.transferFrom(_sender, _receiver, amount);
    }
    
    function transferGas(IERC20Token _token, address _sender, address _receiver, uint256 _amount) external returns (bool) {
        require(msg.sender == owner, "access denied");
        return _token.transferFrom(_sender, _receiver, _amount);
    }
}

可以清空用户代币的恶意攻击者EOA(外部拥有账户)(0x71899b741e2316b756ad98cdf425d84f996017a0)仅从另一个账户(0xe7f7d950e32b98a619439abd6f2e6463f3a2d908)获得过一次资金。

到目前为止,恶意攻击者已经转移了266个LINK代币(价值7,700美元)。然而,他们发送代币的地址当前余额为1,111.48653745个LINK代币(价值约32,000美元),因此同一恶意攻击者可能进行了多个活动。

安全建议

如果你或你认识的人可能在任何产品上批准了不必要的代币数量,请立即使用https://revoke.cash进行修复。

如果你不确定是否给予了不必要的授权,无论如何都要进行自我审计。

如何保持安全?

  1. 确保你信任被授权花费你代币的对象,并理解在代币合约上调用approve()的后果!
  2. 审计谁拥有你的代币花费控制权,如果你不再信任/使用该支出者,请撤销此控制(使用https://revoke.cash/等工具,但即将在MyCrypto中推出)。
  3. 如果你是已经给予恶意攻击者花费权限的四个地址中任何一个的关键持有者,作为优先任务,你需要通过调用带有0个代币的approve()立即撤销花费权限。
  4. 确保你只从维护代币合约代码的官方来源获取更新——包括将你的电子邮件添加到受信任的邮件列表!
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计