Vulnerabilidades de EOS Blockchain no ZeroNights 2018

imagem

Este artigo examinará várias vulnerabilidades reais no blockchain EOS (um dos concorrentes da Ethereum) e como elas foram integradas ao concurso de nova geração de máquinas caça-níqueis seguras no ZeroNights 2018. Se você estiver interessado em saber como está a situação de segurança nesta rede blockchain, então seja bem-vindo sob cat.

Entrada


Tudo começou com o fato de que, recentemente, durante uma auditoria de contratos inteligentes de segurança Etherium, um de nossos amigos publicou um artigo sobre vulnerabilidades em contratos inteligentes na rede EOS. Isso nos interessou bastante e decidimos investigar as vulnerabilidades com mais detalhes.

Tudo isso levou à criação de um concurso para o ZeroNights 2018 chamado "bandido de um braço" com vulnerabilidades em um contrato inteligente.

Vamos começar olhando diretamente para a rede blockchain da EOS, como trabalhar com ela e como tudo está organizado dentro dela. Existem muitos artigos descrevendo a tecnologia na Internet, portanto, provavelmente não haverá detalhes técnicos, mas tentaremos transmitir o significado geral para que o usuário médio possa ter uma idéia elementar dos mecanismos de trabalho da blockchain EOS.

Descrição da tecnologia EOS


O EOS.io é uma blockchain de nova geração da Block.one , baseada no conceito de PoS ( Prova de participação ).

A partir da descrição dos próprios criadores da rede: “O EOS é um software de rede blockchain de código aberto gratuito que fornece aos desenvolvedores e empreendedores uma plataforma para criar, implantar e executar aplicativos descentralizados de alto desempenho (DAPP).”

Se, em poucas palavras, tentar explicar o conceito, será um trecho bem refletido do artigo da Wikipedia:
A idéia da prova de estaca (PoS) é resolver o problema da prova de trabalho (PoW) associada ao alto consumo de energia. Em vez do poder de computação dos participantes, a quantidade de criptomoedas que eles têm em suas contas é importante. Portanto, em vez de usar uma grande quantidade de eletricidade para resolver o problema do PoW, o participante do PoS possui uma porcentagem limitada de possíveis verificações de transação. O limite corresponde à quantidade de criptomoeda na conta do participante
A rede é completamente nova e o primeiro lançamento da rede principal (mainnet) ocorreu em 10 de junho de 2018. A principal criptomoeda é a EOS, e o principal portal para desenvolvedores é developers.eos.io

A blockchain EOS.io suporta aplicativos criados por usuários usando o código WebAssembly (WASM), um novo padrão da web com amplo suporte para grandes empresas como Google, Microsoft, Apple e outras.

No momento, o kit de ferramentas mais recente para criar aplicativos que compilam código no WASM é clang / llvm com seu compilador C / C ++.

Para melhor compatibilidade, os desenvolvedores recomendam o uso do EOSIO CDT (Contract Development Toolkit) - um conjunto de utilitários dos próprios desenvolvedores para um trabalho conveniente e correto na criação de contratos inteligentes.

O compilador eosiocpp anterior já está obsoleto e não é suportado, portanto, todos são aconselhados a atualizar para o novo EOSIO CDT 1.5 (no momento da escrita).

Ao contrário do éter


O conceito de Ether usa PoW (Prova de Trabalho), que exige cálculos caros e a recompensa é dada à primeira pessoa para resolver um problema matemático. Ou seja, aqueles que decidiram em paralelo, mas não tiveram tempo para decidir, desperdiçaram energia. Nesta situação, os mineradores estão lutando entre si por tecnologias e equipamentos mais avançados. Para gerar blocos mais rapidamente e, assim, ganhar.

Diferentemente do Ether, na rede EOS, o sistema escolherá o criador do novo bloco de acordo com o conceito de PoS, e isso é determinado pelo número de status pessoal - uma fração do número total de criptomoedas. Assim, quem tem mais fortuna tem mais chances de ser selecionado pelo sistema. Mas, diferentemente do PoW (éter), não há recompensa por gerar um novo bloco em princípio, e a renda dos mineradores é apenas a comissão das transações.

Conclusão - as criptomoedas baseadas em PoW podem ser 1000 vezes mais eficientes em termos de energia.

Desenvolvemos o ambiente de desenvolvimento


Então, parece que terminamos a teoria, nos voltamos para a prática. Mas, na prática, tudo parece muito mais interessante. Com a documentação no momento em que eles tentavam descobrir isso no verão e começar a fazer algo para o ZeroNights 2018, tudo estava muito ruim, e o portal principal de desenvolvimento estava com bugs, estava meio vazio e às vezes nem funcionava.

