智能合约安全分析,针对 ERC777 任意调用合约 Hook 攻击

news2024/11/27 12:40:53

智能合约安全分析,针对 ERC777 任意调用合约 Hook 攻击

Safful发现了一个有趣的错误,有可能成为一些 DeFi 项目的攻击媒介。这个错误尤其与著名的 ERC777 代币标准有关。此外,它不仅仅是众所周知的黑客中常见的简单的重入问题。

这篇文章对 ERC777 进行了全面的解释,涵盖了所有必要的细节。深入研究 ERC777 代币的具体细节的资源很少,这篇文章对于有兴趣深入了解 ERC777 代币的人来说是一个有价值的详细指南。
在文章的最后部分,将解释我们最近的发现。

简短描述攻击载体

这个漏洞利用了 ERC777 的特性,能够设置一个 Hook 接收函数。通过利用在目标合约中进行任意调用的能力,恶意调用者可以调用 ERC777 注册表合约,并为目标合约分配一个特定的 Hook 地址。因此,只要目标合约在未来收到 ERC777 代币,攻击者的 Hook 合约就会被触发。这个 Hook 可以以各种方式加以利用:要么用于重入攻击以窃取代币,要么只是回退交易,从而阻止目标合约发送或接收 ERC777 代币。

ERC777 和它的 Hook

什么是 ERC777

ERC777 是带有转账 Hook 的代币标准之一。
这里是 EIP 描述:https://eips.ethereum.org/EIPS/eip-777 , 这里是一篇 ERC777 实践。
实现 ERC777 代币的主要动机在于希望能够模仿原生代币转账的行为。通过在代币接收时触发智能合约,开发人员可以执行特定的逻辑,以增强功能并创建更多动态的代币交互。
然而,这些在转账过程中的额外调用使 ERC777 与 ERC20 代币不同。这些 Hook 引入了一个新的攻击载体,可能会影响到那些没有设计时考虑到在代币转账过程中处理额外调用的智能合约。这种出乎意料的行为会给这些合约带来安全风险。
以下是以太坊主网上一些具有一定流动性的 ERC777 代币的列表:
VRA:https://etherscan.io/address/0xf411903cbc70a74d22900a5de66a2dda66507255
AMP:https://etherscan.io/address/0xff20817765cb7f73d4bde2e66e067e58d11095c2
LUKSO:https://etherscan.io/address/0xa8b919680258d369114910511cc87595aec0be6d
SKL:https://etherscan.io/address/0x00c83aecc790e8a4453e5dd3b0b4b3680501a7a7
imBTC:https://etherscan.io/address/0x3212b29e33587a00fb1c83346f5dbfa69a458923
CWEB:https://etherscan.io/address/0x505b5eda5e25a67e1c24a2bf1a527ed9eb88bf04
FLUX:https://etherscan.io/address/0x469eda64aed3a3ad6f868c44564291aa415cb1d9

当 Hook 发生时

ERC20 代币只是在转账过程中更新余额。但 ERC777 代币是这样做的:

  1. 对代币发起者的地址进行 Hook 调用
  2. 更新余额
  3. 对代币接收方地址进行 Hook 调用

这在 VRA 代币中得到了很好的说明:

源码: https://etherscan.io/address/0xf411903cbc70a74d22900a5de66a2dda66507255
现在,让我们检查一下这些调用的代码:

正如你所看到的:

  1. 这个函数从_ERC1820_REGISTRY 中读取称为 implementer(实现者)的合约
  2. 如果该函数找到了一个实现者,那么这个实现者就会被调用。

让我们研究一下这个注册表,看看什么是实现者。

注册表和实现者

