Conteúdo
📝Introdução
🔍Descrição da Vulnerabilidade
🛡️Estratégias de Mitigação
📝Conclusão
🗃️Referências
📝 Introdução
Recentemente, nossos parceiros da Lido, em colaboração com a Immunefi, foram alertados sobre uma vulnerabilidade classificada como ADVERTÊNCIA. Essa vulnerabilidade, sob condições específicas, pode interromper significativamente a experiência do usuário (UX) durante o processamento de uma solicitação de saque. Essa revelação é particularmente preocupante porque não afeta apenas a Lido, mas também se estende a muitos dos maiores protocolos DeFi e seus principais forks, indicando um risco potencial generalizado no ecossistema DeFi.
O que torna essa situação especialmente intrigante é a descoberta por nossos pesquisadores de segurança de que essa vulnerabilidade não está isolada em um único protocolo ou implementação, mas é, na verdade, um problema sistêmico ao qual muitas das principais plataformas DeFi estão expostas. A semelhança da vulnerabilidade em vários protocolos sugere um descuido fundamental nas práticas padrão adotadas pelos desenvolvedores de DeFi.
Estamos muito preocupados com o fato de que todos os protocolos que usam o ERC-20 Permit devem descobrir qual é o problema e explorar as formas de evitá-lo. Vamos descobrir qual é o problema aqui e como podemos evitá-lo no futuro!
🔍 Descrição da Vulnerabilidade
Vamos começar com o cerne do problema. Vamos dar uma olhada em um exemplo específico do código Lido:
Para começar, o ERC-20 Permit é uma modificação do token ERC-20 padrão que permite que os usuários deleguem seus direitos de gastos a outros endereços sem precisar enviar os tokens eles mesmos ou usar o ether para pagar pelo gas das transações. Isso é feito por meio da assinatura de mensagens off-chain, o que simplifica muito o processo de transação.
Vamos dar uma olhada no código abaixo. Estes são os métodos que a Lido usa para processar solicitações de saque usando o mecanismo Permit no contexto de tokens ERC-20.
function requestWithdrawalsWithPermit(uint256[] calldata _amounts, address _owner, PermitInput calldata _permit)
external returns (uint256[] memory requestIds) {
STETH.permit(msg.sender, address(this), _permit.value, _permit.deadline, _permit.v, _permit.r, _permit.s);
return requestWithdrawals(_amounts, _owner);
}
function requestWithdrawalsWstETHWithPermit(uint256[] calldata _amounts, address _owner, PermitInput calldata _permit)
external returns (uint256[] memory requestIds) {
WSTETH.permit(msg.sender, address(this), _permit.value, _permit.deadline, _permit.v, _permit.r, _permit.s);
return requestWithdrawalsWstETH(_amounts, _owner);
}
Essas funções foram projetadas para agilizar as transações, combinando operações de aprovação de token e solicitação de saque em uma única chamada.
ERC20Permit (stETH
e wstETH
herdam dele) usa o mapeamento de nonces para proteção contra reprodução. Quando uma assinatura é verificada e aprovada, o nonce aumenta, invalidando a mesma assinatura que está sendo reproduzida.
Ambos os métodos acima esperam que o usuário assine seus tokens com o endereço do contrato WithdrawlQueue
como spender (quem gasta) e envie a transação para a cadeia com a assinatura uint8 v
, bytes32 r
, bytes32 s
como parte dos argumentos.
Quando a transação do usuário está no mempool, um invasor pode pegar essa assinatura e chamar a função token.permit
no próprio token com os seguintes argumentos:
address owner = victim address
address spender = WithdrawlQueue contract address
uint256 value = _permit.value copied from the still pending transaction
uint256 deadline = _permit.deadline copied from the still pending transaction
uint8 v = _permit.v copied from the still pending transaction
bytes32 r = _permit.r copied from the still pending transaction
bytes32 s = _permit.s copied from the still pending transaction
Como essa é uma assinatura válida, o token a aceita e incrementa o nonce. Isso faz com que a transação do usuário falhe sempre que for minerada, o que, obviamente, prejudica a experiência do usuário.
🛡️Estratégias de Mitigação
Agora, vamos dar uma olhada no que está acontecendo dentro do ERC-2612.
O próprio ERC-2612 faz as seguintes recomendações de mitigação:
A principal informação aqui está contida no parágrafo a seguir:
As mensagens Permit assinadas são censuráveis. A parte retransmissora sempre pode optar por não submeter o Permit depois de recebê-lo, retendo a opção de enviá-lo. O parâmetro deadline (de prazo limite) é uma mitigação para isso. Se a parte signatária tiver ETH, ela também poderá enviar o Permit por conta própria, o que pode tornar inválidas as permissões assinadas anteriormente.
A leitura desatenta desse parágrafo levou à omissão do fato de que a assinatura pode se tornar inválida mesmo após o envio de um Permit por qualquer pessoa que tenha visto a transação no mempool.
O que torna isso mais perceptível são as considerações de segurança do EIP-712:
Como você pode ver, esse subartigo leva em conta a possibilidade de front-running e recomenda a implementação de todas as verificações necessárias de acordo com a lógica do protocolo. No entanto, a maioria dos contratos vulneráveis simplesmente decidiu rejeitar TXs com front-running.
A única maneira de mitigar isso é implementar vários mecanismos de prevenção personalizados ou, de qualquer forma, adicionar algumas correções de acordo com as especificações fornecidas.
📝 Conclusão
Ao concluir este artigo, fica evidente que a atenção meticulosa aos detalhes na leitura das especificações e na implementação de práticas seguras não é apenas aconselhável, mas essencial no âmbito da tecnologia blockchain e do desenvolvimento de contratos inteligentes. Esta publicação serve como um estudo de caso convincente que ressalta essa necessidade.
Fique conectado com a OXORIO
É fundamental manter-se atualizado com as últimas novidades em segurança de blockchain. Convidamos você a seguir a OXORIO no LinkedIn e Twitter para obter insights e atualizações. Além disso, visite nosso site em oxor.io para obter informações detalhadas sobre nossos serviços e como podemos ajudar a proteger seus projetos de blockchain.
🗃️ Referências
[1] — _Potential withdrawal request griefing vector via permit
front-running #803 | Lido-dao
[2] — ERC-2612 specification | by Martin Lundfall in Ethereum EIPs
[3] — EIP-712 specification | “Security Considerations” subarticle
Esse artigo foi escrito por Oxorio e traduzido por Fátima Lima. O original pode ser lido aqui.
Latest comments (0)