측정에 대한 포괄적 인 가이드 스마트 계약 보안.

블록 체인의 부상은 분산 된 합의를위한 독특한 기회를 제공하지만, 스마트 계약 애플리케이션에는 역사적으로 악명 높은 사람과 같이 수백만 달러의 손실을 초래 한 고유 한 보안 문제가 있습니다. DAO 공격. 이러한 위험을 완화하려면 다음을 수행해야합니다. 보안 감사 스마트 계약에. 이 가이드에서는 다양한 스마트 계약 공격과 보안을 보장하기 위해 수행해야하는 감사 프로세스를 최신 개발과 일치하고 신뢰할 수있는 다양한 출처에서 영감을받는 방식으로 자세히 설명합니다.. 

스마트 계약 감사는 코드가 공개적으로 배포되기 전에 보안 결함과 취약성을 찾기 위해 코드를 꼼꼼하게 조사하는 일반 코드 감사와 근본적으로 동일합니다. 대중에게 공개되기 전에 다리를 테스트하는 것과 같습니다. 두 경우 모두 건축업자는 제품의 보안과 안전에 대한 책임이 있습니다. 블록 체인은 본질적으로 복제 된 머클 트리의 추가 전용 링크 “목록”(즉, 변경 불가능)이고 스마트 계약은 자체 실행되므로 시작하기 전에 코드에서 취약점을 찾는 것이 중요합니다..

스마트 계약을 감사하는 방법

 어떤 종류의 스마트 계약 공격이 있습니까??

이 섹션에서는 알고 있어야하는 알려진 공격에 대해 설명하고 감사에서 이러한 공격을 찾기 위해 취할 수있는 특정 단계를 설명합니다..

경쟁 조건 의도 된 순서대로 이벤트가 발생하지 않는 일반적인 시스템 동작입니다. 스마트 계약에서 경쟁 조건은 제어 흐름을 인수하는 외부 계약을 호출 할 때 발생할 수 있습니다..

재진입 첫 번째 함수 호출이 완료되기 전에 일부 함수가 반복적으로 호출되는 경쟁 조건의 한 버전을 설명합니다. 예를 들어 DAO 공격 버그 중 하나는 의도하지 않은 방식으로 상호 작용하는 함수의 다른 호출로 인해 발생했습니다. 핵심 솔루션은 특정 기능, 특히 외부 호출을 면밀히 조사하여 동시 호출이 발생하지 않도록 차단하는 것입니다..

재진입 버그가있는 계약의 예 :

ReentrancyVulnerability 계약 {

function withdraw () {

단위 transferAmount = 10 에테르;

if (! msg.sender.call.value (transferAmount) ()) throw;

}

function deposit () payable {} // 계약을 지불 가능하게 만들고 ether를 보냅니다.

}

위에서 빨간색으로 강조 표시된 라인은 일반적으로 피해야하는 외부 통화입니다. withdraw () 함수는 10 개의 ether를 msg.sender로 전송합니다. 여태까지는 그런대로 잘됐다. 그러나 수신자는 아래와 같이 재귀 적 전송 익스플로잇으로 함수를 여러 번 호출 할 수 있습니다..

위의 계약이 ReentrancyVulnerability.sol 파일에 있고 공격자가 해커 계약이 포함 된 Hacker.sol 파일을 만들어 외부 호출을 악용한다고 가정 해 보겠습니다. 이러한 계약은 잠재적 인 재진입 취약점을 “펜 테스트”하는 데 사용될 수 있습니다.

contract Hacker {

ReentrancyVulnerability r;

uint 공개 카운트;

이벤트 LogFallback (uint c, uint balance);

function 공격자 (취약한 주소) {

r = ReentrancyVulnerability (vulnerable);

}

function attack () {

r.withdraw ();

}

function () payable {

count ++;

LogFallback (count, this.balance);

if (개수 < 10) {

r.withdraw ();

}

}

Hacker.sol에는 이름 변경 기능 외에 두 가지 기본 기능이 정의되어 있습니다. 첫 번째는 ReentrancyVulnerability contract withdraw () 메소드를 호출하는 payable () 인출 함수로, 해커에게 10 개의 이더를 보내고 두 번째 함수 인 function () payable {}을 트리거합니다. ).

