4th Street Bar Hive-Bar

Hive-Bar Powered by Hive beta-fdb5b5b

Community post

이더 15만개는 어떻게 털렸을까? parity 다중서명 지갑(계약) 취약점 살펴보기

hacked_4.png

이더 15만개는 어떻게 털렸을까?

시간이 좀 지난 이슈이고 일단락 된듯하지만 다시한번 알아보고
ICO 지갑이 탈탈 털린 이유를 본격적으로 알아보자 제발 납득좀가게 알아보자.

예상독자 : 이더리움 스마트 컨트렉에 관심있는 프로그래머 , 이더리움에 관심있는 일반인, 해킹에 피해를 입은 당사자.

용어 알아보기

  1. 패리티 (Parity)
    • 이더리움 클라이언트이자 지갑역할을 하는 소프트웨어
    • 가장 널리 사용되는 이더리움 클라이언트는 Geth, 지갑은 Mist
      (Mist는 이더리움 네트워크와 연결되기 위하여 Geth 클라이언트를 사용한다)
  2. 스마트 컨트렉트 (Smart Contract)
    • 프로그래밍을 통해 만들어진 자동화된 계약
    • 이더리움 기반 ICO의 경우 해당 스마트 컨트렉트에 입금되었을때 해당 컨트렉트에 "프로그래밍 되어진 계약" 에 의해 자동으로 토큰을 발급해 주는 형식
  3. 취약점
    • 프로그램 혹은 시스템에서 발견되는 보안적인 헛점
  4. ICO (Initial Coin Offering)
    • 개발/마케팅 자금을 확보하기 위해 초기에 크라우드펀딩을 통해 토큰을 나눠주는것
    • IPO와 CrowdFunding 그 중간 어딘가..

사건 요약

"대량의 이더 (약 15만개) 가 해커의 지갑 주소로 탈취된 사건"

  • Edgeless, Swarm City, æternity 등의 ICO 지갑이 해킹당함
  • 일반적인 개인 지갑은 피해가 없었음
  • 당시 그리고 지금 이더리움 블록체인 네트워크 자체는 보안문제가 발생하지 않았음

코드 살펴보기

Jackie-Chan-WTF-Meme.png
도대체 왜 이런일이 일어나 우리에게 시련을주시고 혼란을 일으키는 것인가.
이것을 알기위해 스마트 컨트렉 코드를 살펴볼 것 입니다.

본 포스팅에 필요한 부분만을 요약하고 잘라내었기 때문에 전체 소스코드는 아닙니다.

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);
  }
}

.
swrdc.jpg

이것만 보았는데 도 불구하고 아무래도 프로그래밍에 대한 지식이 전무하거나 영어 울렁증이 심하다면 혼란스러울 수 있다. 그러니까 아주 아작.. 아니 조각 조각을 내어 엑기스만 살펴보자

function() payable 이 함수는 fallback 함수이다 fallback 함수는 컨트렉이 호출되었을때 해당 컨트렉에 매칭 되는 명령(함수) 가 없을때 기본적으로 호출되는 함수를 말하는데.

여기서 프로그래밍에 대한 지식이 없는 분들을 위하여 첨언을 하자면 함수는 입력을 받아 결과를 계산, 실행 하는것을 말한다. 프로그램은 수많은 함수들의 집합이라고 볼 수 있다.

function() payable 함수는 내부에서_walletLibrary.delegatecall(msg.data); 을 호출 (실행) 하는데 간단히 말하자면 "스마트 컨트렉 코드에 매칭되는 함수가 없으면 walletLibrary 에서 매칭되는 함수를 찾아서 호출한다." 라는 코드입니다. 그리고 이것 자체로는 문제가 없습니다. 하지만 문제가 있으니까 털렷겠죠?

계속해서 walletLibrary 를 살펴봅시다.

contract WalletLibrary is WalletEvents {
  function initDaylimit(uint _limit) {
    m_dailyLimit = _limit;
    m_lastDay = today();
  }
  function initMultiowned(address[] _owners, uint _required) {
    ...
  }
  function initWallet(address[] _owners, uint _required, uint _daylimit) {
    initDaylimit(_daylimit);
    initMultiowned(_owners, _required);
  }
}

initWallet initDaylimit initMultiowned 3가지 함수가 보이는데요 함수명만 번역해도 대략적인 기능을 유추해 볼 수 있습니다.

  • initWallet : 지갑을 초기화 한다
  • initDaylimit : 하루 출금제한 설정
  • initMultiowned : 지갑의 권한을 가지는 주인을 설정한다.

스크린샷 2017-08-01 오전 8.05.59.png

네 이 함수가 public으로 되어있었습니다. 외부에서 접근이 가능했다 라는것이죠. 여기서 말하는 외부는 라이브러리 밖 즉 라이브러리를 사용하는 스마트 컨트렉을 말합니다. 그런데 이 스마트 컨트렉이 function() payable 함수를 walletLibrary 와 연결해놓았죠?

그렇습니다. 컨트렉의 주인이 아닌 사람도 누구나! 아무나! initWallet 을 호출 할 수 있는 상태였습니다. 즉 주인을 바꿔버릴 수 있었던거죠

취약점 패치

스크린샷 2017-07-31 오후 9.01.04.png

취약점 패치는 정말 간단하게 되었습니다. 이함수를 internal 즉 내부 에서만 접근할 수 있게 바꿔 버리고 initWallet 함수는 only uninitialized 즉 컨트렉이 초기화 되어 있지 않은 상태에서만 호출이 가능하도록 변경 되었습니다.

생각해볼 부분

  1. Dao 해킹사태와는 무엇이 다른가.
  2. 이런일이 더이상 안 일어 나도록 하기위해서는 어떤 조치가 필요할 까.

본 포스팅은 얼만전에 발표했던 자료를 재 구성, 보충 한 것 입니다.
아래에서 슬라이드를 보실 수 있습니다.

https://slides.com/ironpark/parity-smart-contrect

저는.

프로그래밍, 인공지능, 보안, 암호화폐에 관심이 많습니다.
다양한 글을 생산하고 있으니 관심있으시면 팔로우 부탁드립니다 :)

또한 본 포스팅이 도움이 되셨다면 Vote! 다른 사람에게도 보여주고 싶다면 ReSteem! 을 해주세요
글쓴이에게 많은 도움이 됩니다.

이전글 보러가기 > 암호화폐 트레이딩 플랫폼 CoinEX 개발일지.1

23 upvotes $2.90

Replies (9)

Review before signing

Posting as . Signing with . Keychain permission: Posting. Hive Keychain will ask you to approve this action next.


  
Technical details

Operation fingerprint: