solidity 特性导致的漏洞

目录

1、默认可见性

2、浮点数精度缺失

3、错误的构造函数

4、自毁函数

5、未初始化指针-状态变量覆盖


1、默认可见性

Solidity 的函数和状态变量有四种可见性:external、public、internal、private。函数可见性默认为 public,状态变量可见性默认为 internal。

可见范围:private < internal < external < public

  • private:只有当前合约可见
  • internal:外部合约不可见,只有当前合约内部和子类合约可见
  • external:只能被外部合约或者外部调用者可见
  • public:公共函数和状态变量对所有智能合约可见

solidity 0.4 版本,函数不设置访问修饰符编译不会报错,函数默认的可见性是 public,如果一下敏感函数没有设置访问修饰符,就可能发生越权函数调用

漏洞场景:

敏感函数忘记设置访问修饰符

漏洞代码示例:

pragma solidity ^0.4.5;

contract HashForEther {
    function withdrawWinnings() {
        // Winner if the last 8 hex characters of the address are 0. 
        require(uint32(msg.sender) == 0);
        sendWinnings();
     }

     function sendWinnings() {
         msg.sender.transfer(this.balance);
     }
}

sendWinnings 函数忘记设置函数访问修饰符了,而默认可见性是 public,于是导致任意地址都可以调用改函数而获得转账。

2、浮点数精度缺失

浮点型,定长浮点型——Solidity目前暂时不支持浮点型,也不完全支持定长浮点型。

fixed/ufixed 表示有符号和无符号的定长浮点数,浮点型可以用来声明变量,但不可以用来赋值。

除法运算:除法运算的结果会四舍五入,如果出现小数,小数点后的部分都会被舍弃,只取整数部分

pragma solidity ^0.4.0;

contract C {
    uint constant public weiPerEth = 1e18;
    uint public token1;
    uint256 public token2;
    uint256  public token3;

    function testC(uint n1, uint n2) external  {
        token1 = 200 wei / weiPerEth;
        token2 = 80 / 10;
        token3 = n1 /n2;
    }
}

token1 由于除法运算出现了小数(0.0...02),取整数部分,变成了0。当 n1 小于 n2 时,如 8/10 ,token3 也将取 0.8 的整数部分,变成 0。

执行结果:

漏洞场景:

转账发送以太时,以太数量由除法运算结果所得,运算数字可控,可能导致结果精度丢失,最终导致以太丢失

漏洞示例:

pragma solidity ^0.4.23;

contract FunWithNumbers{
    uint constant public tokensPerEth = 10;
    uint constant public weiPerEth = 1e18;
    mapping(address => uint) public balances;

    function buyTokens() public payable {
        uint tokens = msg.value/weiPerEth * tokensPerEth; // 第一处浮点和精确度问题
        balances[msg.sender] += tokens;
    }

    function sellTokens(uint tokens) public {
        require(balances[msg.sender] >= tokens);
        uint eth = tokens/tokensPerEth;                ?// 第二处浮点和精确度问题
        balances[msg.sender] -= tokens;
        msg.sender.transfer(eth * weiPerEth);
    }
}

3、错误的构造函数

在 Solidity 0.4.22 版本之前,在Solidity中的0.4.22版本之前,所有的合约名和构造函数同名。编写合约时,如果构造函数名和合约名不相同,合约会添加一个默认的构造函数,自己设置的构造函数就会被当作普通函数,导致自己原本的合约设置未按照预期执行,从而造成安全漏洞。

漏洞场景:

  1. Solidity 0.4.22 前,构造函数与合约名相同,但是大小写不一样
  2. 构造函数错误地声明为了 public 或者 external

示例 1:

pragma solidity ^0.4.20;

contract OwnerWallet {

    address public owner;

    function ownerWallet(address _owner) public {
        owner = _owner;
    }

    function () payable {}

    function withdraw() public {
        require(msg.sender == owner);
        msg.sender.transfer(this.balance);
    }
}

示例 2:采用更安全的 constructor 

pragma solidity ^0.4.0;

