Solidity智能合约编程漏洞及对策

简介:

上溢(Overflow)和下溢(Underflow)

Solidity能处理256位的整数。所以 2²⁵⁶-1 加1就会为0.这个就是Overflow

0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
+ 0x000000000000000000000000000000000001
----------------------------------------
= 0x000000000000000000000000000000000000

在Solidity中如果使用无符号整数,那么0减1就会得到最大的整数

0x000000000000000000000000000000000000
- 0x000000000000000000000000000000000001
----------------------------------------
= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF

对策是使用SafeMath库来做数学运算

 

Solidity可见性修饰符之差别

Public函数可以被任意调用(本合约的方法,被继承的合约方法,以及其他合约方法)

External函数不能被本合约方法调用

Private函数只能在本合约中被调用

Internal函数,稍微宽松一点,可以被本合约和继承合约的函数调用

Delegate Call是一个消息调用,需注意的是目标地址上的代码是运行在调用合约上下文当中的。这意味着调用的合约,可以在运行时动态的引入其他地址上的代码(模块化设计,对吧?),但是运行在调用合约的上下文中,以为着Storage, Balance, 和Current Address都是用的当前合约的

在下例中,攻击者可以通过在Delegation的上下文中调用Delegate合约中Public的PWN函数,从而获得合约的控制权

pragma solidity ^0.4.11;

// Credits to OpenZeppelin for this contract taken from the Ethernaut CTF
// https://ethernaut.zeppelin.solutions/level/0x68756ad5e1039e4f3b895cfaa16a3a79a5a73c59
contract Delegate {

  address public owner;

  function Delegate(address _owner) {
    owner = _owner;
  }

  function pwn() {
    owner = msg.sender;
  }
}

contract Delegation {

  address public owner;
  Delegate delegate;

  function Delegation(address _delegateAddress) {
    delegate = Delegate(_delegateAddress);
    owner = msg.sender;
  }
  
  // an attacker can call Delegate.pwn() in the context of Delegation
  // this means that pwn() will modify the state of **Delegation** and not Delegate
  // the result is that the attacker takes unauthorized ownership of the contract
  function() {
    if(delegate.delegatecall(msg.data)) {
      this;
    }
  }
}

Parity Hack同时错用了修饰符和Delegate Call。一个可以修改合约控制权的函数被设为Public。这就给黑客开了后门:定制虚假的msg.data来获得合约控制权。

msg.data里是要调用函数的签名=sha3 (alias for keccak256)的头8个字节。

web3.sha3("pwn()").slice(0, 10) --> 0xdd365b8b

如果函数有一个参数, pwn(uint256 x):
web3.sha3("pwn(uint256)").slice(0,10) --> 0x35f4581b

 

重入/Reentrancy问题(THEDAO Hack)

在以下的代码中,Call函数会等待直到所有的Gas都是用掉了。但是Sender和真正扣钱是有时间差的。

这就好比,你走进银行,找柜员取现金1000RMB,你的账户正好有1000RMB. 所以第一次,柜员会给你1000RMB。在柜员还没有来的及操作从你的账户中扣1000RMB,你再问柜员要1000RMB,柜员一查,发现你的账户上有1000RMB(因为还没有来得及扣掉),柜员会又给你1000RMB

function withdraw(uint _amount) public { 
    if(balances[msg.sender] >= _amount) { 
        if(msg.sender.call.value(_amount)()) 
          { _amount; } 
        balances[msg.sender] -= _amount; 
    } 
}

对策是:先扣钱,再送钱。另外一种方法是使用Mutex。

现在最好的方法是msg.sender.transfer(_value) . 如果确实要使用send ,用require(msg.sender.send(_value));

以太坊智能合约 —— 最佳安全开发指南

 

   参考: 

        文章1

        文章2

相关文章
|
Java 中间件 应用服务中间件
Servlet容器与Web容器详解
Servlet容器与Web容器详解
504 0
UniApp 获取当前页面标题(navigationBarTitleText)
UniApp 获取当前页面标题(navigationBarTitleText)
2133 0
|
人工智能 计算机视觉
Photoshop2023新版本win11系统安装下载教程
ps迎来了2023的版本,这次的版本提升针对windows11做了特别优化,启动速度比win10快了很多。期盼已久的Win版 PS 2023 终于来了,小编也是通过特殊渠道搞来的,本期带来的WIN版本支持一键安装激活,一次安装永久免费使用众所周知,版本越高,需要的电脑配置也就越来越高。下面放一下2023版本的配置供大家参考。需要注意的是这些版本不再支持windows7系统,仅支持win10及以上的操作系统。
2569 0
|
3月前
|
小程序 PHP 图形学
热门小游戏源码(Python+PHP)下载-微信小程序游戏源码Unity发实战指南​
本文详解如何结合Python、PHP与Unity开发并部署小游戏至微信小程序。涵盖技术选型、Pygame实战、PHP后端对接、Unity转换适配及性能优化,提供从原型到发布的完整指南,助力开发者快速上手并发布游戏。
|
存储 文件存储 数据库
在飞牛 NAS 上部署宝塔面板
飞牛NAS成为家庭私有云热门选择,通过部署宝塔面板,用户可以轻松搭建网站及各类Web应用,如相册、笔记、影视库等。本文介绍如何在飞牛NAS上安装宝塔面板,实现快速配置网站、数据库等服务,特别适合新手操作。
1822 5
在飞牛 NAS 上部署宝塔面板
|
12月前
|
SQL 弹性计算 安全
阿里云服务器租用价格:包年包月收费标准与最新活动价格参考
本文为大家分享阿里云服务器包年包月收费标准,云服务器最新活动价格,以及后续费挂载数据盘、设置密码和安全组等操作教程,以供参考。
|
Docker 容器
Docker服务启动失败报错:Job for docker.service failed because the control process exited with error code.
Docker服务启动失败报错:Job for docker.service failed because the control process exited with error code.
|
SQL 关系型数据库 MySQL
MySQL模糊查询二三事
在实际应用中,根据需求和实际数据情况,选择合适的模糊查询方法并优化查询模式,是确保查询效率和准确性的关键。复杂的查询模式往往需要详细的测试和调优,以达到最佳的性能与响应时效。
736 4
|
关系型数据库 MySQL C++
Windows Server 2012R2 安装mysql 丢失VCRUNTIME140_1.dll------亲测
Windows Server 2012R2 安装mysql 丢失VCRUNTIME140_1.dll------亲测
469 0
|
前端开发
UniApp 中的 u-input 属性讲解
UniApp 中的 u-input 属性讲解
2014 0