30 de junho de 2022
A necessidade de geradores de números pseudo-aleatórios
Os geradores de números aleatórios são usados extensivamente em todos os tipos de aplicações, como jogos de azar, decisão de vencedores em jogos, obtenção de sementes para dados de teste, etc.
Contudo, a geração de números aleatórios na Ethereum é uma tarefa desafiadora devido à sua natureza determinística e ao fato de que, a cada momento que uma função é chamada no contrato, ela deve ser validada por todos os outros nós e mineradores da rede.
Todo algoritmo, incluindo Solidity, é incapaz de gerar números aleatórios verdadeiros; portanto, há uma forte dependência do fator pseudo-aleatório. Além disso, cada cálculo na Solidity custa gas, dificultando o uso de cálculos longos e complexos para geração de números aleatórios.
Mecanismos inseguros para criar números aleatórios na Solidity
Os números aleatórios na Solidity podem ser criados usando vários métodos pré-definidos relacionados ao bloco, como:
-
block.timestamp (now)
- informa o timestamp do bloco atual em segundos desde a época do Unix. -
blockhash(uint blockNumber)
- informa o hash do bloco fornecido, só funciona para os 256 blocos mais recentes, excluindo o atual. -
block.difficulty
- informa a dificuldade do bloco atual. -
block.number
- informa o número do bloco atual. -
block.coinbase
- informa o endereço do minerador para o bloco atual.
Os desenvolvedores nunca deveriam confiar em valores derivados do bloco minerado, visto que eles podem ser facilmente atribuídos pelos mineradores durante a mineração de blocos e confirmação das transações, manipulando, assim, a lógica da função dependendo do gerador de números aleatórios.
Ataques de PRNG na selva (CVE-2018-14715)
O cryptogs, um jogo de pogs, na blockchain Ethereum, usou blockhash(uint blockNumber)
para decidir o vencedor.
Eles não tinham nenhuma verificação para ver se o blockNumber
é muito antigo e a função hash do bloco (Blockhash) retornou 0, quando o blockNumber
foi mais antigo que os 256 blocos do bloco atual block.number
.
Isso permitiu aos invasores manipular a lógica do contrato, colocando-se em primeiro lugar na ordem e retirando (withdrawing) todos os pogs antes de outros usuários.
Sugestões e melhores práticas
- Utilizar oráculos (Oraclize) como fonte externa de aleatoriedade. Deve-se tomar cuidado ao confiar em um oráculo (Oracle). Múltiplos oráculos também podem ser usados.
- Utilizar esquemas de compromisso - um primitivo criptográfico que usa uma abordagem de compromisso e revelação pode ser seguido. Também possui amplas aplicações em coin flipping, provas de conhecimento-zero e computação segura. Por exemplo: RANDAO.
- O VRF chainlink - é um gerador de números aleatórios comprovadamente justo e verificável (RNG), que permite que contratos inteligentes acessem valores aleatórios sem comprometer a segurança ou a usabilidade.
- O algoritmo Signidice - adequado para PRNG em aplicações envolvendo duas partes usando assinaturas criptográficas.
- Hashes de blocos do Bitcoin (Bitcoin Block Hashes) - oráculos como BTCRelay podem ser usados, que atuam como ponte entre a Ethereum e o Bitcoin. Os contratos na Ethereum podem solicitar hashes de blocos da blockchain Bitcoin como fonte de entropia. Deve ser observado que essa abordagem não é segura contra o problema de incentivo ao minerador e deve ser implementada com cautela.
Nosso scanner de segurança de contrato inteligente baseado na nuvem - o SolidityScan - detecta o uso de geradores de números pseudo-aleatórios fracos baseados em variáveis de blocos. Também permite que os desenvolvedores e auditores publiquem relatórios após a correção de bugs. Inscreva-se para uma avaliação gratuita em https://solidityscan.com/signup.
Esse artigo foi escrito por Shashank e traduzido por Isabela Curado Nehme. Seu original pode ser lido aqui](https://blog.solidityscan.com/weak-block-based-prng-in-solidity-f29e089de594).
Top comments (0)