contract C {
    address owner;
    constructor() public {
        owner = msg.sender;
    }
}

4、自毁函数

Solidity 智能合约中存在一个 selfdestruct() 自毁函数,该函数可以对创建的合约进行自毁,并且可强制将合约里的 Ether 转到自毁函数定义的地址中。

contract DeleteContract {


    constructor() payable {}

    receive() external payable {}

    function deleteContract() external {
        // 调用selfdestruct销毁合约,并把剩余的ETH转给msg.sender
        selfdestruct(payable(msg.sender));
    }

}

漏洞场景:

合约限制账户转入的以太数量,而攻击者可以使用自毁函数强制转入任意数量,并且使用 this.balance 作为敏感操作的判断条件

漏洞示例:

contract EtherGame {

    uint public payoutMileStone1 = 3 ether;
    uint public mileStone1Reward = 2 ether;
    uint public payoutMileStone2 = 5 ether;
    uint public mileStone2Reward = 3 ether; 
    uint public finalMileStone = 10 ether; 
    uint public finalReward = 5 ether; 

    mapping(address => uint) redeemableEther;
    function play() public payable {
        require(msg.value == 0.5 ether); 
        uint currentBalance = this.balance + msg.value;
        require(currentBalance <= finalMileStone);
        if (currentBalance == payoutMileStone1) {
            redeemableEther[msg.sender] += mileStone1Reward;
        }
        else if (currentBalance == payoutMileStone2) {
            redeemableEther[msg.sender] += mileStone2Reward;
        }
        else if (currentBalance == finalMileStone ) {
            redeemableEther[msg.sender] += finalReward;
        }
        return;
    }

    function claimReward() public {
        require(this.balance == finalMileStone);
        require(redeemableEther[msg.sender] > 0); 
        redeemableEther[msg.sender] = 0;
        msg.sender.transfer(redeemableEther[msg.sender]);
    }
}

攻击者角度分析

由于合约设置参与者每次提交的 Ether 数为 0.5,提交多次后就会达到10 Ether,因此攻击者就可以创建带有 selfdestruct() 函数的合约,通过 selfdestruct() 函数强制给它提供 0.1 Ether,当强制转入的 0.1 Ether 进入条件判断,最终的计算数值将永远不会成为整数,this.balance==finalMileStone 判断将永远不会成立,导致参与者永远不会获得奖励。所有参与者的 Ether 就会永远锁在 EtherGame 合约中。

5、未初始化指针-状态变量覆盖

合约中状态变量存储在 storage 中,会按声明顺序存入卡槽 slot

contract A{
    address owner;
    B addrB;
}

Solidity 对于复杂的数据类型,在函数中作为局部变量时,会默认存储在 storage 中。当声明的复杂数据类型局部变量未初始化时,它会默认成为指向 storage 的指针,就会指向 slot 0,这时如果声明了状态变量,那么第一个状态变量将会被覆盖。

pragma solidity ^0.4.0;

contract CC { 

    string public _name1;
    string public _name2;

    struct NameRecord {  
        string name1;   
        string name2; 
    }

    function CC() {
        _name1 = "makabaka";
        _name2 = "nigubigu";
    } 

    function register(string n1, string n2) public { 
        // 设置新的NameRecord ,未初始化
        NameRecord newRecord; 
        newRecord.name1 = n1; 
        newRecord.name2 = n2;  
    } 
    
}

register 函数中的结构体类型局部变量 newRecord,由于未初始化,默认会指向 slot 0,于是 newRecord.name1 会覆盖状态变量 _name1,newRecord.name2 会覆盖状态变量 _name2

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/246232.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RS485转WiFi工业路由器在冷链物流温度监控中的应用

随着物联网技术的不断发展和应用&#xff0c;冷链物流行业也迎来了新的机遇和挑战。在冷链物流中&#xff0c;对温度监控的要求尤为重要&#xff0c;因为温度是保证货物质量和安全的关键因素之一。而RS485转WiFi工业路由器则成为了实现高效、可靠的温度监控系统的重要组成部分。…

