EOS 스마트 계약 보안에 대한 궁극적 인 가이드. 2018 년 6 월 세계 최대 ICO 인 EOS가 출시되었을 때 암호 화폐 커뮤니티는 회의적이었습니다. 소프트웨어 버그. 그러나 4 개월을 빨리 감 으면 현재 EOS는 거래를 두 배로 늘리다 이더 리움이 오늘하는 일입니다. 무료 및 빠른 거래 약속을 통해 EOS의 최상위 Dapp은 이더 리움의 최상위 Dapp 2,000 개에 비해 일일 활성 사용자가 약 13,000 명에 이릅니다..

EOS 스마트 계약 보안

작성자 : Rohan Agarwal

일부 일반적인 스마트 계약 취약성은 거의 모든 플랫폼에 적용됩니다. Ethereum과 마찬가지로 EOS로 작성된 스마트 계약은 메인 넷에 게시되기 전에 감사를 받아야합니다. 계약이 충분히 검증되지 않은 경우 계약의 치명적인 버그가 악용 될 수 있습니다. 이 가이드에서는 EOS에서 차세대 킬러 dApp을 만들기위한 일반적인 함정을 피할 수 있도록 도와드립니다..

가이드를 읽기 전에 가이드를 읽는 동안 도움이 될 EOS 개발과 관련된 몇 가지 전제 조건 정보를 아는 것이 중요합니다. C ++에 대한 지식은 필수입니다. 스마트 계약 개발을 시작하기에 가장 좋은 곳은 EOSIO 자체입니다. 선적 서류 비치

ABI 디스패처 처리

통근자 "씨" {

void apply (uint64_t 수신기, uint64_t 코드, uint64_t 작업) {

class_name thiscontract (receiver);

if ((코드 == N (eosio.token)) && (액션 == N (전송))) {

execute_action (&이 계약, &class_name :: transfer);

반환;

}

if (code! = receiver) return;

스위치 (액션) {EOSIO_API (class_name, (action_1) (action_n))};

eosio_exit (0);

}

}

위 이미지는 수정 된 ABI 디스패처의 샘플 코드입니다. 아래에 표시된 것처럼 더 간단한 ABI 디스패처는 계약의 더 간단한 작업 처리에 사용됩니다..

EOSIO_ABI (class_name, (action_1) (action_n));

ABI 디스패처 / 포워더를 사용하면 계약이 수신 eosio.token 전송 이벤트를 수신하고 스마트 계약과의 정상적인 상호 작용을 수신 할 수 있습니다. 비정상적이고 불법적 인 호출을 피하기 위해 각 키 작업과 코드를 요구 사항에 맞게 바인딩하는 것이 중요.

예를 들어 dApp에 발생한 해킹이 있습니다. EOSBet 카지노 ABI 전달 소스 코드의 버그로 인해.

if (코드 == self || 코드 == N (eosio.token)) {

TYPE thiscontract (self);

스위치 (액션) {

EOSIO_API (TYPE, MEMBERS)

}

}

ABI 포워딩 소스 코드의 적용 액션 핸들러에서 위의 확인을 통해 공격자는 eosio.token :: transfer () 함수를 완전히 우회하고 EOS를 컨트랙트에 전송하지 않고 직접 컨트랙트 :: transfer () 함수를 호출 할 수 있습니다. 내기. 손실에 대해 그는 아무것도받지 못했지만 아무것도 잃지 않았습니다. 그러나 승리를 위해 그는 계약에서 실제 EOS를 지급 받았습니다..

계약에 들어오는 작업 요청 전에 eosio.token 계약 이전 작업 확인을 추가하여 위의 버그를 수정했습니다..

if (코드 == self || 코드 == N (eosio.token)) {

if (액션 == N (전송)) {

eosio_assert (코드 == N (eosio.token), "EOS를 전송해야합니다");

}

TYPE thiscontract (self);

스위치 (액션) {

EOSIO_API (TYPE, MEMBERS)

}

}

require_auth (account) 문을 사용하는 것이 중요합니다. 인증 된 계정 만 실행하려는 작업으로. require_auth (_self); 계약 소유자 만 거래에 서명하도록 승인하는 데 사용됩니다.