이벤트 LogFallback (uint v, uint balance); 위에 정의 된 대체 함수가 호출 될 때마다 트리거되는 정의됩니다. 이 이벤트는 카운터가있는 if 문을 통해 실행되어 에테르 복귀를 방지하기 위해 10 번의 호출에서 함수를 중지하는 루프 역할을합니다. 마지막으로 해커의 withdraw () 메소드가 다시 호출됩니다. 이는 payable ()의 원래 withdraw () 방법이 완료되기 전에 if 문이 마지막으로 충족되고 카운터 조건이 충족 될 때까지 withdraw ()가 다시 호출되기 때문에 가능합니다..

재진입은 문제의 원인이 아니라 문제의 증상이므로 함수에서 직접 재진입을 중지하려고 시도하지 말고 외부 함수가 사용되는 위치를 분석해야합니다. 이것이 의미하는 바는 외부 함수를 호출하기 전에 모든 내부 작업을 완료하는 것입니다..

요약 : 외부 코드를 최소화하거나 외부 통화 전에 모든 내부 작업을 완료합니다..

교차 기능 경쟁 조건 동일한 솔루션으로 동일한 상태를 공유하는 두 기능의 유사한 공격을 설명합니다. 한 가지 예는 공격자가 사용자 잔액이 0으로 설정되기 전에 또는 공격자가 이미 인출을 받았음에도 불구하고 transfer ()를 외부에서 호출하는 경우입니다.

function transfer (address to, uint amount) {

여기에서 전송이 발생합니다.

}

function withdrawBalance () public {

uint amountToWithdraw = userBalances [msg.sender];

require (msg.sender.call.value (amountToWithdraw) ());

userBalances [msg.sender] = 0;

}

위 코드에서 해커는 withdrawBalance ()의 빨간색 선이 실행되거나 외부 호출이 이루어질 때 transfer ()를 호출 할 수 있습니다. 보시다시피 userBalance는 나중에 0으로 만 설정되므로 인출이 이루어 졌더라도 해커가 토큰을 전송할 수 있습니다..

트랜잭션 주문 의존성 (TOD) / 전면 실행 또 다른 경쟁 조건이지만 이번에는 블록 내 거래 주문에 대한 조작의 맥락에서 볼 수 있습니다. 이것은 짧은 시간 동안 mempool에있는 트랜잭션과 관련이 있습니다. Front Running은 한 사용자가 다른 사용자를 희생시키면서 조작 된 거래 주문으로부터 이익을 얻을 수 있도록합니다.

  • Front Running을 허용 할 수있는 한 가지 조건은 다음과 같습니다. 타임 스탬프 종속성, 따라서 특히 베팅 계약과 같이 거래 시간이 재정적으로 중요한 경우 타임 스탬프 사용을 면밀히 조사해야합니다. 이더 리움 타임 스탬프는 동기화 된 글로벌 시계에서 연결이 끊어지며이 불일치는 채굴자가 이용할 수 있습니다..
  • 또 다른 조건은 정수 오버플로 및 언더 플로, 그러면 최대 원에 도달하는 단위 값이 0으로 설정되거나 0보다 작은 단위 값이 최대 값으로 설정됩니다. 정수 오버플로 및 언더 플로는 다음과 같은 도구로 감지 할 수 있습니다. 미스릴.

        

오버플로 및 언더 플로에 대한 코드 예제는 매우 간단합니다.

uint public c = a + b;

공격자는 언더 플로를 빼거나 오버플로를 더할 수 있습니다.

function underflow () public {

c-= 2 ** 256-1;

}

function overflow () public {

c + = 2 ** 256-1;

}

또 다른 형태의 공격은 이더를 계약에 강제로 전송하여 계약에 대한 자금을 제한하려는 논리가 없는지 확인하는 기능으로 가능합니다..

다음 로직을 가진 코드는 위의 취약점입니다.

require (this.balance > 0); // 0은 임의의 숫자 일 수 있습니다.

분석중인 코드에서 이러한 공격이 성공적으로 실행되는 것을 방지하기 위해 감사 프로세스는 엔지니어링 접근 방식을 취해야합니다. 이론 및 실습에 대한 배경과 도구 응용 프로그램을 통한 엄격한 검증.

 완전한 스마트 계약 감사를위한 단계

위에서 알려진 공격을 가능하게하는 취약성과 기타 버그 및 보안 문제는 다음 감사 프로세스에서 발견됩니다. ConsenSys 모범 사례, 그만큼 HashEx 감사 프레임 워크, 보다 포괄적 인 구조를 만들기위한 공개 감사 :

     0. 배포 된 스마트 계약에 대한 감사가 완료되는지 확인합니다 2 : 귀하의  

           릴리스 후보 (RC) 또는 최종 Smart

           최종 사용자에게 가장 가까운 공개 릴리스 전 계약 단계

           생성물.

  1. 법적 고지 사항 제공 : 감사의 목적은 보증을 제공하는 것이 아니라 보안 원칙에 근거한 논의를 촉진하는 것입니다..

예 : “이 감사에 표시되는 정보는 일반적인 논의 목적으로 만 사용되며 개인 또는 법인에 법적 보안 보장을 제공하기위한 것이 아닙니다.”

  1. 당신이 누구인지 설명하십시오: 공간에서의 권한 또는 엄격한 분석을 수행 할 수있는 이유를 설명하고 강력한 감사를 통해 백업합니다..
  2. 감사 프로세스 설명: 감사중인 스마트 계약 및 사용할 프로세스를 보안 관점에서 설명합니다..
  3. 공격 취약성 테스트 수행: 위에 문서화 된 관련 공격이 계약에 대해 성공적으로 시작될 수 있는지 분석.
  4. 발견 된 세부 취약점 및 우려 사항:이 단계에서는 수정 제안과 함께 심각한 중간 및 낮은 심각도 취약성에 대해 논의합니다. 즉시 취약하지는 않지만 잠재적 인 문제가되는 영역이있을 수 있습니다.이 영역도 기록해 두십시오..
  5. 계약 복잡성 분석: 복잡성은 오류 가능성을 증가 시키므로 복잡한 계약 로직, 모듈화되지 않은 코드, 독점 도구 및 코드, 명확성보다는 성능을 기록해 두세요. 이들 중 어느 것도 반드시 위험 신호는 아니지만 가능한 한 피해야합니다..
  6. 실패 준비 분석: 버그 또는 취약점과 같은 실패시 계약은 어떻게 대응하나요? 계약이 일시 중지되고 위험에 처한 돈이 관리되는지 확인하십시오..
  7. 코드 통화 분석: 모든 라이브러리와 도구가 최신 버전으로 업데이트 되나요? 최신 도구 버전에는 취약성 패치가 함께 제공 될 수 있으므로 이전 버전을 사용하는 것은 불필요하고 쉽게 예방할 수있는 위험입니다..
  8. 재사용 코드와 중복 코드 분석: 이전에 배포되고 보안이 입증 된 계약의 중복 코드는 엄격한 분석이 필요하지 않습니다. 그러나 이전에 감사하지 않은 재사용 코드는 철저하게 조사해야하며 잘 테스트되고 이전에 배포 된 버전이있는 경우 사용해서는 안됩니다..
  9.  외부 통화 분석
  1. 외부 호출 후 상태 변경 방지? 외부 호출은 제어 흐름을 조작 할 수 있으므로 먼저 모든 내부 호출을 완료해야합니다..
  2. 신뢰할 수없는 계약 표시? 외부 계약은 코드 상호 작용이 잠재적으로 안전하지 않다는 것을 알리기 위해 명확하게 표시되어야합니다. 여기에는 발신자가 아닌 UntrustedSender와 같은 이름 지정 규칙이 포함됩니다..
  3. 외부 호출의 오류가 올바르게 처리됩니까?? 계약 호출은 예외가 발생하면 자동으로 throw를 전파하고이 가능성을 처리하지 않으면 (반환 값을 확인하여) 계약이 실패합니다..
  4. 외부 전화가 푸시보다 풀을 선호합니까?? 외부 통화 실패의 결과를 최소화하기 위해 외부 통화가 자체 거래로 격리되었는지 확인합니다..
  1.  초기 잔액 분석: 코드는 계약이 제로 잔액으로 시작될 것이라고 가정합니까? 계약 주소는 계약이 생성되기 전에 wei를받을 수 있으므로 초기 잔액 가정이 없어야합니다..
  2.  온 체인 데이터의 보안 분석: 특정 온 체인 데이터가 나타나는 시간이 계약 기능에 중요하지 않은지 확인합니다.이 데이터는 공개되어 있고 잘못된 순서는 한 당사자가 다른 당사자보다 유리할 수 있기 때문입니다 (예 : 가위 바위 보 게임)..
  3.  N 자 계약 분석: 참가자가 드롭하고 돌아 오지 않아도 괜찮습니까? 이 가능성을 고려해야합니다..
  4.  견고성 특정
  1. 불변성이 적용됩니까?? 실패한 어설 션은 어설 션 가드를 트리거합니다. assert ()는 assert (this.balance)와 같은 불변을 처리 할 때 사용해야합니다. >= totalSupply);
  2. 정수 나누기가 수행됨? 간단히 말해서 모든 정수 나눗셈은 Solidity에서 가장 가까운 정수로 내림합니다. 이것이 문제라면 대신 승수를 사용하십시오..
  3. Ether가 강제로 전송되면 어떻게 되나요?? ETH는 주소로 강제 전송 될 수 있으므로 계약 잔액을 확인하는 불변 코딩과 강제 ETH 동작이 코드에 미치는 영향을 확인합니다..
  4. tx.origin 임 익숙한? tx.origin은 사용자의 주소를 포함하고 있으므로 승인에 사용해서는 안됩니다. 따라서 다른 계약에서 계약을 호출하여 승인을받을 수 있습니다 (tx.origin을 사용하는 경우 대신 msg.sender ()를 사용하는 것이 좋습니다)..
  5. 타임 스탬프 의존성: 알려진 공격 섹션에서 논의 된 바와 같이, 이더 리움 타임 스탬프는 동기화 된 글로벌 시계에서 연결이 끊어지며,이 불일치는 채굴자가 이용할 수 있으므로 타임 스탬프 의존성을 최소화해야합니다..
  1.  다음 단계 제공: 발견 된 취약성에 대한 수정 사항을 제안하고 향후 단계를 진행합니다. 이것들이 고쳐 졌다면 계약은 메인 넷 사용에 안전할까요??