As redes de teste ainda não foram realmente lançadas, então tive que implantar meu nó. A propósito, ao contrário das opiniões na Internet, obtê-lo não foi tão difícil. Usando a documentação oficial, a lançamos a partir do docker developers.eos.io/eosio-nodeos/docs/docker-quickstart

Vamos falar sobre os principais utilitários, programas para trabalhar com o blockchain EOS, com os quais tive que lidar no momento do trabalho na competição:

  • Nós - de fato, o serviço do próprio nó EOSIO; Você pode configurar e configurar vários plugins, por exemplo, CORS, histórico e outros.
  • O Cleos é um utilitário de console para trabalhar com um nó, chamar métodos de contrato e interagir com uma carteira, chaves e acessos. A ferramenta mais comum ao trabalhar com EOS.
  • O Keosd é uma carteira de console ou, mais precisamente, um serviço de carteira, um armazenamento de chaves privadas.
  • Eosio.cdt - Contract Development Toolkit, o chamado conjunto de ferramentas de desenvolvedor para depuração e compilação de contratos, gerando arquivos ABI e muito mais.
  • Eos.js - biblioteca de API Javascript para trabalho conveniente com o nó e contratos via web, incorporados no site.
  • O Scatter é uma carteira de desktop para armazenamento seguro das chaves da sua conta. Existe uma biblioteca da Web scatter.js, que interage com a carteira da área de trabalho do Scatter nos soquetes da Web e, portanto, ajuda a trabalhar com aplicativos DAPP no navegador.

Uff! .. Sim, existem muitos programas, entendê-los também não é totalmente fácil. Uma descrição de tudo isso merece uma postagem separada e está além do escopo deste artigo. Mas vamos imaginar que instalamos um nó em nosso servidor e até aprendemos a usar métodos de contrato para chamar métodos de contrato, se tivéssemos um.

Sim, a coisa mais importante. Precisamos esboçar o próprio contrato inteligente. Vamos escrever em C ++ e, para fazer pelo menos algo sensato, eu tive que ler muita documentação.

Para entender os contratos, eles dão um exemplo de um contrato Hello em todos os lugares. O arquivo principal é hello.cpp e o contrato inteiro é descrito nele.

#include <eosiolib/eosio.hpp> using namespace eosio; class hello : public eosio::contract { public: using contract::contract; /// @abi action void hi( account_name user ) { print( "Hello, ", name{user} ); } }; EOSIO_ABI( hello, (hi) ) 

Se em poucas palavras tentar explicar, então aqui - tudo é simples . Carregamos a biblioteca eosio.hpp, criamos a classe hello (também conhecida como contrato) e herdamos o contrato da classe. Criamos o método void hi e inserimos a variável de usuário do tipo account_name nos parâmetros, é uint64_t. No método, imprima "Olá" e o nome que especificamos quando o método é chamado. A última linha em que o EOSIO_ABI está localizado é uma macro auxiliar que aceita nossa classe e métodos públicos dessa classe e também participa da formação do arquivo .abi, onde são indicados todos os métodos públicos do contrato.

Explorando vulnerabilidades


Portanto, na estrutura desse artigo , várias vulnerabilidades foram descritas - agora vamos considerá-las com mais detalhes.

Estouro Numérico - Estouro Numérico


Quando o contrato é chamado, o nó verifica o tipo do parâmetro e, se os dados que estamos tentando alimentá-lo não se ajustarem, o nó começará a xingar e essas atrocidades não serão perdidas. MAS! Se dentro do contrato houver algum tipo de algoritmo para alterar o número, a soma dos números ou, digamos, a multiplicação, o número já poderá ser alterado dentro do contrato. Isso significa que você pode especificar um número que o nó irá ignorar, mas multiplicar o contrato, e o número irá além do tipo de dados válido, o que levará ao estouro.

O que isso pode dar? Por exemplo, há uma verificação de algum tipo de parâmetro numérico, digamos int Número <0, e sabe-se que int é um número assinado e, se o número exceder, o sinal do número para valores grandes será alterado para negativo. Assim, a verificação será excedida. E aqui, é claro, tudo depende da criticidade dessa verificação.