所有 ERC777 代币都与注册表(Registry)的合约有关:https://etherscan.io/address/0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24。
这个地址被 ERC777 代币用来存储设定的 Hook 接收者。这些 Hook 接收者被称为 “接口实现者”。
这意味着 Alice 可以选择 Bob 作为她的接口实现者。如果 Alice 接收或发送 ERC777 代币,Bob 将收到 Hook。
Alice 可以管理不同的 Hook 类型。因此,当 Alice 发送代币时,她可以选择 Bob 作为接口实现者,而只有当 Alice 收到代币时,她选择 Tom 作为实现者。
在大多数情况下,她也可以为不同的代币选择不同的接口实现者。
这些偏好设置被存储在这个映射的注册表中:

_interfaceHash 是 Alice 为一个事件选择接口实现者的标识。
而任何人都可以用这个函数读取 Alice 的接口实现者:

正如你所看到的,这就是我们之前在 VRA 代码中遇到的函数。
变量_TOKENS_SENDER_INTERFACE_HASH 被用作_interfaceHash,它可以是任何字节。但是 VRA 代币使用这些字节来识别这种类型的 Hook:

接收 Hook

设置一个 Hook 接收函数,Alice 只需在注册表上调用这个函数并输入 Bob 的地址作为_implementer 参数。

她还必须指定一个_interfaceHash。她会从 VRA 代币代码中获取这个_TOKENS_SENDER_INTERFACE_HASH。
还有一个重要的细节。
在为上面的 VRA 设置实现者后,Alice 也将会意识到,即使其他 ERC777 代币被转账,Bob 也会收到调用。
比如 imBTC, imBTC 在发送的代币上有相同的_interfaceHash。
这是由于所有 ERC777 代币共享相同的注册表合约来存储 Hook 的偏好设置。但这取决于 ERC777 代币为他们的 Hook 指定名称,虽然有时它们是相似的,但并不总是如此。

如何找到 ERC777 代币

调用注册表是所有 ERC777 都具有的特征。
因此,我们可以尝试dune.com来调用所有调用注册表的智能合约。

我们可以使用这个 SQL 脚本。事实上,我们应该另外过滤出代币地址,但至少我们有一个完美的开始,结果有 78 个地址。
译者备注:dune traces 表 会记录交易内部调用记录。

这个注册表是唯一可能的吗?

理论上,没有人能够保证某些代币恰好使用这个 0x1820 合约作为注册表。
但我们可以用dune.com来检查。

它返回这些地址

0x1820a4b7618bde71dce8cdc73aab6c95905fad24
0xc0ce3461c92d95b4e1d3abeb5c9d378b1e418030
0x820c4597fc3e4193282576750ea4fcfe34ddf0a7

我们检查过,0x1820 是唯一拥有有价值的 ERC777 代币的注册表。其他注册表的代币并不那么有价值。

可 Hook 代币的普遍情况

ERC777 不仅是一个带有 Hook 的标准。还有 ERC223、ERC995 或 ERC667。
它们并不那么稀奇。你一定听说过实现 ERC667 的LINK 代币。

使用任意调用的攻击载体

这是最近为Safful的客户发现的攻击载体。
研究人员通常认为 ERC777 代币会对调用发起者和接收者进行调用。但实际上,发起者和接收者可选择任意 “Bob” 作为 Hook 接收者。
因此,想象一下结合那些具有任何数据对任何地址进行任意调用的合约会发生什么?
就有任意调用功能的可以广泛存在于 DEX 聚合器、钱包、multicall 合约中。
译者注:任意调用功能是指在合约中存在类似这样的函数:
function execute(address target, uint value, string memory signature, bytes memory data, uint eta) public payable;
它可以调用任何的其他的方法。
攻击方法:

  1. 攻击者找到一个允许任意调用的函数的目标合约(Target)
  2. 攻击者在目标(Target)上调用:
  3. registy1820.setInterfaceImplementer(Target, hookHash, Attacker)
  4. 现在,我们的 Attacker 是 Target 的实现者
  5. Attacker 会随着 ERC777 代币中使用的 hookHash 而被调用。
  6. 每当目标合约(Target)收到 ERC777 代币时,Attacker 就会收到一个 Hook 调用。
  7. 下面的攻击,取决于 Target 代码 而不同:
    • Attacker 可以在一些用户执行目标合约中的函数时进行重入
    • Attacker 可以直接回退,这样用户的交易就直接被还原了