추가 감사 및 버그 예

여기에서 감사의 과거 예와 자체 스마트 계약 감사에 적용 할 수있는 코드 스 니펫의 통계를 확인할 수 있습니다. 스마트 계약 감사 영역에는 강점과 약점을 모두 포함하는 해설 중심에서 테스트 중심까지 다양한 프레임 워크를 사용하는 엔터티 수가 증가하고 있습니다..

‘unchecked-send’버그의 예를 들어 Hacking, Distributed 블로그에서 다음 코드 스 니펫을 제공합니다.

(gameHasEnded && !(prizePaidOut)) {

winner.send (1000); // 우승자에게 상품 보내기

PrizePaidOut = True;

}

감사 단계 섹션에서 논의한 바와 같이 send () 사용은 항상 신중하게 조사해야합니다. 이 경우 send () 메소드가 실패하여 게임 우승자가 지급되지 않을 수 있습니다. 잠재적으로 큰 자금이 위험에 처한 경매와 같은 사용 사례에 대해서도 유사한 취약점이 존재할 수 있습니다..

에 따라 이더 리움 문서, 이 실패가 발생할 수 있습니다 “호출 스택 깊이가 1024이면 (항상 호출자가 강제 할 수 있음) 수신자에게 가스가 부족해도 실패합니다.” 문서는 다음에 대한 솔루션을 제공합니다. “항상 송금의 반환 가치를 확인하거나 더 나은 방법 : 수취인이 돈을 인출하는 패턴을 사용하십시오.”

문서 제안에 따라 Hacking, Distributed는이 솔루션을 제공합니다.

(gameHasEnded && !(prizePaidOut)) {

계정 [수상자] + = 1000

계정 [패자] + = 10

PrizePaidOut = True;

}

function withdraw (amount) {

if (accounts [msg.sender] >= 금액) {

msg.sender.send (amount);

accounts [msg.sender]-= 금액;

}

}

… 전송 실패가 한 번에 한 당사자에게만 영향을 미치도록 코드가 리팩터링되는 방식.

ConsenSys 권장 사항 프레임 워크는 알려진 공격을 다루는 많은 ‘좋은 코드와 나쁜 코드’예제를 제공합니다..

pragma 견고성 ^ 0.4.4; // 나쁨

pragma 견고성 0.4.4; // 좋은

예를 들어, 프라그 마는 특정 컴파일러 버전에 고정되어야하며, 이는 발견되지 않은 버그의 위험이 더 큰 다른 버전을 사용하여 계약이 배포되는 것을 방지합니다..

uint256 상수 비공개 솔트 = block.timestamp; // 경고

또한 블록의 타임 스탬프에 대한 코드는 다음 타임 스탬프 사용을 면밀히 조사 할 수있는 플래그 여야합니다..

추천하는 다른 많은 예를 분석하는 것이 좋습니다. 합의현상금

보충 자료로 도구 감사

철저한 감사에는 사용자 행동에 의해 설명되는 문서 및 사용 사례와 함께 테스트가 포함될 수 있습니다. 이 경우 BDD (Behavior Driven Development) 관행을 사용해야합니다. 이는 개발의 스마트 계약 테스트 측면과 비슷하지만 기능보다는 보안에 중점을 둡니다..

