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

智能合约安全分析,针对 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.rhkb.cn/news/118747.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2、Nginx 安装

文章目录 2、Nginx 安装2.1 官网下载2.2 安装 nginx2.2.1 第一步2.2.2 第二步2.2.3 第三步,安装 nginx2.2.4 第四步,修改防火漆规则 【尚硅谷】尚硅谷Nginx教程由浅入深 志不强者智不达;言不信者行不果。 2、Nginx 安装 2.1 官网下载 nginx…

软件测试面试怎样介绍自己的测试项目?会问到什么程度?

想知道面试时该怎样介绍测试项目?会问到什么程度?那就需要换位思考,思考HR在这个环节想知道什么。 HR在该环节普遍想获得的情报主要是下面这2个方面: 1)应聘者的具体经验和技术能力, 2)应聘者的…

Python实战之数据表提取和下载自动化

在网络爬虫领域,动态渲染类型页面的数据提取和下载自动化是一个常见的挑战。本文将介绍如何利用Pyppeteer库完成这一任务,帮助您轻松地提取动态渲染页面中的数据表并实现下载自动化。 一、环境准备 首先,确保您已经安装了Python环境。接下来…

Android.mk开发模板

今天简单写了一个 Android.mk 的示例模板,供初学者参考。 本模板主要给大家示例 Android NDK 开发中的如下几个问题: 如何自动添加需要编译的源文件列表如何添加第三方静态库、动态库的依赖如何构造一个完整的NDK工程框架 假设我们的项目依赖 libmath.…

【Go 基础篇】Go语言结构体基本使用

在Go语言中,结构体是一种重要的数据类型,用于定义和组织一组不同类型的数据字段。结构体允许开发者创建自定义的复合数据类型,类似于其他编程语言中的类。本文将深入探讨Go语言中结构体的定义、初始化、嵌套、方法以及与其他语言的对比&#…

小赢科技,寻找金融科技核心价

如果说金融是经济的晴雨表,是通过改善供给质量以提高经济质量的切入口,那么金融科技公司,就是这一切行动的推手。上半年,社会经济活跃程度提高背后,金融科技公司既是奉献者,也是受益者。 8月29日&#xff0…

postgresql并行查询(高级特性)

######################## 并行查询 postgresql和Oracle一样支持并行查询的,比如select、update、delete大事无开启并行功能后,能够利用多核cpu,从而充分发挥硬件性能,提升大事物的处理效率。 pg在9.6的版本之前是不支持的并行查询的,从9.6开始支持并行查询,但是功能非常…

go学习part21(3)redis连接池

连接池 1.介绍 每次使用数据就就建立链接再关闭可以,但是如果有大量客户端频繁请求连接,大量创建连接和关闭会非常耗费资源。 所以就建立一个连接池,里面存放几个不关闭的连接,谁要用就分配给谁。 说明:通过Golang 对 Redis操…

WebGPT VS WebGPU

推荐:使用 NSDT编辑器 快速搭建3D应用场景 随着WebGPU的引入,Web开发发生了有趣的转变,WebGPU是一种新的API,允许Web应用程序直接访问设备的图形处理单元(GPU)。这种发展意义重大,因为 GPU 擅长…

sublime编辑latex 出现参考文献无法编译报错:citation “...” undefined

问题描述 使用sublime编译latex文件时,参考文献按照常规的方式放好,ctrl B 编译的时候,显示找不到参考文献,编译出的pdf文件也没有references: 但是把文件放到overleaf上就可以直接编译出来,说明是本地编…

快速为RPG辅助工具MTool增加更多快捷键(一键保存等)

起源:MTool是个好工具,本身固然好用,但是它本身的快捷键功能很少,虽然内置了一个录制工具,但是一个个的录,又麻烦,一般人也难以掌握 本文用快速方法增加更多快捷键,可以做到一键保存…

c++ qt--线程(一)(第八部分)

c qt–线程(一)(第八部分) 一.进程(Process) 在任务管理器中的进程页下,可以看到进程,任务管理器将进程分为了三类,应用、后台进程、window进程 应用: 打开…

【UE 材质】实现方形渐变、中心渐变材质

步骤 一、实现方形渐变 1. 新建一个材质,材质域选择“后期处理” 2. 通过“Mask”节点单独获取R、G通道,可以看到R通道是从左到右0~1之间的变化,对应U平铺 可以看到G通道是从上到下0~1之间的变化,对应V平铺 3. 完善如下节点 二、…

Leetcode1090. 受标签影响的最大值

思路:根据值从大到小排序,然后在加的时候判断是否达到标签上限即可,一开始想用字典做,但是题目说是集合却连续出现两个8,因此使用元组SortedList进行解决 class Solution:def largestValsFromLabels(self, values: li…

Java后端开发面试题——多线程

创建线程的方式有哪些? 继承Thread类 public class MyThread extends Thread {Overridepublic void run() {System.out.println("MyThread...run...");}public static void main(String[] args) {// 创建MyThread对象MyThread t1 new MyThread() ;MyTh…

aarch64-linux交叉编译libcurl带zlib和openssl

交叉编译libcurl需要依赖zlib和openssl 需要先用aarch64工具链编译zlib和openssl aarch64-linux环境搭建 下载工具链 gcc用于执行交叉编译 gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnusysroot是交叉版本的库文件集合 sysroot-glibc-linaro-2.25-2019.12-aarch64-lin…

iOS逆向进阶:iOS进程间通信方案深入探究与local socket介绍

在移动应用开发中,进程间通信(Inter-Process Communication,IPC)是一项至关重要的技术,用于不同应用之间的协作和数据共享。在iOS生态系统中,进程和线程是基本的概念,而进程间通信方案则为应用的…

在 Spring Boot 中集成 MinIO 对象存储

MinIO 是一个开源的对象存储服务器,专注于高性能、分布式和兼容S3 API的存储解决方案。本文将介绍如何在 Spring Boot 应用程序中集成 MinIO,以便您可以轻松地将对象存储集成到您的应用中。 安装minio 拉取 minio Docker镜像 docker pull minio/minio创…

Linux:内核解压缩过程简析

文章目录 1. 前言2. 背景3. zImage 的构建过程4. 内核引导过程5. 内核解压缩过程6. 内核加压缩过程小结7. 参考资料 1. 前言 限于作者能力水平,本文可能存在谬误,因此而给读者带来的损失,作者不做任何承诺。 2. 背景 本文基于 ARM32架构 …

剑指 Offer 62. 圆圈中最后剩下的数字(简单)

题目&#xff1a; class Solution { public:int lastRemaining(int n, int m) {int pos 0;for(int i2;i<n;i){pos (posm)%i;}return pos;} };作者&#xff1a;想吃火锅的木易 链接&#xff1a;详细题解 来源&#xff1a;力扣&#xff08;LeetCode&#xff09;