http://www.7klian.com

以太坊中智能合约进攻和裂痕百科全书

    }
为了防备此类进攻的产生,必需仔细思量在应用措施中归并基于时间的操纵是否安详。
}
Solidity为钻石问题提供的办理方案是利用反向C3线性化。这意味着它将使担任从右到左线性化,因此担任的顺序很重要。发起从更一般的智能合约开始,再到更详细的智能合约竣事,以制止呈现问题。
    address payable owner;
    function relay(bytes _data) public {
进攻
equire()要领用于验证条件,譬喻输入或智能合约状态变量,或验证来自外部智能合约挪用的返回值。 为了验证外部挪用,可以由挪用者提供输入,也可以由被挪用返回输入。假如被挪用方的返回值产生输入斗嘴,则大概是以下两种环境之一出了问题:
要办理此问题,首先要思量需求条件是否太强。如有须要,请削弱它以答允任何有效的外部输入。假如问题不是必须条件,则智能合约中必需有提供外部输入的错误。确保此智能合约未提供无效输入。
· 要求条件太强。
此刻或block.timestamp会见的块的时间戳可由矿工操纵。 利用时间戳执行智能合约函数时,应思量三个因素。
执行事务的用户(转发器)可以通过仅利用足以执行事务的气体而不是足够使子挪用乐成的气体来有效地审查事务。
假如资金被发送到一个由坏的参加者建设的智能合约中,这大概会有问题,因为他们可以简朴地建设一个回退函数来还原所有付款。
另一种靠得住的防范要领是标志不受信任的成果。
意外的以太坊余额
        require(refundAddresses[x].send(refunds[refundAddresses[x]])) 
这种环境也大概导致进攻。假设一个坏的参加者抉择建设大量的地点,每个地点从智能合约中付出少量资金。假如有效地执行,则可以无限期地阻止事务,甚至大概阻止进一步的事务处理惩罚。
3. 利用区块哈希,因为网络越发分手,区块的开采本钱更高。
        currentLeader = msg.sender;
检测智能合约中错误
限制区块气体的DoS
    }
假如智能合约利用某些汇编指令(譬喻mstore),则进攻者大概可以或许将函数变量指向任何其他函数。这大概使进攻者可以或许粉碎智能合约的函数,甚至大概耗尽智能合约资金。
时间戳依赖性
function payOut() {
签名延展性
    }
  uint a = 2;
在这里,我们可以看到余额只有在资金转移后才被修改。这可以让黑客在余额配置为0之前多次挪用该函数,有效地耗尽智能合约。
利用诸如block.timestamp,blockhash和block.difficulty之类的链属性好像是个好主意,因为它们凡是会发生伪随机值。然而,问题在于矿工修改这些值的本领。 譬喻在具有数百万美元大奖的打赌应用中,矿工有足够的动力去生成很多替代区块,只选择会导致矿工中奖的区块。虽然,要像这样节制区块链会支付庞大的价钱,可是假如赌注足够高,那必定可以做到。
        if (highestBidder != address(0)) {
function refundAll() public {
具有函数范例变量的任意跳转
可重入性是一种进攻,当契约函数中的错误答允函数在本应克制的环境下多次执行时,大概会产生这种进攻。假如恶意利用,这可以用来从智能合约中抽走资金。实际上,可重入性是DAO进攻中利用的进攻向量。
尽量好像应该除掉与Vulnerable智能合约的任何生意业务,但实际上有两种要领可以强制发送Ether。
        …
如Fomo3D(倒数游戏,最后一位投资者赢得了头奖,但每项投资都增加了倒计时的时间)是由一个用户赢得的,该用户在短时间内完全阻塞了区块链,不答允其他人在按时器运行之前举办投资出局,他赢了得了角逐。
}
    }
uint256 nextPayeeIndex;
        // Do something bad
人们凡是会假设在智能合约中利用加密签名系统会验证签名是否独一; 可是事实并非如此。在
以太坊中的签名可以在没有私钥的环境下举办变动并保持有效。 譬喻椭圆密钥暗码术由三个变量v,r和s构成,假如以正确的方法修改了这些值,则可以得到带有无效私钥的有效签名。
无限操纵
这种布局可有效防备重入,因为智能合约的修改状态将防备不良行为者执行恶意交互。
Payee[] payees;
mapping (address => uint) public refunds;
  uint256 amount = balances[msg.sender];
