拒绝服务攻击
2022年4月,一家名为Akutar的热门NFT项目成功地进行了一次 荷兰式拍卖筹集了11,539.5个ETH。 However, when processing refunds for previous community pass holders, a flaw in their smart contract prevented operations, locking all funds within the contract due to a DoS vulnerability.
你可以在解析:AKUTARS NFT事件(2022年4月)中找到更多详细信息。
在Web2环境中,拒绝服务(DoS)攻击通常涉及使用过多的流量淹没服务器,使其无法处理合法请求。 在Web3领域,这类攻击利用漏洞来破坏智能合约操作。
漏洞示例
Let’s explore a simplified contract, GameOfFunds
, that demonstrates this type of vulnerability. 该合约允许玩家在开始时存入ETH,并打算 在游戏结束时退还这些存款。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;
contract GameOfFunds {
bool public refundsComplete;
mapping(address => uint256) public deposits;
address[] public participantList;
// Players deposit ETH into the contract
function contribute() external payable {
require(!refundsComplete, "Game Over");
require(msg.value > 0, "Please deposit ETH");
deposits[msg.sender] = msg.value;
participantList.push(msg.sender);
}
// Refund players at the end of the game
function processRefunds() external {
require(!refundsComplete, "Game Over");
for (uint256 i = 0; i < participantList.length; i++) {
address participant = participantList[i];
uint256 refundAmount = deposits[participant];
(bool success, ) = participant.call{value: refundAmount}("");
require(success, "Refund Failed!");
deposits[participant] = 0;
}
refundsComplete = true;
}
function getBalance() external view returns(uint256) {
return address(this).balance;
}
}
这个合约存在漏洞,因为processRefunds()
函数使用了call
方法,它会激活收件人地址的回退函数。 A malicious contract can disrupt this process.
contract Malicious {
fallback() external payable {
revert("DoS Attack!");
}
function initiateAttack(address gameAddress) external payable {
GameOfFunds game = GameOfFunds(gameAddress);
game.contribute{value: msg.value}();
}
}
预防策略
- 确保外部合同调用(包括回退函数)不会干扰或停止关键操作,即使个别交易失败,退款等流程也能继续进行。
- 即使关键参与者永久缺席,也要保持合约功能,并允许用户自行提取退款,而不是分批发放。
- 防止合约意外自毁并避免无限循环,以确保合约运行稳定和安全。