No dia 8 de dezembro de 2023, a OpenZeppelin emitiu um importante aviso de segurança. Aparentemente, ao compartilhar o padrão ERC-2771 e funções do tipo Multicall, existe o risco de falsificação de endereço! Eu estudei profundamente esta vulnerabilidade e quero compartilhar minhas descobertas.
O criminoso trocou 5 WETH por aproximadamente 3,455,399,346 TIME
Em seguida, construiu parâmetros de calldata engenhosos e chamou [Forwarder].execute
Esta função iniciou o multicall no contrato TIME, e o calldata restante foi utilizado para burn() - destruição de tokens no pool!
Como é que isto funciona?
Nesta ataque, as estrelas se alinharam: ERC-2771, Multicall e dados meticulosamente elaborados. O contrato TOKEN herda ERC2771Context, e aqui começa a parte mais interessante!
ERC-2771 fornece um msg.sender virtual, permitindo delegar transações a terceiros. O endereço real é adicionado ao calldata. Quando [Forwarder] chama o contrato, _msgSender() verifica esses dados e corta os últimos 20 bytes como "msg.sender real".
Multicall transforma uma chamada em várias, economizando gás. Ele aceita um array de chamadas e as executa através de deleGatecall().
E aqui está a armadilha! O atacante desloca o calldata de tal forma que os primeiros 4 bytes dos novos dados correspondem à função burn(), e o parâmetro é uma enorme quantia de tokens. Na linha 0x20 é adicionado o endereço do pool de liquidez TIME-ETH, que se torna o msg.sender "esperado"!
Raiz do problema
No ERC-2771 [Forwarder] nunca foi planejado para trabalhar com multicall! O atacante adicionou os parâmetros _msgSender() na chamada externa do multicall. Dentro da função multicall, algumas funções também adicionaram esses parâmetros, o que permitiu simular uma chamada de QUALQUER endereço!
Medidas de proteção
A nova versão do OpenZeppelin Multicall agora preserva o comprimento do contexto ERC-2771 e o considera em cada chamada filha.
A ThirdWeb foi mais longe e proibiu qualquer contrato de chamar multicall, impedindo o uso de [Forwarder].
Esta vulnerabilidade é um exemplo claro de como a combinação de componentes que são seguros separadamente pode criar uma falha catastrófica! Todos os desenvolvedores devem lembrar: verifiquem sempre a interação entre os diferentes padrões.
Esta página pode conter conteúdo de terceiros, que é fornecido apenas para fins informativos (não para representações/garantias) e não deve ser considerada como um endosso de suas opiniões pela Gate nem como aconselhamento financeiro ou profissional. Consulte a Isenção de responsabilidade para obter detalhes.
Análise do princípio da vulnerabilidade de substituição de endereço arbitrário no ERC2771 Multicall da SharkTeam
No dia 8 de dezembro de 2023, a OpenZeppelin emitiu um importante aviso de segurança. Aparentemente, ao compartilhar o padrão ERC-2771 e funções do tipo Multicall, existe o risco de falsificação de endereço! Eu estudei profundamente esta vulnerabilidade e quero compartilhar minhas descobertas.
Análise do ataque
Vamos considerar um dos ataques:
O esquema de ataque é genialmente simples:
Como é que isto funciona?
Nesta ataque, as estrelas se alinharam: ERC-2771, Multicall e dados meticulosamente elaborados. O contrato TOKEN herda ERC2771Context, e aqui começa a parte mais interessante!
ERC-2771 fornece um msg.sender virtual, permitindo delegar transações a terceiros. O endereço real é adicionado ao calldata. Quando [Forwarder] chama o contrato, _msgSender() verifica esses dados e corta os últimos 20 bytes como "msg.sender real".
Multicall transforma uma chamada em várias, economizando gás. Ele aceita um array de chamadas e as executa através de deleGatecall().
E aqui está a armadilha! O atacante desloca o calldata de tal forma que os primeiros 4 bytes dos novos dados correspondem à função burn(), e o parâmetro é uma enorme quantia de tokens. Na linha 0x20 é adicionado o endereço do pool de liquidez TIME-ETH, que se torna o msg.sender "esperado"!
Raiz do problema
No ERC-2771 [Forwarder] nunca foi planejado para trabalhar com multicall! O atacante adicionou os parâmetros _msgSender() na chamada externa do multicall. Dentro da função multicall, algumas funções também adicionaram esses parâmetros, o que permitiu simular uma chamada de QUALQUER endereço!
Medidas de proteção
A nova versão do OpenZeppelin Multicall agora preserva o comprimento do contexto ERC-2771 e o considera em cada chamada filha.
A ThirdWeb foi mais longe e proibiu qualquer contrato de chamar multicall, impedindo o uso de [Forwarder].
Esta vulnerabilidade é um exemplo claro de como a combinação de componentes que são seguros separadamente pode criar uma falha catastrófica! Todos os desenvolvedores devem lembrar: verifiquem sempre a interação entre os diferentes padrões.