Linux ed命令教程:如何使用ed命令编辑文本文件(附案例详解和注意事项)

Linux ed命令介绍 ed命令是Linux中的一个简单文本编辑器。它是一种基于行的文本编辑器&#xff0c;用于创建、修改和操作文本文件。它是Unix中最早的编辑器&#xff0c;后来被vi和emacs文本编辑器所取代。 Linux ed命令适用的Linux版本 ed命令在大多数Linux发行版中都可以使…

群晖(Synology)云备份的方案是什么

群晖云备份方案就是在本地的 NAS 如果出现问题&#xff0c;或者必须需要重做整列的时候&#xff0c;保证数据不丢失。 当然&#xff0c;这些是针对有价值的数据&#xff0c;如果只是电影或者不是自己的拍摄素材文件&#xff0c;其实可以不使用云备份方案&#xff0c;因为毕竟云…

hive常用SQL函数及案例

1 函数简介 Hive会将常用的逻辑封装成函数给用户进行使用&#xff0c;类似于Java中的函数。 好处&#xff1a;避免用户反复写逻辑&#xff0c;可以直接拿来使用。 重点&#xff1a;用户需要知道函数叫什么&#xff0c;能做什么。 Hive提供了大量的内置函数&#xff0c;按照其特…

软件测评中心 ▏科技项目验收测试流程和注意事项简析

科技项目验收测试是指对已开发完成的科技项目进行测试和评估&#xff0c;以确认其达到预期的功能和性能要求&#xff0c;保证项目的质量和可靠性。 一、科技项目验收测试的流程一般包括以下几个阶段&#xff1a;   1、需求分析和测试计划&#xff1a;在开始测试前&#xff0…

RK3568平台(网络篇) 有线网络基本概念及测试手法

一.什么是交换机&#xff1f; 交换机是一种用于电(光)信号转发的网络设备。它可以为接入交换机的任意两个网络节点提供独享的电信号通路。最常见的交换机是以太网交换机。交换机工作于OSI参考模型的第二层&#xff0c;即数据链路层。交换机拥有一条高带宽的背部总线和内部交换…

打工人副业变现秘籍,某多/某手变现底层引擎-Stable Diffusion 模特假人换服装、换背景、换真人

给固定人物换背景或者换服装,需要用到一个Stable Diffusion扩展插件,就是sd-webui-segment-anything。 sd-webui-segment-anything 不仅可以做到抠图的效果,也能实现之多蒙版的效果。 什么是蒙版 图片蒙版是一种用于调节图像修改程度以及进行局部调整的工具。它通常分为四种…

LED恒流调节器FP7125,应用LED街道照明、调光电源、汽车大灯、T5T8日光灯

目录 一、FP7125概述 二、FP7125功能 三、应用领域 近年来&#xff0c;随着人们环保意识的不断增强&#xff0c;LED照明产品逐渐成为照明行业的主流。而作为LED照明产品中的重要配件&#xff0c;LED恒流调节器FP7125的出现为LED照明带来了全新的发展机遇。 一、FP7125概述 FP…

HarmonyOS(十三)——详解自定义组件的生命周期

前言 自定义组件的生命周期回调函数用于通知用户该自定义组件的生命周期&#xff0c;这些回调函数是私有的&#xff0c;在运行时由开发框架在特定的时间进行调用&#xff0c;不能从应用程序中手动调用这些回调函数。 下图展示的是被Entry装饰的组件生命周期&#xff1a; 今…

mysql 与mssql 命令有那些区别

use databasename 进入指定数据库名 命令一致 select databse() 查询当前进入数据库的名 mssql无法使用&#xff0c;mysql正常 mssql 暂无 C知道介绍 以下是MySQL和MSSQL命令的一些区别&#xff1a; 1. 连接数据库的命令不同&#xff1a; - MySQL&#xff1a;…

【Linux】free命令使用