행동 승인

void token :: transfer (account_name from, account_name to, asset quantity)

{

자동 sym = 수량 .symbol.name ();

require_recipient (from);

require_recipient (~);

자동 지불 자 = has_auth (to)? 누구에게 누구로부터;

sub_balance (에서, 수량);

add_balance (to, quantity, payer);

}

위의 샘플 코드를 사용하면 누구나 작업을 호출 할 수 있습니다. 이를 해결하려면 require_auth (from); 지급인이 조치를 요청하도록 승인하는 진술.

eosio.token 계약 수정을 피하십시오

최근 화이트 햇 해커가 10 억 토큰을 요구하다 eosio.token 계약에서 제대로 테스트되지 않은 메서드 호출로 인해 dapp의. Dapp Se7ens (현재 비활성 상태) eosio.token 계약 내에서 토큰을 사용자 계정으로 에어 드롭하기위한 새로운 방법을 선언했습니다. 계약은 변경 사항을 반영하기 위해 eosio.token 계약의 문제 또는 이전 작업을 호출하지 않았으므로 자금이 사용자의 계정에 마술처럼 나타났습니다. 둘째, 해커가 프로세스에서 10 억 개의 토큰을 청구 할 수 있도록 이전하기 전에 방법에서 금액을 확인하는 것을 잊었습니다..

최대 공급량 및 토큰 기호를 변경하는 것 외에도 eosio.token 계약의 버그가 치명적일 수 있으므로 사용자 지정 기능에 대한 수정을 피하는 것이 좋습니다. 안전하게 에어 드랍을 용이하게하기 위해 에어 드랍 토큰을 별도의 계정으로 이체하고 그곳에서 분배하십시오.

다중 인덱스 테이블 속성 수정

EOS는 현재 작업 간 공유를 위해 공유 메모리 데이터베이스에 데이터를 저장합니다..

struct [[eosio :: table]] person {

account_name 키;

std :: string first_name;

std :: string last_name;

std :: string street;

std :: string city;

std :: string 상태;

uint64_t primary_key () const {return key; }

};

typedef eosio :: multi_index<N (사람), 사람> address_index;

위의 샘플 코드는 struct person을 사용하여 해당 테이블의 단일 행 데이터 구조를 기반으로하는 people이라는 이름의 multi_index 테이블을 생성합니다. 현재 EOS 수정을 허용하지 않습니다 일단 배포되면 테이블 속성의. eosio_assert_message 어설 션 실패가 발생하는 오류입니다. 따라서 테이블을 배포하기 전에 속성을 완전히 고려해야합니다. 그렇지 않으면 다른 이름의 새 테이블을 만들어야하며 이전 테이블에서 새 테이블로 마이그레이션 할 때 각별한주의가 필요합니다. 그렇지 않으면 데이터가 손실 될 수 있습니다..

숫자 오버플로 확인

산술 연산을 수행 할 때 경계 조건을 충분히 책임감있게 확인하지 않으면 값이 오버플로되어 사용자 자산이 손실 될 수 있습니다..

void transfer (symbol_name symbol, account_name from, account_names to, uint64_t balance) {

require_auth (from);

계정 fromaccount;

eosio_assert (is_balance_within_range (잔액), "잘못된 잔액");

eosio_assert (균형 > 0, "양수 잔액을 이전해야합니다."); uint64_t 금액 = 잔액 * 4; // 곱셈 오버플로

}

위의 샘플 코드에서 uint64_t 사용자 잔액을 나타 내기 위해 값이 곱해지면 오버플로가 발생할 수 있습니다. 따라서 사용하지 마십시오 uint64_t 잔액을 표시하고 가능한 한 산술 연산을 수행합니다. 오버플로 조건을 처리하는 정확한 균형보다는 운영을 위해 eosiolib에 정의 된 자산 구조를 사용합니다..

계약의 가정 처리

계약을 실행하는 동안 주장이 필요한 가정이있을 것입니다. eosio_assert를 사용하면 사전에 조건을 처리하고 어설 션이 실패 할 경우 특정 작업의 실행을 중지합니다. 예로서 –