function withdraw() external {
}
很多智能合约进攻是由开拓人员健忘或放弃利用可见性修饰符引起的。 然后默认环境下将该函数配置为public,这大概导致意外状态变动。
在Solidity中,您可以利用初级挪用,譬喻address.call(),address.callcode(),address.delegatecall()和address.send(),也可以利用智能合约挪用,譬喻ExternalContract.doSomething( )。初级挪用永远不会激发异常-相反,假如碰着异常,它们将返回false,而智能合约挪用将自动激发。
contract SuperContract {
· 计较劲增加(不须要的气体耗损)
在本节中,我们将先容已知的智能合约
裂痕以及如何制止这些裂痕。此处列出的险些所有裂痕都可以在智能合约弱点分类中找到。
在某些环境下,纵然您未遍历未指定长度的数组,您的智能合约也大概受到气体限制的进攻。进攻者可以通过利用足够高的气体价值来填充生意业务之前的几个区块。

上的应用措施打点财政代价,使安详性变得绝对重要。作为一种新兴的、尝试性的技能,智能合约虽然也受到了相当多的进攻。
// INSECURE
    }
uint16 => 65535
        // replay protection; do not call the same transaction twice
  }
以太坊生意业务要求发送者付出费以抑制垃圾生意业务进攻,可是在某些环境下,可以有足够的念头来举办此类进攻。譬喻在Dapp Fomo3D上利用了区块填充进攻。该应用措施具有倒数计时器,通过最后一次购置密钥,用户可以赢得大奖-除非用户每次购置钥密钥,计时器城市耽误。进攻者购置了一把密钥,然后持续塞满了接下来的13个区块,这样他们才气赢得大奖。
为了越发安详地举办签名验证,请遵循以下发起:
    address highestBidder;
}
这种进攻是通过以很高的气体价值刊行几笔生意业务来完成的。假如气体价值足够高,而且生意业务耗损了足够的气体,它们就可以填满整个区块并阻止其他生意业务被处理惩罚。
为了制止在随机数生成中哄骗矿工,有一些办理方案:
前端运行又称为事务排序依赖性
  if (balances[msg.sender] >= amount) {
结构函数名称不正确
uint8 => 255
· 提供输入的条约中有一个bug。
另外,为了得到最佳安详性,请利用“checks-effects-interactions”模式。这是智能合约函数的简朴履历法例。
假如在assert()中查抄的条件实际上不是稳定的,则发起您将其替换为require()语句。
        require(gasleft() >= _gasLimit);
在Solidity中可以两次利用沟通的变量,但大概会导致意外的副浸染。 对付利用多个智能合约,这尤其坚苦。 请看以下示例:
在智能合约开拓方面,遵循尺度很重要。配置尺度是为了防备裂痕,而忽略这些裂痕大概会导致意想不到的效果。
在Solidity 0.4.10中,建设了以下函数:assert(),require()和revert()。 在这里,我们将接头assert函数以及如何利用它。
        require(success);
        owner = msg.sender;
  balances[msg.sender] = 0;
以太坊的参考类型“ Yellow Paper”(黄皮书)没有划定可以改变几多区块的时间限制,它必需大于其父级的时间戳。话虽这么说,风行的协议实现会拒绝未来时间戳大于15秒的区块,因此只要您的时间相关事件可以安详地相差15秒,就可以安详地利用区块时间戳。
写入任意存储位置
uint256 =>(2 ^ 256)-1
跨函数重入进攻
在这里,我们可以看到SubContract担任了SuperContract,而且变量a被两次界说为差异的值。 此刻,假设我们利用a在SubContract中执行某些成果。 由于已修改a的值,因此从SuperContract担任的成果将不回复浸染。
假如未查抄初级挪用的返回值,则纵然函数挪用抛堕落误,也大概继承执行。这大概导致意外行为并粉碎措施逻辑。失败的挪用甚至大概是由进攻者引起的,进攻者可以进一步操作应用措施举办进攻。
由于delegatecall提供了对智能合约的如此多的节制权,因此只将其用于可信的智能合约(好比您本身的智能合约)长短常重要的。假如方针地点来自用户输入,请确保它是受信任的协定。
由于始终可以将以太坊发送到智能合约中(请参阅“强行将以太币发送到智能合约”)-假如智能合约具有特定的余额,则很容易受到进攻。
    }
}
接下来,应执行智能合约的效力-譬喻状态修改。
为制止签名可延展性的问题,切勿在签名动静哈希中利用签名来查抄智能合约是否已处理惩罚了先前签名的动静,因为恶意用户可以找到并从头建设您的签名。
    }