이더 리움 스마트 계약 감사에 트러플을 사용하려면 표준 npm install -g 트러플을 사용하여 프레임 워크를 설치 한 다음 트러플 초기화를 사용하여 프로젝트 구조를 만듭니다 (이전에 획득했다고 가정). node.js).

이 프로세스는 테스트 조건을 확인하기 위해 계약 및 라이브러리를 가져온 후 테스트를 작성하고 테스트 네트워크에서 실행하는 데 중점을 둡니다. 일반적인 assert () 또는 다음과 같은 테스트 프레임 워크를 사용할 수 있습니다. 차이. 마지막으로 오버플로 및 언더 플로 확인, 함수 한계 테스트, 반환 값의 형식이 올바른지 확인하는 등 우리가 구축 한 단계를 테스트합니다..

스마트 계약을 중심으로하는 많은 분산 형 애플리케이션은 감사 관행을 지원하기 위해 다양한 소프트웨어 도구를 구현했습니다. 취약점에 대한 자동화 된 코드 검사와 같은 이러한 도구는 보완으로 사용될 수 있지만 공식 감사 프로세스를 대체해서는 안됩니다. 앞서 언급했듯이 한 가지 옵션은 미스릴, 단위 오버플로 및 언더 플로를 감지하는 데 사용할 수 있습니다. 또 다른 도구는 Etherscrape입니다. 여기 send ()를 사용할 때 재진입 버그에 대한 라이브 이더 리움 계약을 스크 레이 핑합니다. 또한 다음과 같은 분산 형 감사 플랫폼이 있습니다. 현상금 도구가 충분하지 않을 때 회사와 프리랜서 감사원을 모으는. 

다음 단계 제공

발견 된 취약성의 심각도에 따라 개선 할 계약의 특정 측면에 초점을 맞추도록 권장합니다. 또한 출시 전에 다른 버그 나 우려 사항을 찾는 효과적인 수단으로 버그 현상금 및 지속적인 침투 테스트를 권장 할 수 있습니다. 이더 리움 바운티 모델로.

코드 리팩토링으로 인해 새로운 취약점이 발생할 수 있으므로 계약에 새로운 추가 사항이 추가되면 감사되지 않은 상태가됩니다. 마지막으로 공개 또는 비공개 감사에서 질문에 대한 연락처를 만듭니다..

결론

이 가이드가 제공하는 감사 개요는 일반적으로 스마트 계약에 적용되지만 지금까지 가장 인기있는 이더 리움 계약에 맞춰져 있으므로 가장 많은 자금을 거래하여 공격 위험이 가장 높고 감사가 가장 필요합니다..

이제 스마트 계약 감사를 수행 할 수있는 도구, 리소스 및 노하우가 있으므로 블록 체인 공간의 보안과 신뢰성을 향상 시키십시오. 스마트 계약 감사에 관심이 있거나 스마트 계약 감사가 필요한 경우 체크 아웃 Bountyone.io

추가 읽기

블록 체인 기술은 여전히 ​​떠오르고 빠르게 성장하는 분야이므로 모든 것을 포괄하는 솔루션에 대한 리소스가 없기 때문에이 가이드에 대한 이해를 높이기 위해 다양한 소스를 권장합니다..

01. “스마트 계약 보안 모범 사례” 으로 합의

02. “GitHub가 아닌 배포 된 스마트 계약을 감사하십시오!” 으로 합의

03. “스마트 계약 감사를위한 궁극적 인 가이드 + Solidity에서 가장 위험한 공격”  작성자 : Merunas Grincalaitis

04. “스마트 계약 개발 : 스마트 계약 감사 모범 사례” 으로 스마트 함

05. “스마트 계약을위한 감사 및 보안 코딩의 중요성” 의 위에 ETH 뉴스

06. “이더 리움 스마트 계약 보안으로 진행” 으로 Zeppelin 솔루션

07. “EtherCamp의 Hacker Gold (HKG) 공개 코드 감사” 으로 Zeppelin 솔루션

08. 응고: 스마트 계약에 대한 전체 감사 서비스

09. SmartDec: 도구 기반 스마트 계약 보안 플랫폼

10. 하버드 혁신 연구소 감사 …에서 Experfy

11. Ethereum Classic Multisig 지갑에서 수행되는 보안 감사 으로 덱 사란

12. “ ‘Unchecked-Send’버그에 대한 라이브 이더 리움 계약 스캔” 으로 해킹, 분산

Mike Owergreen Administrator
Sorry! The Author has not filled his profile.
follow me