solidity 安全 未初始化指针的风险——天上不会掉馅饼

这篇具有很好参考价值的文章主要介绍了solidity 安全 未初始化指针的风险——天上不会掉馅饼。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

引用类型未初始化

引用类型,则必须明确指明数据存储哪种类型的位置里。 有三种位置: 内存memory 、 存储storage 以及 调用数据calldata 。

  • memory 即数据在内存中,因此数据仅在其生命周期内(函数调用期间)有效。不能用于外部调用。

  • storage 状态变量保存的位置,只要合约存在就一直存储.

  • calldata 用来保存函数参数的特殊数据位置,是一个只读位置。

在开发合约时,准确地理解如何使用这个操作至关重要。否则可以因为利用不适当地初始化变量来产生有漏洞的合约。

漏洞分析

在讨论这个漏洞之前,我们需要先了解状态变量在Solidity中是如何存储的。简单来说,状态变量按照合约中出现的顺序保存在slot中,例如第一个变量存储在slot0,第二个在slot1中,依次类推。

Solidity中,结构体,数组和映射等复杂数据结构,都是通过栈上的指针访问实际的存储位置,memory或者storage;当他们做的局部变量,如果没有初始化,则默认是放在 storage 中的,而且默认指向slot0。

这样意味着我们可以操作这个局部变量,间接控制了原来存在slot0上的值。

实例分析

pragma solidity ^0.4.19;

contract CryptoRoulette {

    uint256 public secretNumber;
    uint256 public betPrice = 0.1 ether;

    struct Game {
        address player;
        uint256 number;
    }

    function CryptoRoulette() public {
        shuffle();
    }

    function shuffle() internal {
        //secretNumber = uint8(sha3(now, block.blockhash(block.number-1))) % 20 + 1;
        secretNumber = 6;
    }

    function play(uint256 number) payable public {
        require(msg.value >= betPrice && number <= 10);

        Game game; //问题所在
        game.player = msg.sender;
        game.number = number;

        if (number == secretNumber) {
            msg.sender.transfer(this.balance);
        }

        shuffle();
    }
}

该合约设置了一个public(这里是故意的,让玩家认为这是合约的漏洞)属性的随机数 secretNumber,在 shuffle() 函数作用原来是指定blockhash和时间生成一个随机数(为了更加直观,我直接写死为6),玩家可以通过 play() 函数去盲猜这个随机数,如果猜对了就可以将合约中的所有eth取走,每次调用 play() 函数后都会重置随机数。即使玩家知道随机数是6,也不可能拿走合约里的eth,不信大家可以试试;

原因就是结构体 game的初始化对存储数据 secretNumber 的覆盖;其实就是我们上边讲的,secretNumber 存储到了slot0,game由于没有指定位置,所以默认在storage中,且位于slot0;所以我们初始化时,game.player = msg.sender ,由于结构体 game的初始化对存储数据 secretNumber 进行了覆盖,导致 secretNumber 变成了 msg.sender 的 uint256 内容,这样一来就使得后面的 if判断条件不能成立,从而使得玩家不能转走合约中的所有eth。

解决方法

我们在函数里直接初始化结构体必须加 memory 关键字,因为 memory 是使用内存来进行存储,这样一来就可以避免占用 storage 的存储位;该问题在 Solidity 0.5.0 版本以前只是进行了提示,并没有做出错误警告,所以在老版本编译器中要注意该问题。在最新的版本,则不需要担心,直接error。

这段代码其实是基于《加密轮盘赌轮》修改的,感兴趣的可以看看原来的。

GutHub 地址:github.com/smart-contract-honeypots/CryptoRoulette.sol文章来源地址https://www.toymoban.com/news/detail-791843.html

