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

智能合约中外部调用漏洞

外部调用 :

在智能合约开发中,调用不受信任的外部合约是一个常见的安全风险点。这是因为,当你调用另一个合约的函数时,你实际上是在执行那个合约的代码,而这可能会引入你未曾预料的行为,包括恶意行为。下面我将通过一个示例来说明这一风险,并提出相应的缓解策略。

漏洞合约示例

假设我们有一个智能合约,它允许用户通过调用一个外部合约来完成某种任务,比如兑换代币。这里,我们假设外部合约提供了一个transferFrom函数,用于从一个账户向另一个账户转移代币。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;contract ExternalCallVulnerable {address public externalTokenContract;constructor(address _externalTokenContract) {externalTokenContract = _externalTokenContract;}function exchangeTokens(uint256 amount) public {IERC20(externalTokenContract).transferFrom(msg.sender, address(this), amount);}
}

在这个合约中,exchangeTokens函数调用了外部合约的transferFrom函数。然而,这里存在一个潜在的问题:外部合约可能包含恶意代码,或者其逻辑可能与预期不符,导致资金损失或其他不良后果。

攻击演示

攻击者可以通过部署一个恶意的ERC20代币合约,并将这个合约地址传递给我们的合约。恶意合约可能在transferFrom函数中包含额外的逻辑,比如在转移代币的同时,调用我们的合约中的其他函数,或者执行一些未授权的操作。

