漏洞原因:
因为initWallet函数是公开函数( public function) , 攻击者调用initWallet,重新初始化钱包会把之前合约钱包所有者覆盖, 即可改变钱包所有者。
漏洞代码:
// constructor - just pass on the owner array to the multiowned and// the limit to daylimitfunction initWallet(address[] _owners, uint _required, uint _daylimit) {initDaylimit(_daylimit);initMultiowned(_owners, _required);}// constructor - stores initial daily limit and records the present day&#39;s index.function initDaylimit(uint _limit) {m_dailyLimit &#61; _limit;m_lastDay &#61; 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 &#61; _owners.length &#43; 1;m_owners[1] &#61; uint(msg.sender);m_ownerIndex[uint(msg.sender)] &#61; 1;for (uint i &#61; 0; i <_owners.length; &#43;&#43;i){m_owners[2 &#43; i] &#61; uint(_owners[i]);m_ownerIndex[uint(_owners[i])] &#61; 2 &#43; i;}m_required &#61; _required;}
修复方法&#xff1a;
设置 initMultiowned 和 initDaylimit 禁止外部调用&#xff0c;给initWallet添加only_uninitialized函数修改器&#xff0c;确保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 daylimitfunction initWallet(address[] _owners, uint _required, uint _daylimit) only_uninitialized {initDaylimit(_daylimit);initMultiowned(_owners, _required);}// constructor - stores initial daily limit and records the present day&#39;s index.function initDaylimit(uint _limit) internal {m_dailyLimit &#61; _limit;m_lastDay &#61; 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 &#61; _owners.length &#43; 1;m_owners[1] &#61; uint(msg.sender);m_ownerIndex[uint(msg.sender)] &#61; 1;for (uint i &#61; 0; i <_owners.length; &#43;&#43;i){m_owners[2 &#43; i] &#61; uint(_owners[i]);m_ownerIndex[uint(_owners[i])] &#61; 2 &#43; i;}m_required &#61; _required;}
POC
web3.eth.contract(MultiSigParityAbit).at(Vulnerable_Address).initWallet.getData([YOUR_ADDRESS], 1,2000000000000000000)
POC未测试&#xff0c;待测。
REF:http://shellcode.se/programming/simple-mistake-leads-to-30m-usd-theft/