free命令 ​free是指查看当前系统内存的使用情况&#xff0c;它显示系统中剩余及已用的物理内存和交换内存&#xff0c;以及共享内存和被核心使用的缓冲区。 作者 作者&#xff1a;Brian Edmonds。 语法 free [参数] free 命令 -Linux手册页 命令选项及作用 执行令 &am…

HI3559AV100和FPGA 7K690T的PCIE接口调试记录-续

上文https://blog.csdn.net/fzktongyong/article/details/134963814?spm1001.2014.3001.5501 上一篇文中PCIE实测速度和理论计算有较大偏差&#xff0c;经过尝试后有所提升。 1、提升效果 1&#xff09;、RC写操作&#xff0c;实测速度817MB/s&#xff08;410407&…

实验:华为静态路由配置

1.实验目的&#xff1a; 掌握华为路由器和交换机的基本配置方法理解静态路由的原理和作用学习使用vlan和trunk技术划分和连接不同网段能够通过ping命令测试网络连通性和故障排除 2.实验内容&#xff1a; 使用ARI200路由器和S5735交换机搭建如下图所示的网络拓扑在路由器上配…

Elasitcsearch--解决CPU使用率飙升

原文网址&#xff1a;Elasitcsearch--解决CPU使用率飙升_IT利刃出鞘的博客-CSDN博客 简介 本文介绍如何解决ES导致的CPU使用率飙升的问题。 问题描述 线上环境 Elasticsearch CPU 使用率飙升常见问题如下&#xff1a; Elasticsearch 使用线程池来管理并发操作的 CPU 资源。…

【深度学习目标检测】三、基于深度学习的人物摔倒检测(python,yolov8)

深度学习目标检测方法则是利用深度神经网络模型进行目标检测&#xff0c;主要有以下几种&#xff1a; R-CNN系列&#xff1a;包括R-CNN、Fast R-CNN、Faster R-CNN等&#xff0c;通过候选区域法生成候选目标区域&#xff0c;然后使用卷积神经网络提取特征&#xff0c;并通过分类…

商业智能BI和数据可视化的区别

现在市场上有非常多的商业智能BI产品&#xff0c;几乎都在着重宣传其数据可视化功能的强大&#xff0c;给人造成一种商业智能BI就是数据可视化的印象。事实上商业智能BI并不等于数据可视化。要探究商业智能BI和数据可视化的区别&#xff0c;我们先要分别弄清楚这两个概念。 1、…

【华为数据之道学习笔记】5-1支撑非数字原生企业数字化转型的数据底座建设框架

华为通过建设数据底座&#xff0c;将公司内外部的数据汇聚在一起&#xff0c;对数据进行重新组织和联接&#xff0c;让数据有清晰的定义和统一的结构&#xff0c;并在尊重数据安全与隐私的前提下&#xff0c;让数据更易获取&#xff0c;最终打破数据孤岛和垄断。通过数据底座&a…

20231214使用WPS将英文SRT字幕的全大写字符转换为首字母大写的小写字幕

20231214使用WPS将英文SRT字幕的全大写字符转换为首字母大写的小写字幕 2023/12/14 13:16 看英文纪录片&#xff0c;发现英文字母是全部大写。 所以需要整理成为小写的字幕【句子的首字符大小&#xff01;】 https://re.talking.1080p.hdtv.x265.aac.mvgroup.org/index.php?t…

【动态规划】【广度优先搜索】LeetCode:2617 网格图中最少访问的格子数

本文涉及的基础知识点 二分查找算法合集 动态规划 题目 给你一个下标从 0 开始的 m x n 整数矩阵 grid 。你一开始的位置在 左上角 格子 (0, 0) 。 当你在格子 (i, j) 的时候&#xff0c;你可以移动到以下格子之一&#xff1a; 满足 j < k < grid[i][j] j 的格子 (i,…

双向无线功率传输系统MATLAB仿真

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 模型简介&#xff1a; 初级侧转换器通过双向 AC/DC 转换器从电网获取电力&#xff0c;并由直流线电压 Vin 供电&#xff0c;而拾波侧被视为连接到 EV&#xff0c;并由连接到任一存储的单独直流源 Vout 表示或…