某60区块链安全之重入漏洞实战记录
区块链安全
文章目录
- 区块链安全
- 重入漏洞实战
- 实验目的
- 实验环境
- 实验工具
- 实验原理
- 实验内容
重入漏洞实战
实验目的
学会使用python3的web3模块
学会以太坊重入漏洞分析及利用
实验环境
Ubuntu18.04操作机
实验工具
python3
实验原理
以太坊智能合约的特点之一是能够调用和使用其他外部合约的代码。这些合约通常会操作以太币,经常将以太发送到各种外部用户地址。这种调用外部合约或向外部地址发送以太币的操作,需要合约提交外部调用。这些外部调用可能被攻击者劫持,比如,通过一个回退函数,强迫合约执行进一步的代码,包括对自身的调用。这样代码可以重复进入合约,这就是“重入” 的来源。著名的 DAO 黑客攻击事件中就是利用了这种类型的漏洞。
合约可以有一个未命名的函数。这个函数不能有参数也不能有返回值。 如果在一个到合约的调用中,没有其他函数与给定的函数标识符匹配(或没有提供调用数据),那么这个函数(fallback 函数)会被执行。除此之外,每当合约收到以太币(没有任何数据),这个函数就会执行。此外,为了接收以太币,fallback函数必须标记为payable。 如果不存在这样的函数,则合约不能通过常规交易接收以太币。
合约使用 call 函数调用发送以太币时,默认提供所有剩余的 gas。这也给了恶意合约发起重入攻击的条件。
题目环境是测试链,所以需要本地与题目进行交互,可使用python3中的web3模块,通过web3模块的rpc功能与题目交互,从而编写自动化利用脚本。
实验内容
找到合约重入漏洞并形成利用
使用python3的web3模块远程利用漏洞并获取flag
实验地址为nc ip 10002
nc ip 10002连接到题目,输入1,获取部署合约的game account及token
打开http://ip,输入上述分配的game account,点击Request获取eth
查看源码
漏洞主要在于 withdraw() 函数,合约在进行提币时,使用 require 依次判断提币账户是否拥有相应的资产,随后使用 msg.sender.call.value(amount) 来发送 Ether ,处理完成后相应修改用户资产数据
在提币的过程中,存在一个递归 withdraw 的问题(因为 -=_amount 在转账之后),攻击者可以部署一个包含恶意递归调用的合约将公共钱包合约里的 Ether 全部提出
其中,转账使用的是 address.call.value()() 函数,传递了所有可用 gas 供调用,是可以成功执行递归的前提条件
python3 exp.py