到了这里,关于solidity 安全 未初始化指针的风险——天上不会掉馅饼的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • L2TP连接尝试失败,因为安全层在初始化与远程计算机的协商时遇到一个处理错误。

    一、首先这个问题,有一定概率出现(已确认) 1. 使用后未将其断开或者频繁连接断开,导致注册表出现异常。(目前推断是这样的) 2. 系统网卡驱动问题,需要进行网络重置,卸载网卡驱动后重新安装网卡驱动。(已使用2年半的方法) 二、关联的系统服务选项 服务名称

    2024年02月02日
    浏览(64)
  • Pytorch权重初始化/参数初始化

    refer: 【Pytorch】各网络层的默认初始化方法 https://blog.csdn.net/guofei_fly/article/details/105109883 其实Pytorch初始化方法就在各自的层的 def reset_parameters(self) - None: 方法中。 有人可能会问 为什么这个方法和Pytorch直接出来的权重初始值不一样 ?单步调试会发现其实这个方法运行了至少两

    2024年02月11日
    浏览(66)
  • win11 解决L2TP连接尝试失败,因为安全层在初始化与远程计算机的协商时遇到一个处理错误

    百度了大量文章挨个试,最终结合多个文章的方法连上了。这里整合记录一下  修改注册表 1:在“开始 运行”中输入regedit.exe,单击“确定”,进入 2:找到这个目录 HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesPolicyAgent   点击:编辑--新键--dword   文件名称:AssumeUDPEncapsulation

    2024年02月15日
    浏览(53)
  • Linux内存初始化-启动阶段的内存初始化

    本文代码基于ARM64平台, Linux kernel 5.15 在加载kernel 之前, kernel对于系统是有一定要求的,明确规定了boot阶段必须要把MMU关闭: 那么在进入kernel之后, 就必须有一个使能MMU, 建立映射的过程, 本文描述kernel启动阶段进行内存初始化相关的操作。 在初始化阶段,我们mapping二段

    2024年02月08日
    浏览(78)
  • 【温故而知新】JavaScript初始化/初始化加载

    在JavaScript中,对象、数组、函数、类等都可以通过不同的方式进行初始化。以下是几种常见的初始化方式: 对象初始化: 使用字面量方式: 使用构造函数方式: 数组初始化: 使用字面量方式: 使用构造函数方式: 函数初始化: 类初始化: 使用Array的of和from方法进行数组

    2024年01月24日
    浏览(78)
  • 深度学习参数初始化(二)Kaiming初始化 含代码

    目录 一、介绍 二、基础知识 三、Kaiming初始化的假设条件  四、Kaiming初始化的简单的公式推导 1.前向传播 2.反向传播 五、Pytorch实现 深度学习参数初始化系列: (一)Xavier初始化 含代码 (二)Kaiming初始化 含代码         Kaiming初始化论文地址:https://arxiv.org/abs/1502.01

    2024年02月04日
    浏览(78)
  • 【随机种子初始化】一个神经网络模型初始化的大坑

    半年前写了一个模型,取得了不错的效果(简称项目文件1),于是整理了一番代码,保存为了一个新的项目(简称项目文件2)。半年后的今天,我重新训练这个整理过的模型,即项目文件2,没有修改任何的超参数,并且保持完全一致的随机种子,但是始终无法完全复现出半

    2024年02月09日
    浏览(69)
  • 初始化磁盘选哪个格式 初始化磁盘分区形式选什么好

    在 初始化磁盘 之前,我们应该先明确什么时候需要初始化磁盘,通常是在电脑安装了SSD固态硬盘,计算机无法正常读取该固态硬盘时。或者需要腾空移动磁盘,以做它用时。那么初始化磁盘时,有哪些格式呢?如今主流的是NTFS格式。也有FAT 32格式,但读写性能会比较差。

    2024年02月09日
    浏览(49)
  • Win11配置VPN:L2TP连接尝试失败,因为安全层在初始化与远程计算机的协商时遇到了一个处理错误

    (1)在“开始 运行”中输入regedit.exe,单击“确定”,进入注册表编辑器。 (2)在“注册表编辑器”页面的左侧导航树中,选择“我的电脑 HKEY_LOCAL_MACHINE SYSTEM CurrentControlSet Services PolicyAgent”,在菜单栏上选择“编辑 新建 DWORD值”。 (3)键入AssumeUDPEncapsulationContextOnSendRule,敲击键

    2024年02月08日
    浏览(62)
  • c# 初始化列表,并给列表里面所有的元素进行初始化

    Enumerable.Repeat 方法是用于生成一个包含指定元素重复若干次的序列。它接受两个参数,第一个参数是要重复的元素,第二个参数是重复次数。 下面是 Enumerable.Repeat 方法的用法和示例:

    2024年02月13日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包