智能合约安全-parity多重签名钱包安全漏洞

 

漏洞原因:

    因为initWallet函数是公开函数( public function) , 攻击者调用initWallet,重新初始化钱包会把之前合约钱包所有者覆盖, 即可改变钱包所有者。 

漏洞代码:

  // constructor - just pass on the owner array to the multiowned and
  // the limit to daylimit
  function initWallet(address[] _owners, uint _required, uint _daylimit) {
    initDaylimit(_daylimit);
    initMultiowned(_owners, _required);
  }
 
  // constructor - stores initial daily limit and records the present day's index.
  function initDaylimit(uint _limit) {
    m_dailyLimit = _limit;
    m_lastDay = today();
  }
 
  // constructor is given number of sigs required to do protected "onlymanyowners" transactions
  // as well as the selection of addresses capable of confirming them.
  function initMultiowned(address[] _owners, uint _required) {
    m_numOwners = _owners.length + 1;
    m_owners[1] = uint(msg.sender);
    m_ownerIndex[uint(msg.sender)] = 1;
    for (uint i = 0; i < _owners.length; ++i)
    {
      m_owners[2 + i] = uint(_owners[i]);
      m_ownerIndex[uint(_owners[i])] = 2 + i;
    }
    m_required = _required;
  }

修复方法:

设置 initMultiowned 和 initDaylimit 禁止外部调用,给initWallet添加only_uninitialized函数修改器,确保initWallt只被调用一次。

安全修复代码:

  // throw unless the contract is not yet initialized.
  modifier only_uninitialized { if (m_numOwners > 0) throw; _; }

  // constructor - just pass on the owner array to the multiowned and
  // the limit to daylimit
  function initWallet(address[] _owners, uint _required, uint _daylimit) only_uninitialized {
    initDaylimit(_daylimit);
    initMultiowned(_owners, _required);
  }

  // constructor - stores initial daily limit and records the present day's index.
  function initDaylimit(uint _limit) internal {
    m_dailyLimit = _limit;
    m_lastDay = today();
  }

  // constructor is given number of sigs required to do protected "onlymanyowners" transactions
  // as well as the selection of addresses capable of confirming them.
  function initMultiowned(address[] _owners, uint _required) internal {
    m_numOwners = _owners.length + 1;
    m_owners[1] = uint(msg.sender);
    m_ownerIndex[uint(msg.sender)] = 1;
    for (uint i = 0; i < _owners.length; ++i)
    {
      m_owners[2 + i] = uint(_owners[i]);
      m_ownerIndex[uint(_owners[i])] = 2 + i;
    }
    m_required = _required;
  }  

POC

web3.eth.contract(MultiSigParityAbit).at(Vulnerable_Address).initWallet.getData([YOUR_ADDRESS], 1,2000000000000000000)

POC未测试,待测。

 

 REF:http://shellcode.se/programming/simple-mistake-leads-to-30m-usd-theft/

posted @ 2017-07-20 10:22 小小leo 阅读(...) 评论(...) 编辑 收藏