Por exemplo, no mesmo artigo sobre vulnerabilidades, existe um caso real em que os invasores conseguiram influenciar o parâmetro de equilíbrio, enganando o sistema. Os comentários do código descrevem em mais detalhes o mecanismo de interação com o contrato:

 //      typedef struct acnts { account_name name0; account_name name1; account_name name2; account_name name3; } account_names; //     (   1 EOS) //  ,     , //      «» void batchtransfer( symbol_name symbol, account_name from, account_names to, uint64_t balance ){ //    require_auth(from); //    account fromaccount; //      require_recipient(from); require_recipient(to.name0); require_recipient(to.name1); require_recipient(to.name2); require_recipient(to.name3); // ,       . //   is_balance_within_range   ( eosio_assert(is_balance_within_range(balance), "invalid balance"); // ,      «» //  , «» 1111111111111111  0,     eosio_assert(balance > 0, "must transfer positive balance"); //   amount    4 //     ,  amount   int64_t amount = balance * 4; //     from,    int itr = db_find_i64(_self, symbol, N(table), from); // ,    eosio_assert(itr >= 0, "wrong name"); //    fromaccount   db_get_i64(itr, &fromaccount, (account)); // ,       // ,    0.1 EOS //    ,    amount eosio_assert(fromaccount.balance >= amount, "overdrawn balance"); //   sub_balance(symbol, from, amount); //    4  add_balance(symbol, to.name0, balance); add_balance(symbol, to.name1, balance); add_balance(symbol, to.name2, balance); add_balance(symbol, to.name3, balance); } 

O hacking provavelmente foi realizado da seguinte maneira. O invasor pré-criou 4 contas e chamou o método batchtransfer diretamente, algo como isto:

 cleos push action contractname batchtransfer \'{"symbol ":"EOS", "from":”attacker”, "to":{ “name0”:”acc0”, “name1”:”acc1”, “name2”:”acc2”, “name3”:”acc3”}, "balance":"111111111111111111 EOS"}' -p attacker@active 


imagem

Farei uma reserva imediatamente, isso é apenas uma suposição; exatamente como eles fizeram o hack - não sabemos e, se houver outras idéias sobre essa ou mais informações precisas, escreva nos comentários.

Verificação de autenticação


A falta de verificação do método do contrato require_auth () para autorização do usuário levará ao fato de que qualquer pessoa que não possua os direitos necessários pode usar os métodos privilegiados do contrato, por exemplo, retirando dinheiro do contrato.

Falta de verificação de chamada de método


Ao enviar dinheiro para um contrato (EOS), você pode indicar em uma macro especial o que acontecerá a seguir e o que fazer. Digamos, quando você recebe dinheiro, um determinado algoritmo será chamado, por exemplo, para iniciar a roleta ou algo mais, além de um cheque:

 if( code == self || code == N(eosio.token) || action == N(onerror) ) { \ TYPE thiscontract( self ); \ switch( action ) { \ EOSIO_API( TYPE, MEMBERS ) \ } } //    action == N(transfer) 

Nesta verificação, não há restrições quanto à chamada do método de transferência, e é por isso que você pode chamar o método de transferência diretamente, sem enviar dinheiro ao contrato. E isso significa iniciar o mecanismo com um ganho adicional, sem gastar um centavo.

Competição ZeroNights 2018


A ideia do concurso nasceu por conta própria: como tudo está conectado com jogos e três vulnerabilidades, portanto, faremos o jogo no mecanismo de contrato inteligente no blockchain EOS.io. O jogo deve ser o mais simples possível, mas interessante.

Caça-níqueis "bandido de um braço"! As pessoas que desejam dinheiro fácil sempre me surpreenderam - lembre-se, não há brindes no mundo, ou quase nenhum. Aqui, a propósito, está bem ali, ou melhor, aparecerá quando as vulnerabilidades forem usadas.

Frontend


Eles decidiram tornar os jogos front-end na moda, bonitos e tridimensionais. Obrigado vtornik23 por não ter se recusado a participar e nos ajudou a criar uma interface completa no mecanismo Unity3d.

imagem

Máquina de jogo tridimensional "bandido de um braço"; enviando 1 EOS nele e puxando uma alavanca inteligente, o jogador tem a oportunidade de começar a roda da fortuna e ganhar o jackpot!

Vulnerabilidades do contrato


De acordo com a idéia do jogo, a vitória foi considerada como a perda de três bonecas ZeroNights, que no coeficiente numérico seria 777 ou 0. As chances de ganhar foram equivalentes a 0,02%, e algum programador desatento tentou complicar o algoritmo aleatório adicionando apenas excesso de multiplicação. a quantidade de dinheiro enviada e com preguiça de pensar nas condições com mais detalhes, então escrevi if (result == 777 || result <1), o que torna possível escorregar um valor negativo.

  int rnd = random(999); int result = rnd * price.amount; uint64_t prize = 0; print("Result:", result); // BINGO 777 or 000 !!! ~ 0.02% if(result == 777 || result < 1 ) { prize = 100; sendtokens(from); } 

