용어 알아보기
ICO 해킹사태
도대체 왜?
WHY??!?
WHY??!?
WHY??!?
대체 해킹이 발생한 이유는 무엇이며.
최초 원인 제공은 누구인가.
원인과 진행
코드 살펴보기
contract Wallet is WalletEvents {
address _walletLibrary;
function Wallet(address[] _owners, uint _required, uint _daylimit) {
bytes4 sig = bytes4(sha3("initWallet(address[],uint256,uint256)"));
address target = _walletLibrary;
assembly {
delegatecall(sub(gas, 10000), target, 0x0, add(argsize, 0x4), 0x0, 0x0)
}
}
function() payable {
if (msg.value > 0)
Deposit(msg.sender, msg.value);
else if (msg.data.length > 0)
_walletLibrary.delegatecall(msg.data);
}
function getOwner(uint ownerIndex) constant returns (address) {
return address(m_owners[ownerIndex + 1]);
}
function hasConfirmed(bytes32 _operation, address _owner) external constant returns (bool) {
return _walletLibrary.delegatecall(msg.data);
}
function isOwner(address _addr) constant returns (bool) {
return _walletLibrary.delegatecall(msg.data);
}
}
fallback 함수란
다른 함수에 매칭 되지 않을 때 기본으로 호출되는 함수
walletLibrary에게 권한을 위임 하여 호출한다
이때 호출되는 라이브러리의 함수는
msg.data에 의하여 결정된다.
코드 살펴보기
contract WalletLibrary is WalletEvents {
function initDaylimit(uint _limit) {
m_dailyLimit = _limit;
m_lastDay = today();
}
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;
}
function initWallet(address[] _owners, uint _required, uint _daylimit) {
initDaylimit(_daylimit);
initMultiowned(_owners, _required);
}
}
하루 출금 제한을 바꿀 수 있고
지갑의 주인을 바꿀 수 있다
그런데 말입니다
이 함수가 Public 이라면요?
취약점 패치
함수를 internal 로 바꾸고
컨트렉트의 initialize는 한번만 가능하도록 바꾸기만 했을 뿐인데. 취약점이 패치되었다.