有两种要领可以防备这种环境产生。第一种办理方案是仅答允受信任的用户中继事务。另一种办理方案是要求转运商提供足够的气体,如下所示。
当易受进攻的函数与进攻者试图递归挪用的函数沟通时,就会产生单函数重入进攻。
· 存储智能合约处理惩罚的每个动静哈希,然后在执行成果之前比较现有哈希查抄动静哈希。
    balances[msg.sender] -= amount;
· 切勿生成包括签名的动静哈希。
最后,我们可以与其他智能合约举办交互-譬喻外部函数挪用。
// arbitrary length iteration based on how many addresses participated
这里的另一个常见问题是在Oracle挪用中利用未加密的链下机要(譬喻API密钥)。假如可以确定您的API密钥,恶意行为者可以简朴地本身利用它或操作其他前言,譬喻用尽您答允的API挪用并强迫Oracle返回错误页面,这大概会或大概不会导致问题,详细取决于智能合约的布局。
    function transferTo(address payable dest, uint amount) external;
    function () payable {
此刻假如有人拐骗您将以太坊发送至TxAttackWallet智能合约地点,他们可以通过查抄tx.origin来查找发送生意业务的地点来窃取您的资金。
  uint a = 1;
    for(uint x; x < refundAddresses.length; x++) { 
}
假如利用时间戳来实验发生随机性,则矿工可以在区块验证后的15秒钟内宣布时间戳,从而使他们可以或许将时间戳配置为一个值,从而增加利用该成果的几率。
tx.origin是Solidity中的全局变量,它返回发送事务的地点。重要的是您切勿利用tx.origin举办授权,因为另一个智能合约可以利用回退函数来挪用您的智能合约并得到授权,因为授权地点存储在tx.origin中。 思量以下示例:
      i++;
2. 通过oracle的外部来历-譬喻Oraclize。
    uint256 amount = balances[msg.sender];
过期的编译器版本
struct Payee {
        refunds[msg.sender] = 0;
时间戳哄骗
由于内联汇编是从底层会见EVM的一种方法,因此它绕过了很多重要的安详成果。 因此,只有在须要且正确领略的环境下,才利用汇编措施。
pragma solidity >=0.5.0 <0.7.0;
单函数可重入(Single-function reentrancy)
尽量答允,但最好的做法是制止利用未利用的变量。 未利用的变量会导致一些差异的问题:
        require(tx.origin == owner);
在此示例中,黑客可以通过在fallout()函数中将余额配置为0之前具有回退函数挪用transfer()来转移已用资金来操作此智能合约。
}
}
如今有很多经纪人打赌条约依靠已往的哈希来提供RNG。在大大都环境下,这不是可骇的RNG来历,甚至可以表明256个区块后产生的哈希删除。可是到当时,他们中的很多人基础就没有下注。这将使或人可以对很多这些成果相似的智能合约下注,并以必然的功效作为所有人的赢家,在主持人仍未决的环境下查抄主持人的提交,而且假如倒霉,只需阻塞区块链,直到举办修剪即可,获得他们的赌注。
从Solidity 0.5.0开始,未初始化的存储指针不再是问题,因为与未初始化的存储指针的协定将不再编译。 话虽如此,相识在某些环境下应该利用哪些存储指针仍然很重要。
假如您利用初级挪用,请确保查抄返回值以处理惩罚大概的失败挪用。

}
康科迪亚大学(University of Concordia)认为,“先行是一种动作,在此进程中,用户可以从预先会见有关即将产生的生意业务和生意业务的特权市场信息中受益”,对市场中将来事件的相识会导致聚敛。
    }
另一种要领是预先计较智能合约的地点,并在陈设智能合约之前将以太坊发送到该地点。令人惊奇的是,这是大概实现的。
    mapping (bytes => bool) executed;
// INSECURE
      payees[i].addr.send(payees[i].value);
    balances[to] += amount;