O contrato inteligente em si é apresentado no github , para que todos possam examiná-lo mais de perto e identificar outras vulnerabilidades. Eles já foram escritos sobre eles um pouco mais alto, então não deve haver nenhuma dificuldade em encontrá-los.

Regras para participação


As regras de participação são muito simples: era necessário tentar vencer ou invadir os mecanismos do sistema. Quando três matryoshkas caem - Jackpot !!! O sistema cobra 100 unidades de criptomoeda. Se um participante recebe um jackpot três vezes seguidas, ele se torna um vencedor e recebe prêmios dos organizadores - hoodies de marca, crachás, uma variedade de produtos.

Obviamente, você pode ganhar puxando a alavanca por um longo tempo e esperando ter sorte, mas a sorte é imprevisível e a porcentagem de ganhos é muito pequena, por isso foi mais fácil de hackear.

Resultados da Competição


Como resultado, a competição, em nossa opinião, foi perfeita. As recompensas foram planejadas para 3 pessoas, e apenas três conseguiram lidar com a competição antes da data final programada. A competição foi realizada por 2 dias, durante os quais os participantes tiveram que resolver a tarefa. O prêmio oficial e a apresentação dos presentes ocorreram no encerramento da conferência no palco principal do ZeroNights 2018.

A ênfase principal foi colocada no conhecimento da tecnologia blockchain da EOS, e deixamos algumas dicas, uma das quais ninguém conseguiu encontrar. Vamos deixar esse enigma para mais tarde ...

Revisões dos participantes


Alexey (1 lugar)
O ZeroNights é uma das minhas conferências favoritas, começando pela primeira, em São Petersburgo. Não perdi nenhuma. Sempre dá entusiasmo por seis meses, com certeza, e lá na primavera PHDays :). Nos últimos 3 anos venho desenvolvendo blockchain. Este ano, o blockchain chegou ao ZeroNights (no passado, a verdade parece ser a mesma, estava no hackvest, mas eu perdi). Primeiro de tudo, depois de me registrar na conferência, fui ver o que e como havia com o blockchain. Eu pensei que seria algo como PHDays, algum tipo de curva aleatória ou condição de corrida no ar. Mas aqui estava a EOS, com quem eu tinha um pouco de conhecimento no primeiro hackathon da EOS, mas não demorou muito e, além disso, todas as configurações de desenvolvimento foram perdidas. O espírito de luta caiu e fui esperar o início da conferência. Mas a curiosidade melhorou, afinal, o que há de errado com a EOS!

Stanislav Povolotsky (2 lugares)
Para mim, foi um concurso longo, mas interessante. E foi uma ótima oportunidade para conhecer a arquitetura do blockchain da EOS. O concurso começou com a surpresa de você não ter acesso à rede EOS (rede principal) - apenas por $$$. Depois de solicitar que o contrato fosse implantado na rede de teste, registrando-se nessa rede, configurando a dispersão e visualizando o histórico de transações do contrato do jogo, ficou imediatamente claro como trapacear a máquina caça-níqueis (o autor do contrato fez isso várias vezes durante o teste). Mas a confiança de que é tão rápido e fácil gerenciar o concurso desapareceu rapidamente assim que a rede não aprovou todas as minhas transações com parâmetros idênticos aos da transação vencedora.

Irina (3º lugar)
Antes de participar da competição, ela apresentou o trabalho de contratos inteligentes apenas em teoria, por isso foi muito interessante “conhecê-los ao vivo”, ver o código-fonte, experimentar as ferramentas (e mais uma vez garantir que o python seja o melhor). A tarefa acabou sendo realmente muito emocionante. Obrigada

E em conclusão


Para não dizer que todo mundo lidou com facilidade. Para alguém, foram dois dias difíceis e, no final, apenas os sortudos conseguiram vencer usando as deficiências de qualquer blockchain - se as informações entraram no blockchain, elas são acessíveis a todos e, se alguém já invadiu algo, o outro pode assisti-lo o caminho.

Agradecemos a todos os participantes e a todos que ajudaram na organização do concurso.
Vejo você no ZeroNights 2019, novas aventuras esperam por você!

Source: https://habr.com/ru/post/pt433552/


All Articles