// 恶意合约示例
contract MaliciousToken is IERC20 {function transferFrom(address, address, uint256) public override returns (bool) {// 正常转移代币逻辑...// 执行额外的恶意操作,例如调用合约中的其他函数ExternalCallVulnerable(0x...).someUnsafeFunction();return true;}
}

当用户尝试通过我们的合约交换恶意合约中的代币时,恶意合约的transferFrom函数会被调用,执行恶意操作。

解决方案

为了减轻外部调用带来的风险,我们可以采取以下措施:

  • 1、代码审查:在允许调用外部合约之前,对其进行彻底的代码审查,确保其逻辑符合预期,没有包含恶意代码。

  • 2、白名单机制:只允许调用经过验证的、可信任的合约列表。这样,即使出现新的恶意合约,也无法通过我们的合约进行调用。

  • 3、使用安全库:利用如OpenZeppelin等安全库中的标准化接口,这些接口通常已经考虑到了安全性和兼容性问题。

  • 4、限制调用深度:避免在调用外部合约时再次调用其他外部合约,以防止递归调用导致的攻击。

  • 5、事件监听与异常处理:在调用外部合约时,监听返回值和异常,确保调用成功并且没有发生异常行为。

下面是一个改进后的合约示例,其中实现了白名单机制:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;interface IERC20 {function transferFrom(address, address, uint256) external returns (bool);
}contract SafeExternalCall {mapping(address => bool) public approvedContracts;address public externalTokenContract;constructor(address _externalTokenContract) {approveContract(_externalTokenContract);externalTokenContract = _externalTokenContract;}function exchangeTokens(uint256 amount) public {require(approvedContracts[externalTokenContract], "Contract not approved");IERC20(externalTokenContract).transferFrom(msg.sender, address(this), amount);}function approveContract(address contractAddress) public {approvedContracts[contractAddress] = true;}
}

在智能合约开发中,调用不受信任的外部合约是一个常见的安全风险点。这是因为,当你调用另一个合约的函数时,你实际上是在执行那个合约的代码,而这可能会引入你未曾预料的行为,包括恶意行为。下面我将通过一个示例来说明这一风险,并提出相应的缓解策略。

漏洞合约示例

假设我们有一个智能合约,它允许用户通过调用一个外部合约来完成某种任务,比如兑换代币。这里,我们假设外部合约提供了一个transferFrom函数,用于从一个账户向另一个账户转移代币。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;contract ExternalCallVulnerable {address public externalTokenContract;constructor(address _externalTokenContract) {externalTokenContract = _externalTokenContract;}function exchangeTokens(uint256 amount) public {IERC20(externalTokenContract).transferFrom(msg.sender, address(this), amount);}
}

在这个合约中,exchangeTokens函数调用了外部合约的transferFrom函数。然而,这里存在一个潜在的问题:外部合约可能包含恶意代码,或者其逻辑可能与预期不符,导致资金损失或其他不良后果。

攻击演示

攻击者可以通过部署一个恶意的ERC20代币合约,并将这个合约地址传递给我们的合约。恶意合约可能在transferFrom函数中包含额外的逻辑,比如在转移代币的同时,调用我们的合约中的其他函数,或者执行一些未授权的操作。

// 恶意合约示例
contract MaliciousToken is IERC20 {function transferFrom(address, address, uint256) public override returns (bool) {// 正常转移代币逻辑...// 执行额外的恶意操作,例如调用合约中的其他函数ExternalCallVulnerable(0x...).someUnsafeFunction();return true;}
}

当用户尝试通过我们的合约交换恶意合约中的代币时,恶意合约的transferFrom函数会被调用,执行恶意操作。

安全改进

为了减轻外部调用带来的风险,我们可以采取以下措施:

  1. 代码审查:在允许调用外部合约之前,对其进行彻底的代码审查,确保其逻辑符合预期,没有包含恶意代码。

  2. 白名单机制:只允许调用经过验证的、可信任的合约列表。这样,即使出现新的恶意合约,也无法通过我们的合约进行调用。

  3. 使用安全库:利用如OpenZeppelin等安全库中的标准化接口,这些接口通常已经考虑到了安全性和兼容性问题。

  4. 限制调用深度:避免在调用外部合约时再次调用其他外部合约,以防止递归调用导致的攻击。

  5. 事件监听与异常处理:在调用外部合约时,监听返回值和异常,确保调用成功并且没有发生异常行为。

下面是一个改进后的合约示例,其中实现了白名单机制:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;interface IERC20 {function transferFrom(address, address, uint256) external returns (bool);
}contract SafeExternalCall {mapping(address => bool) public approvedContracts;address public externalTokenContract;constructor(address _externalTokenContract) {approveContract(_externalTokenContract);externalTokenContract = _externalTokenContract;}function exchangeTokens(uint256 amount) public {require(approvedContracts[externalTokenContract], "Contract not approved");IERC20(externalTokenContract).transferFrom(msg.sender, address(this), amount);}function approveContract(address contractAddress) public {approvedContracts[contractAddress] = true;}
}

在这个改进后的合约中,我们添加了一个approvedContracts映射,用于存储经过审批的外部合约地址。只有当外部合约地址被列入白名单时,才能通过我们的合约进行调用。

通过这些改进,我们可以大大降低因调用不受信任的外部合约而引入的安全风险。然而,在实际应用中,还需要持续关注新的安全威胁和最佳实践,以维护合约的安全性。

相关文章:

智能合约中外部调用漏洞

外部调用 : 在智能合约开发中,调用不受信任的外部合约是一个常见的安全风险点。这是因为,当你调用另一个合约的函数时,你实际上是在执行那个合约的代码,而这可能会引入你未曾预料的行为,包括恶意行为。下面…...

转型AI产品经理(4):“认知负荷”如何应用在Chatbot产品

认知负荷理论主要探讨在学习过程中,人脑处理信息的有限容量以及如何优化信息的呈现方式以促进学习。认知负荷定律认为,学习者的工作记忆容量是有限的,而不同类型的认知任务会对工作记忆产生不同程度的负荷,从而影响学习效果。以下…...

【C++11】常见的c++11新特性(一)

文章目录 1. C11 简介2. 常见的c11特性3.统一的列表初始化3.1initializer_list 4. decltype与auto4.1decltype与auto的区别 5.nullptr6.右值引用和移动语义6.1左值和右值6.1.1左值的特点6.1.2右值的特点6.1.3右值的进一步分类 6.2左值引用和右值引用以及区别6.2.1左值引用6.2.2…...

牛客周赛 Round 46 题解 C++

目录 A 乐奈吃冰 B 素世喝茶 C 爱音开灯 D 小灯做题 E 立希喂猫 F 祥子拆团 A 乐奈吃冰 #include <iostream> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <set> #include <vector>…...

9.3 Go 接口的多态性

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…...

Java通过字符串字段匹配形成树形结构

Java通过字符串字段匹配形成树形结构 文章目录 Java通过字符串字段匹配形成树形结构数据表模拟数据解决办法:1、domian 类:2、Node层(形成树形关系):3、controller 层4、Util 工具类1、BeanCopierUtil4、Mapper5、Manager(用来组装树形结构)6、测试:有的时候我们形成树形不…...

数字孪生智慧水利:精准管理与智能决策的新时代

图扑数字孪生技术在智慧水利中的应用&#xff0c;通过虚拟模型与真实水利系统的无缝连接&#xff0c;实现对水资源和水利工程的全面监控和精细管理。实时数据采集与动态模拟提升了水利系统的预测和响应能力&#xff0c;从洪水预警到水质监测&#xff0c;数字孪生助力各项决策更…...

基于ChatGLM3的本地问答机器人部署流程

基于ChatGLM3的本地问答机器人部署流程 前言一、确定文件结构1.新建文件夹储存本地模型2.下载源码和模型 二、Anaconda环境搭建1.创建anaconda环境2.安装相关库3.设置本地模型路径4.启动 三、构建本地知识库1.下载并安装postgresql2.安装c库3.配置向量插件 四、线上运行五、 全…...

归并排序——逆序数对的统计

逆序数对的统计 题目描述 运行代码 #include <iostream> using namespace std; #define LL long long const int N 1e5 5; int a[N], tmp[N]; LL merge_sort(int q[], int l, int r) {if (l > r)return 0; int mid l r >> 1; LL res merge_sort(q, l,…...

基于截图和模拟点击的自动化压测工具开发(MFC)

1.背景 想对一个MFC程序做自动压测功能&#xff0c;根据判断程序界面某块区域是否达到预定状态&#xff0c;来自动执行鼠标点击或者键盘输入的操作&#xff0c;以解决测试人员需要重复手动压测问题。 1.涉及的技术 串口控制&#xff0c;基于MFC橡皮筋类(CRectTracker)做一个…...

力扣每日一题 6/10

881.救生艇[中等] 题目&#xff1a; 给定数组 people 。people[i]表示第 i 个人的体重 &#xff0c;船的数量不限&#xff0c;每艘船可以承载的最大重量为 limit。 每艘船最多可同时载两人&#xff0c;但条件是这些人的重量之和最多为 limit。 返回 承载所有人所需的最小船…...

[知识点] 内存顺序属性的用途和行为

C标准库中定义了以下几种内存顺序属性&#xff1a; std::memory_order_relaxedstd::memory_order_consumestd::memory_order_acquirestd::memory_order_releasestd::memory_order_acq_relstd::memory_order_seq_cst 1. std::memory_order_relaxed 定义&#xff1a;不提供同步…...

JAVA Mongodb 深入学习(二)索引的创建和优化

一、常用索引类型 1、单个索引 单个索引的创建 db.你的表名.createIndex({"你的字段名":1}) 单个索引的创建且是唯一索引 db.你的表名.createIndex({"你的字段名":1}),{ unique: true }) 2、复合索引 将多个过滤的字段&#xff0c;做成索引&#xff0c;…...

转让北京劳务分包地基基础施工资质条件和流程

地基基础资质转让流程是怎样的?对于企业来说&#xff0c;资质证书不仅是实力的证明&#xff0c;更是获得工程承包的前提。而在有了资质证书后&#xff0c;企业才可以安心的准备工程投标&#xff0c;进而在工程竣工后获得收益。而对于从事地基基础工程施工的企业&#xff0c;需…...

Python基础——字符串

一、Python的字符串简介 Python中的字符串是一种计算机程序中常用的数据类型【可将字符串看作是一个由字母、数字、符号组成的序列容器】&#xff0c;字符串可以用来表示文本数据。 通常使用一对英文的单引号&#xff08;&#xff09;或者双引号&#xff08;"&#xff09;…...

AP的数据库性能到底重要吗?

先说结论&#xff1a;没那么重要。甚至可能不重要。 我用我的经历和分析给大家说说。诸位看看如何。 不重要的观点是不是不能接受&#xff1f; 因为这些是站在我们角度觉得的。而实际上使用者&#xff08;业务或者用户&#xff09;&#xff0c;真的不太在乎我们所在乎的。 …...

Vue3【二】 VSCode需要安装的Vue语法插件

VSCode需要安装的 适配Vue3的插件 Vue-Official插件安装...

设置路径别名

一、描述 如果想要给路径设置为别名&#xff0c;就是常见的有些项目前面的引入文件通过开头的&#xff0c;也就是替换了一些固定的文件路径&#xff0c;怎么配置。 二、配置 import { defineConfig } from vite import react from vitejs/plugin-react import path from path…...

人事信息管理系统(Java+MySQL)

一、项目背景 在现代企业中&#xff0c;管理大量员工的工作信息、薪资、请假、离职等事务是一项非常繁琐和复杂的任务。传统的手工管理方式不仅效率低下&#xff0c;而且容易出错。为了提高人事管理的效率&#xff0c;减少人工操作带来的错误&#xff0c;企业迫切需要一个高效…...

Python 中生成器与普通函数的区别

在Python中&#xff0c;生成器和普通函数有一些区别。 生成器使用 yield 语句从函数中返回一个值&#xff0c;而不是使用 return 语句。当生成器函数被调用时&#xff0c;它会返回一个迭代器对象&#xff0c;而非立即执行函数体内的代码。 生成器函数可以通过多次调用 yield 语…...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略&#xff0c;并且实现了基本的选区操作&#xff0c;还调研了自绘选区的实现。那么相对的&#xff0c;我们还需要设计编辑器的选区表达&#xff0c;也可以称为模型选区。编辑器中应用变更时的操作范围&#xff0c;就是以模型选区为基准来…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

pam_env.so模块配置解析

在PAM&#xff08;Pluggable Authentication Modules&#xff09;配置中&#xff0c; /etc/pam.d/su 文件相关配置含义如下&#xff1a; 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块&#xff0c;负责验证用户身份&am…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

Android15默认授权浮窗权限

我们经常有那种需求&#xff0c;客户需要定制的apk集成在ROM中&#xff0c;并且默认授予其【显示在其他应用的上层】权限&#xff0c;也就是我们常说的浮窗权限&#xff0c;那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开&#xff0c;首…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)

前言&#xff1a; 最近在做行为检测相关的模型&#xff0c;用的是时空图卷积网络&#xff08;STGCN&#xff09;&#xff0c;但原有kinetic-400数据集数据质量较低&#xff0c;需要进行细粒度的标注&#xff0c;同时粗略搜了下已有开源工具基本都集中于图像分割这块&#xff0c…...