contract TxUserWallet {
        highestBidder = msg.sender;
在以太
坊中,某些应用措施依赖于随机数的生成来保持公正。可是在以太坊中,随机数的生成很是坚苦,而且有一些陷阱值得思量。
可以将成果可见性指定为public,private,internal或external。重要的是要思量哪种可视性最适合您的智能合约函数。
无掩护的自毁指令
此刻,利用Solidity的现代版本,您可以利用Constructor要害字界说结构函数,从而有效弃用此裂痕。 因此,办理此问题的要领只是利用现代的Solidity编译器版本。
        innerContract.call(bytes4(keccak256(“execute(bytes)”)), _data);
状态变量默承认见性
    nextPayeeIndex = i;
为了防备签名重放进攻,智能合约应仅答允处理惩罚新的哈希。这样可以防备恶意用户多次重播另一个用户的签名。
有时候,用户不需要将以太坊发送到智能合约。不幸的是,在这种环境下,可以绕过智能合约回退函数并强行发送以太坊。
譬喻:
开拓人员凡是会明晰声明函数可见性,而声明变量可见性并不常见。状态变量可以具有三个可见性标识符之一:public,private或internal。幸运的是,变量的默承认见性是内部的,而不是public的,可是纵然您规划将变量声明为internal的,也必需明晰,因此对付谁可以会见该变量没有错误的假设。
    require(msg.sender.call.value(amount)());
为了防备进一步的进攻,我列出了险些所有已知的进攻和裂痕的列表。尽量此列表大概包括已知的进攻,但新的裂痕仍在按期发明,因此,这应该只是您作为工程师研究智能合约安详性的开始。
在智能合约中转移资金时,请利用发送或转移而不是挪用。利用挪用的问题与其他函数差异,它没有2300的限制。这意味着可以在外部函数挪用中利用该挪用,该函数可用于执行重入进攻。
跨函数重入进攻是同一进程的更巨大版本。当易受进攻的成果与进攻者可以操作的成果共享状态时,就会产生跨函数重入进攻。
在这种环境下,区块气限额大概是一个问题,即向一系列地点发送资金。纵然没有任何恶意,这也很容易堕落。仅仅是因为有太多的用户需要付费,就可以最大限度地超出气体的限额,并阻止生意业务的乐成。
contract Auction {
    function transferTo(address payable dest, uint amount) public {
存在未利用的变量
在以太坊区块链中,所有区块都有气体限制。气体限制的长处之一是,它可以防备进攻者建设无限的事务轮回,可是假如事务的气体利用量高出此限制,则事务将失败。 这大概以几种差异的方法导致DoS进攻。
    address owner;
办理此问题的有效要领是在当前的推付式付出系统上利用预付式付出系统。 为此,请将每笔付款分本钱身的生意业务,然后让收款人挪用该成果。
当您高出最大值(溢出)或低于最小值(下溢)时,大概会产生溢出和下溢错误。当您高出最大值时,您将返回到零,而当您低于最小值时,它将使您返回到最大值。
    function somethingBad() {
}
缺少针对签名重放进攻的掩护
}
    constructor() public {
    address addr;
· 在哈希中包罗条约的地点,以确保动静仅在单个条约中利用。
            refunds[highestBidder] += highestBid; // record the refund that this user can claim
// Refund the old leader, if it fails then revert
// THIS CONTRACT CONTAINS A BUG – DO NOT USE
防备可重入进攻
contract auction {
// INSECURE
整数上溢和下溢
    uint highestBid;
function transfer(address to, uint amount) external {
        dest.transfer(amount);
前端进攻在金融市场恒久以来一直是一个问题,由于的透明性,这个问题在市场再次呈现。
譬喻彩票应用可以利用区块时间戳来选择组中的随机投标人。矿工可以进入彩票,然后将时间戳修改为一个值,使他们有更大的几率赢得彩票。
担任顺序不正确
违反条例
第一种要领是在以“易受进攻的条约”地点配置为受益人的条约上挪用“selfdestruct”要领。 这是可行的,因为selfdestruct不会触发回退函数。
contract Executor {
DoS(拒绝处事)进攻大概产生在函数中,当您实验向用户发送资金时,该函数依赖于该资金转移是否乐成。
    function withdrawRefund() external {

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

相关文章阅读