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

in #kr7 years ago

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

Sort:  

헐 저 소스가 실 사용되고 있던 부분이라면 애초에 보안이 취약했던 것 아닐까요? 가상화폐의 모든 소스들에대해 취약성부터 검증해야될듯하네요ㅠㅠ

일단 패리티에서 개발한 다중서명 지갑 코드를 사용한 경우에 모두 해당하는 문제가 있었습니다.
즉 OpenZeppelin 에서 만든 코드를 사용한 경우에서는 취약점이 없었습니다.

다만 패리티에서 말하기를 취약점 발생 당시 UI쪽 대규모 업데이트에 작은 컨트렉코드가 껴있는 상태였기 때문에 해당하는 코드리뷰가 제대로 이루어 지지 않았다는 발표가 있었습니다. 따라서 해당 부분에 대한 절차 개선을 하고 있다고 하였으며

솔리디티 언어 자체가 접근제어자가 명시되어 있지 않은경우 기본 public이기 때문에 해당 부분이 개선되어야 한다는 이야기도 있습니다.

보안이 중요한 시장인데 코드리뷰가 안된것은 매우 심각하다고 봅니다. 좋은정보들 감사합니다 고수의 향기가 물씬 나시는데요ㅎㅎ

그런데 말입니다ㅎㅎㅎ 퍼...블급이네요

퍼스트 블러드! ㅋㅋ :)

Congratulations @ironpark! You have completed some achievement on Steemit and have been rewarded with new badge(s) :

Award for the number of comments

Click on any badge to view your own Board of Honor on SteemitBoard.
For more information about SteemitBoard, click here

If you no longer want to receive notifications, reply to this comment with the word STOP

By upvoting this notification, you can help all Steemit users. Learn how here!

좋은 정보 공유해주셔서 감사합니다! 이런 문제가 있었군요, 앞으로 올려주시는 좋은 글 많이 읽어보겠습니다!


어려운 ICO 정보를 한 눈에!!
ICO REPORT 입니다.

좋은 글 감사합니다.^^

최근에 뉴비가 이더리움 수십만개를 날리는 사건이 또 일어나니 패리티에대한 신용도가 떨어지네요...

Coin Marketplace

STEEM 0.19
TRX 0.24
JST 0.037
BTC 96612.01
ETH 3387.37
USDT 1.00
SBD 3.05