Aprenda sobre as vulnerabilidades populares de contratos inteligentes.
Foto de Mika Baumeister em Unsplash
Segurança inteligente do contrato:
Um contrato inteligente é um software, que é executado automaticamente quando critérios específicos são atendidos. Como contratos inteligentes são executados em uma rede blockchain descentralizada, eles são considerados seguros por padrão. No entanto, contratos inteligentes ainda podem ser vulneráveis a certos riscos de segurança, como erros de codificação, ataques maliciosos e testes insuficientes. Para reduzir o risco de problemas de segurança, é importante seguir as melhores práticas para escrever e implantar contratos inteligentes, como testar minuciosamente o código, usando técnicas de codificação seguras, e mantendo o código do contrato simples e modular. Também é importante auditar regularmente contratos inteligentes para identificar e solucionar possíveis vulnerabilidades.
O DAO Hack
Um dos maiores ataques que envolveram um contrato inteligente ocorreu em 2016, quando uma vulnerabilidade no código de contrato inteligente da Organização Autônoma Descentralizada ( DAO — Decentralized Autonomous Organization, no original ), foi explorada, resultando no roubo de cerca de $50 milhões em valor da criptomoeda Ether. O hack foi o resultado de um erro de codificação no contrato inteligente do DAO, que permitiu ao invasor retirar fundos repetidamente do contrato sem permissão. O incidente destacou a necessidade de testes e auditorias completas do código de contrato inteligente para garantir que ele seja seguro e livre de vulnerabilidades.
Vulnerabilidades populares no contrato inteligente:
Ataque de reentrada
Os ataques de reentrada ocorrem quando um contrato chama outro contrato e o segundo contrato volta ao primeiro contrato antes que o primeiro contrato conclua sua execução. Isso pode levar a comportamentos inesperados e potencial perda de fundos.
Para evitar isso, o Solidity oferece as funções revert()
e require()
, que interrompem a execução do contrato e revertem quaisquer alterações feitas se a condição especificada não for atendida.
Aqui está um exemplo de contrato vulnerável a um ataque de reentrada:
contract ReentrancyAttack {
address public owner;
uint public balance;
constructor() public {
owner = msg.sender;
balance = 100;
}
function withdraw() public {
// vulnerável ao ataque de reentrada
if (balance >= 10) {
balance -= 10;
msg.sender.transfer(10);
}
}
}
Para evitar essa vulnerabilidade, podemos usar a função require()
para verificar se o saldo é suficiente antes de realizar a transferência:
contract ReentrancyAttack {
address public owner;
uint public balance;
constructor() public {
owner = msg.sender;
balance = 100;
}
function withdraw() public {
// preveni o ataque de reentrada
require(balance >= 10, "Insufficient balance");
balance -= 10;
msg.sender.transfer(10);
}
}
Neste contrato atualizado, se o saldo for insuficiente para a transferência, a função require()
irá interromper a execução do contrato e reverterá as alterações feitas. Isso garantirá que o contrato não possa ser explorado por um ataque de reentrada.
Tx.origin
O ataque tx.origin em Solidity envolve a exploração do fato de que a variável global tx.origin nos contratos de Solidity é o endereço do chamador externo do contrato, e não o proprietário do contrato real. Isso permite que um invasor personifique o proprietário do contrato chamando o contrato de outro endereço, ignorando quaisquer controles de acesso ou verificações de permissão baseadas no endereço do proprietário do contrato.
Aqui está um exemplo de código vulnerável ao ataque tx.origin:
pragma solidity ^0.8.01;
contract MyContract { address public owner;
constructor() {
owner = msg.sender;
}
function myFunction() public {
require(msg.sender == owner, "Unauthorized access");
// ..........
}
}
Neste exemplo, o contrato verifica se o chamador da função myFunction ( ) é o proprietário do contrato. No entanto, como tx.origin é usado em vez do msg.sender, um invasor pode chamar myFunction ( ) de qualquer endereço e personificar o proprietário do contrato. Isso pode permitir que o invasor obtenha acesso não autorizado às funções e dados do contrato.
Sanduíche
O ataque sanduíche é uma vulnerabilidade que pode ocorrer nos contratos inteligentes de Solidity quando eles usam várias funções para modificar as mesmas variáveis de estado. Isso pode levar a um comportamento inesperado e potencialmente malicioso no contrato.
Aqui está um exemplo de um contrato de solidity vulnerável ao ataque sanduíche:
pragma solidity ^0.8.01;
contract SandwichAttack {
uint public balance;
function deposit(uint amount) public {
balance += amount;
}
function withdraw(uint amount) public {
balance -= amount;
}
function transfer(address to, uint amount) public {
withdraw(amount);
to.transfer(amount);
deposit(amount);
}
}
Neste contrato, a função transfer
usa as funções withdraw
e depositve
para mover fundos do saldo do contrato para outro endereço. No entanto, se um usuário malicioso chamar para a função deposit
entre as chamadas de withdraw
etransfer
, eles poderiam efetivamente cancelar a retirada e aumentar o saldo do contrato pelo valor depositado. Isso resultaria no saldo incorreto do contrato e poderia levar à perda ou roubo de fundos
Para evitar essa vulnerabilidade, os contratos de solidity devem usar a palavra-chave require
para garantir que as variáveis de estado não sejam modificadas por várias funções simultaneamente. Por exemplo, o contrato acima pode ser modificado da seguinte maneira:
pragma solidity ^0.8.01;
contract SandwichAttack {
uint public balance;
function deposit(uint amount) public {
require(balance + amount >= balance, "Overflow detected");
balance += amount;
}
function withdraw(uint amount) public {
require(balance >= amount, "Insufficient balance");
balance -= amount;
}
function transfer(address to, uint amount) public {
withdraw(amount);
to.transfer(amount);
deposit(amount);
}
}
Neste contrato modificado, as funções deposit
e withdraw
usam a palavra-chave require
para garantir que o saldo do contrato não seja modificado simultaneamente por várias funções. Isso impede que o ataque sanduíche ocorra e garante também a integridade do estado do contrato.
Obrigado pessoal!
Siga-me no Twitter: @Param_eth
Este artigo foi escrito por Param_eth e traduzido por Adriano P. de Araujo. O original em inglês pode ser encontrado aqui.
Oldest comments (1)
Esse codigo que voce esta mostrando no tx.origin não tem nenhuma vulnerabilidade
ai esta um exemplo de vulnerabilidade tx.origin