如果 DEX 聚合器计算最佳兑换路径是通过某个有 ERC777 代币的 DEX 交易对时,那么可能会遇到问题。

保护

经过与客户数小时的讨论,我们找到了一个不会破坏任意调用的解决方案。
项目方最好限制使用 Registry1820 作为任意调用的地址。因此,没有攻击者能够利用任意调用来设置接口实现者。

经验之谈

项目和审计人员必须注意到 ERC777 中描述的 Hook 行为。这些代币不仅对接收者和发起者进行调用,也对其他一些 Hook 接收者进行调用。
在这个意义上,允许任意调用的项目必须特别注意,并考虑 ERC777 的另一个攻击载体。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/968837.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数学建模--粒子群算法(PSO)的Python实现

目录 1.开篇提示 2.算法流程简介 3.算法核心代码 4.算法效果展示 1.开篇提示 """ 开篇提示: 这篇文章是一篇学习文章,思路和参考来自:https://blog.csdn.net/weixin_42051846/article/details/128673427?utm_mediumdistribute.pc_relevant.none-task-blog-…

Android 12 源码分析 —— 应用层 四(SystemUI的基本布局设计及其基本概念)

Android 12 源码分析 —— 应用层 四(SystemUI的基本布局设计及其基本概念) 在上两篇文章中,我们介绍SystemUI的启动过程,以及基本的组件依赖关系。基本的依赖关系请读者一定要掌握,因为后面的文章,将会时…

数学建模--主成分分析法(PCA)的Python实现(

目录 1.算法核心思想: 2.算法核心代码: 3.算法分类效果: 1.算法核心思想: 1.设置降维后主成分的数目为2 2.进行数据降维 3.设置main_factors1个划分类型 4.根据组分中的值进行分类 5.绘制出对应的图像 2.算法核心代码&#xff1a…

使用多线程std::thread发挥多核计算优势(解答)

使用多线程std::thread发挥多核计算优势(题目) 单核无能为力 如果我们的电脑只有一个核,那么我们没有什么更好的办法可以让我们的程序更快。 因为这个作业限制了你修改算法函数。你唯一能做的就是利用你电脑的多核。 使用多线程 由于我们…

C语言练习8(巩固提升)

C语言练习8 编程题 前言 奋斗是曲折的,“为有牺牲多壮志,敢教日月换新天”,要奋斗就会有牺牲,我们要始终发扬大无畏精神和无私奉献精神。奋斗者是精神最为富足的人,也是最懂得幸福、最享受幸福的人。正如马克思所讲&am…

无涯教程-JavaScript - CUBESETCOUNT函数

描述 CUBESETCOUNT函数返回集合中的项目数。 语法 CUBESETCOUNT (set)争论 Argument描述Required/Optionalset Microsoft Excel表达式的文本字符串,其输出为由CUBESET函数定义的集合。 OR CUBESET功能。 OR 对包含CUBESET函数的单元格的引用。 Required Notes 求值CUBESE…

【个人博客系统网站】统一处理 · 拦截器

【JavaEE】进阶 个人博客系统(2) 文章目录 【JavaEE】进阶 个人博客系统(2)1. 统一返回格式处理1.1 统一返回类common.CommonResult1.2 统一返回处理器component.ResponseAdvice 2. 统一异常处理3. 拦截器实现3.1 全局变量SESSI…

Mariadb高可用(四十)

目录 一、概述 (一)概念 (二)组成 (三)特点 (四)工作原理 二、实验要求 三、构建MHA (一)ssh免密登录 (二)安装mariadb数据库…

数学建模--一维插值法的多种插值方式的Python实现

目录 1.算法流程步骤 2.算法核心代码 3.算法效果展示 1.算法流程步骤 #算法的核心就是利用scipy中的interpolate来完成工作 #一共是5种一维插值算法形式: #插值方法:1.阶梯插值 2.线性插值 3.2阶样条插值 4.3阶样条插值 #"nearest"阶梯插值 #"zero&…

硬盘数据恢复的基础操作方法分享

确定硬盘故障类型:在进行硬盘数据恢复之前,首先需要确定故障类型是硬件故障还是软件故障。如果是软件故障,可以尝试使用数据恢复软件进行恢复;如果是硬件故障,则需要求助专业数据恢复公司进行处理。 使用数据恢复软件…

JavaScript基础05——字面量、变量介绍及变量基本使用

哈喽,大家好,我是雷工! 说起变量感觉很熟悉,但要让解释什么是变量时,却有点语塞,就像解释下为啥112一样,感觉非常熟悉,就是知道,但确解释不出来。 不过虽然在其他场景比较…

机器学习——线性回归/岭回归

0、前言: 线性回归会用到python第三方库:sklearn.linear_model中的LinearRegression导入第三方库的方法:from sklearn.linear_model import LinearRegression使用LinearRegression(二维数据,一维数据)进行预测,其中数…

MySQL中的索引事务(2)事务----》数据库运行的原理知识+面试题~

本篇文章建议读者结合:MySQL中的索引事务(1)索引----》数据库运行的原理知识面试题~_念君思宁的博客-CSDN博客此时,如果你根据name来查询,查到叶子节点得到的只是主键id,还需要通过主键id去主键的B树里面在…

源码角度看待线程池的执行流程

文章目录 前言一、线程池的相关接口和实现类1.Executor接口2.ExecutorService接口3.AbstractExecutorService接口4.ThreadPoolExecutor 实现类 二、ThreadPoolExecutor源码解析1.Worker内部类2.execute()方法3.addWorker()方法 总结 前言 线程池内部维护了若干个线程&#xff…

RT-Thread 内核移植

内核移植 内核移植就是将RTT内核在不同的芯片架构、不同的板卡上运行起来,能够具备线程管理和调度,内存管理,线程间同步等功能。 移植可分为CPU架构移植和BSP(Board support package,板级支持包)移植两部…

1783_CMD启动MATLAB同时执行一个脚本

全部学习汇总: GitHub - GreyZhang/g_matlab: MATLAB once used to be my daily tool. After many years when I go back and read my old learning notes I felt maybe I still need it in the future. So, start this repo to keep some of my old learning notes…

【数据结构】树和二叉树的概念及结构(一)

目录 一,树的概念及结构 1,树的定义 2,树结点的分类及关系 3,树的表示 二,二叉树的概念及结构 1,二叉树的定义 2,特殊的二叉树 3,二叉树的性质 4,二叉树的存储结构 1&…

Unity中Shader 纹理属性 Tilling(缩放度) 和 Offset(偏移度)

文章目录 前言一、Tilling(缩放度),个人理解有点像减小周期函数的周期的效果(在单位空间内,容得下重复的函数图像的多少)二、Offset(偏移度),个人理解是函数的平移三、在Shader中使用 Tilling 和…

如何批量查询所有德邦快递的物流信息

当我们需要查询多个德邦快递的物流信息时,我们可以使用固乔快递查询助手来批量查询。以下是具体的操作步骤: 1. 在浏览器中搜索并下载【固乔快递查询助手】软件。这款软件支持多种快递公司,包括德邦快递,而且可以批量查询物流信息…

洞发现-APP应用之漏洞探针利用修复(44)

主要分为三个部分,第一部分抓包是很重要的,第二部分是协议,第三部分是逆向(讲的不会太多,介绍根据使用不介绍原理), 关于反编译,app就分为安卓和苹果系统,苹果系统的源码…