void assert_roll_under (const uint8_t& roll_under) {

eosio_assert (롤 언더 >= 2 && 롤 언더 <= 96,

"롤 언더 오버플로, 2보다 크고 96보다 작아야합니다.");

}

위의 assert 문은 roll_under integer가 2보다 크다고 가정합니다. & 96 미만입니다. 그러나 그렇지 않으면 위의 메시지를 던지고 실행을 중지합니다. 위와 같은 코너 케이스를 발견하지 못하면 규칙을 설정하는 집에 재앙이 될 수 있습니다..

진정한 난수 생성

EOS 블록 체인에서 진정한 난수를 생성하는 것은 정확하게 수행되지 않으면 여전히 위험합니다. 그렇게하지 않으면 공격자가 결과를 예측하고 그 과정에서 전체 시스템을 조작하게됩니다. 같은 서비스 Oracalize.it 외부 소스에서 난수를 제공하기 위해 존재하지만 비용이 많이 들고 단일 실패 지점이 있습니다. 사람들은 과거에 블록 체인의 상황 변수 (블록 번호, 블록 스탬프 등)를 사용하여 이더 리움 스마트 계약에서 난수를 생성했지만 전에 게임. 생성을 올바르게 수행하려면 프로그램은 단일 당사자가 단독으로 제어 할 수없는 일종의 결합 된 임의성을 제공해야합니다. 현재 가능한 가장 좋은 방법 중 하나는 두 당사자간에 난수를 생성 할 때 Dan Larimar 자신이 제안한 방법입니다..

BountyOne 블로그 : EOS 스마트 계약 보안

문자열 sha256_to_hex (const checksum256& sha256) {

return to_hex ((char *) sha256.hash, sizeof (sha256.hash));

}

문자열 sha1_to_hex (const checksum160& sha1) {

return to_hex ((char *) sha1.hash, sizeof (sha1.hash));

}

주형 <클래스 T>

인라인 무효 hash_combine (std :: size_t& 시드, const T& V) {

std :: hash<티> 해셔;

시드 ^ = hasher (v) + 0x9e3779b9 + (시드 << 6) + (씨앗 >> 2);

}

위의 샘플 코드는 1에서 100 사이의 최적화 된 난수 생성을 제공합니다. seed1은 하우스 시드이고 seed2는 위의 사용자 시드입니다. 참고로, DappubEOSBetCasino 플레이어와 집 (개발자) 사이에 공정한 주사위 게임의 난수 생성기를 구현하여 완전한 계약을 오픈 소스했습니다..

uint8_t compute_random_roll (const checksum256& seed1, const 체크섬 160& seed2) {

size_t 해시 = 0;

hash_combine (hash, sha256_to_hex (seed1));

hash_combine (hash, sha1_to_hex (seed2));

반환 해시 % 100 + 1;

}

EOSBet은 최근에 다시 해킹 공격자가 자신의 지갑간에 거래 할 때마다 자신의 지갑으로 EOS를 보내기 위해 eosio.token 계약을 속일 때 65,000 EOS의. eosio.token 계약 코드 통지 수신 토큰이있는 EOS 토큰의 발신자와 수신자 모두. 행동을 모방하기 위해 & 해킹을 용이하게하고, 공격자는 두 개의 계정을 만들었습니다. & B. A는 require_recipient (N (eosbetdice11)) 문이있는 작업과 스마트 계약을 맺었습니다. A가 액션 콜을 통해 A에서 B 로의 거래를 촉진했을 때 전달 함수 eosio.token 계약에서 호출 된 것처럼 계약에서. EOS가 계약에 실제로 이전되지 않았기 때문에 해커가 베팅을 잃을 때마다 아무것도 잃지 않았지만 베팅에서 이기면 보상을 받았습니다. 따라서 계약 이름과 작업 이름 만 확인하는 것만으로는 충분하지 않습니다..

계약 통지 확인

문제를 완화하기 위해 함수는 계약이 실제로 토큰의 수신자인지 여부를 확인해야합니다..

eosio_assert (transfer_data.from == _self || transfer_data.to == _self, "수신 또는 발신 전송이어야합니다.");

EOS에서 스마트 계약을 개발하는 동안 따라야 할 모범 사례는 무엇입니까??

버그는 모든 소프트웨어에서 불가피한 부분입니다. 그 결과는 특히 가치 거래와 관련된 경우 분산 된 환경에서 증폭됩니다. 위에서 논의한 EOS 특정 보호 장치와는 별도로 새로운 스마트 계약 개발자가 염두에 두어야 할 일반적인 예방 조치 및 모범 사례는 다음과 같습니다.

  1. 항상 심사 메인 넷에 공개하기 전에 타사 스마트 계약 감사 회사와 독립적으로 계약.
  2. 테스트 넷에 릴리스하기 전에 계약의 필요한 Caveman 디버깅 (현재 계약을 디버그하는 유일한 방법)을 수행하십시오. EOSIO 문서에는 훌륭한 가이드 그것을 위해.
  3. 메인 넷 출시 초기에 과도한 손실을 방지하기 위해 인출 제한 전송률을 설정합니다. 화이트 햇 해커의 책임있는 공개를위한 버그 바운티 프로그램 보유.
  4. 버그가 감지되면 킬 스위치를 사용하여 계약을 동결하십시오..

이를 구현하기 위해 multi_index 테이블에 플래그를 유지합니다. 계약 소유자 만 호출 할 수있는 작업을 사용하여 플래그를 설정합니다. 그런 다음 플래그가 고정되어 있는지 여부를 모든 공개 조치를 확인합니다. 함수의 샘플 구현은 다음과 같습니다..

struct st_frozen {

uint64_t 고정;

};

typedef 싱글 톤<N (고정), st_frozen> tb_frozen;

tb_frozen _frozen;

uint64_t getFreezeFlag () {

st_frozen frozen_st {.frozen = 0};

return _frozen.get_or_create (_self, frozen_st);

}

무효 setFreezeFlag (const uint64_t& pFrozen) {

st_frozen frozen_st = getFreezeFlag ();

frozen_st.frozen = pFrozen;

_frozen.set (frozen_st, _self);

}

// 공개 행동

void freeze () {

require_auth (_self);

setFreezeFlag (1);

}

// 공개 행동

void unfreeze () {

require_auth (_self);

setFreezeFlag (0);

}

// 모든 공개 활동

void action (…) {

eosio_assert (getFreezeFlag (). frozen == 1, "계약이 동결 됨!");

}

  1. 라이브러리의 보안 향상 또는 플랫폼의 취약성 공개에 대한 업데이트를 유지하십시오. 필요한 경우 즉시 라이브러리 업데이트.
  2. 최소한 계약 코드를 오픈 소스하여 게임에서 공정성이 유지되고 인디 개발자가 버그를 훨씬 빠르게 발견 할 수 있습니다..

EOS 스마트 계약 보안 : 결론

EOS가 출시 된 지 불과 5 개월이 지났지 만 예상보다 훨씬 더 성장했습니다. 그것이 만든 트레이드 오프 – DPOS, 가변 스마트 계약, 21 개의 마이닝 노드 등은 확실히 탈 중앙화 최대화 주의자들로부터 심한 비판을 받았습니다. 그럼에도 불구하고 현재 플랫폼이 제공하는 확장 성을 고려할 때 Ethereum 기반 dApps를 EOS로 전환하는 것은 중단되지 않았습니다. 전쟁에서이기는 것이 EOS인지 Ethereum인지는 아직 결정되지 않았지만 EOS는 확실히 전투에서 승리했습니다. 그리고 Ethereum이 “The World Computer”를 실행하는 데 필요한 확장성에 도달 할 때까지 동일하게 유지 될 것입니다..

_________________________________________________________________________________________

이 기사는 Rohan Agarwal에 의해 작성되었습니다.

Bio – #Android Dev # Entrepreneur # Blockchain Dev & 연구원 공동 창립자 @ Cypherock.com – 스마트 폰용 보안 하드웨어 지갑.

Linkedin – https://www.linkedin.com/in/rohanagarwal94/

Github – https://github.com/rohanagarwal94

트위터 – https://twitter.com/rohanagarwal94

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