---
title: "Vulnerabilidade de replay de assinatura ERC-1271"
description: "Em 27 de outubro de 2023, a Alchemy descobriu uma vulnerabilidade de replay de assinatura em contratos ERC1271 que afetou um grande número de smart contract accounts (SCA) e gerou riscos ao interagir com diversas aplicações."
---

# Vulnerabilidade de replay de assinatura ERC-1271

<ImageBlock
  src="https://media.alchemy.com/1711750158-smart-contract.png"
  alt="Vulnerabilidade de Replay de Assinatura em Smart Contract Account"
  width={2400}
  height={1260}
  caption="Vulnerabilidade de Replay de Assinatura em Smart Contract Account"
  priority
/>

Em 27 de outubro de 2023, a Alchemy descobriu uma vulnerabilidade de replay de assinatura de contrato ERC1271 que afetou um grande número de contas de contrato inteligente \(SCA\), e levou a riscos ao interagir com diversas aplicações. As SCAs afetadas incluíam nossa LightAccount e a SmartAccount da OKX, e as interações com aplicações que identificamos como estando em risco incluíram Permit2 e [Cowswap](https://www.alchemy.com/dapps/cowswap). Rapidamente levamos essa questão às várias SCAs e aplicações afetadas e descobrimos que [curiousapple](https://twitter.com/0xcuriousapple), um pesquisador de segurança independente, havia encontrado a mesma vulnerabilidade um mês antes. Colaboramos com curiousapple, [Frangio](https://twitter.com/frangio_) \(autor do ERC1271\), o time do ERC4337, e outros especialistas técnicos em SCA em uma correção. Neste momento, nenhum fundo está em risco e o impacto às aplicações é bastante limitado. Todas as SCAs envolvidas já reconheceram o risco ou lançaram uma correção.

## Detalhes técnicos

### Assinaturas de contrato ERC-1271

No Ethereum e em todas as chains baseadas na Ethereum Virtual Machine \(EVM\), existem dois tipos diferentes de contas - Externally Owned Accounts \(EOA\) e Smart Contracts. EOAs conseguem autenticar mensagens assinando com a chave privada do seu par de chaves ECDSA associado. No entanto, como os smart contracts recebem um endereço predeterminado durante a criação do contrato, eles não têm acesso fácil a uma chave privada para assinar mensagens.

Para resolver esse problema, o padrão de assinaturas de contrato [ERC-1271](https://eips.ethereum.org/EIPS/eip-1271) foi proposto em 2018. Com esse padrão, smart contracts podem implementar restrições/verificações para o que constitui uma assinatura válida, e aplicações podem chamar `contract.isValidSignature` para verificar se alguma ação foi autorizada pelo smart contract.

No contexto de contas de contrato inteligente \(SCAs\), o ERC-1271 é bastante útil, pois permite que usuários de SCAs usem aplicações baseadas em assinatura exatamente como as EOAs fazem. Essas aplicações incluem [OpenSea](https://www.alchemy.com/dapps/opensea), e a maior parte do DeFi \(que dependem do fluxo de aprovação de token → chamada\).

### Vulnerabilidade de replay de assinatura ERC1271

A maioria das SCAs implementa o ERC-1271 usando sua implementação de referência mostrada acima. Do ponto de vista de engenharia, é uma implementação leve, e torna as integrações de clientes muito mais fáceis, já que poderíamos reutilizar métodos como `signTypedData`, `signMessage`, `eth\_signTypedData\_v` e `personal\_sign` da mesma forma que são usados para EOAs.

No entanto, no caso em que o mesmo endereço possui múltiplas SCAs, e a aplicação não inclui o endereço de origem da interação, a mesma assinatura seria válida em ambas as contas para aquela aplicação.

Como essa vulnerabilidade só é possível com uma combinação de SCA e aplicação, o quão grave essa vulnerabilidade seria depende de quais aplicações essa interação funcionaria. A primeira aplicação que investigamos foi a [Permit2](https://github.com/dragonfly-xyz/useful-solidity-patterns/tree/main/patterns/permit2), que é infraestrutura pública construída pela Uniswap que melhora a segurança e a UX dos fluxos de aprovação de tokens [ERC20](https://www.alchemy.com/overviews/erc20-solidity) em toda a indústria, e por isso é amplamente usada hoje.

O bloco de código abaixo mostra as structs que a assinatura do Permit2 cobre. Notavelmente, `address owner`, o endereço de onde os tokens são retirados, não é coberto pela assinatura e é passado como argumento nas chamadas ao Permit2.

Como um atacante tiraria proveito dessa vulnerabilidade de replay de assinatura é algo como:

1. Bob solicita um pagamento de `X` tokens de Alice, que possui `n` SCAs, e solicita que isso seja feito via Permit2
1. Depois que Alice assina o primeiro permit, Bob pode fazer replay desse permit em todas as SCAs de Alice para receber um total de `n X` tokens.

<ImageBlock
  src="https://media.alchemy.com/1711750457-diagram-of-bob-s-attack-on-alice-that-owns-2-scas.png"
  alt="Diagrama do ataque de Bob contra Alice, que possui 2 SCAs"
  width={852}
  height={559}
  caption="Diagrama do ataque de Bob contra Alice, que possui 2 SCAs"
/>

Durante esse processo, criamos uma prova de conceito para confirmar essa vulnerabilidade. Ela pode ser encontrada aqui: [**replay-sig-poc**](https://github.com/omgwiNNING/replay-sig-poc)​

## Impacto

Como parte de nossa investigação, descobrimos que:

1. Múltiplas SCAs estavam em risco.

1. Além da nossa LightAccount, outras SCAs incluíam a [Kernel](https://github.com/zerodevapp/kernel/blob/main/src/Kernel.sol) da Zerodev, [Biconomy](https://github.com/bcnmy/scw-contracts), [Soul Wallet](https://github.com/SoulWallet/soul-wallet-contract), o [EIP4337Fallback](https://github.com/eth-infinitism/account-abstraction/blob/8215b88768d993fb6459c2723d173791a537a2e7/contracts/samples/gnosis/EIP4337Fallback.sol) da eth-infinitism para Gnosis Safes, [AmbireAccount](https://github.com/AmbireTech/wallet/blob/main/contracts/AmbireAccount.sol), a [SmartAccount](https://github.com/okx/AccountAbstraction/tree/main/contracts/wallet) da OKX, a [BaseWallet](https://github.com/argentlabs/argent-contracts/blob/develop/contracts/wallet/BaseWallet.sol) da Argent, e a [Fuse Wallet](https://github.com/fuseio/fuse-wallet-contracts).
1. Múltiplas aplicações estavam em risco:

1. Permit2 - Transferências baseadas em assinatura são replicáveis via replay. No entanto, a maior parte do uso do Permit2 é com o Universal Router, e qualquer forma de tirar proveito disso exigiria uma vulnerabilidade crítica independente no Universal Router.
1. Cowswap - Trades usando o caminho ERC-1271 são replicáveis via replay. A assinatura cobre `address recipient`, então o risco aqui seria, no máximo, preços desatualizados e/ou algumas perdas para MEV.
1. [Gnosis Safe](https://www.alchemy.com/dapps/gnosis-safe) não era vulnerável a esse vetor de ataque.

Nesse momento, divulgamos isso às SCAs e aplicações via um grupo no telegram e descobrimos que curiousapple também havia descoberto o mesmo problema um mês antes e estava colaborando com Frangio e outros especialistas técnicos em SCA em uma correção. No geral, a lista completa de combinações afetadas de SCAs e aplicações até o momento é mostrada abaixo:

<ImageBlock
  src="https://media.alchemy.com/1711750508-screenshot-2024-02-06-at-1-59-14-pm-1.png"
  alt="Tabela de smart contract accounts e aplicações afetadas pela vulnerabilidade de replay de assinatura ERC-1271"
  width={637}
  height={587}
  caption="Impacto: Contas e Aplicações"
/>

Nota: No caso da Argent, como é um aplicativo móvel e gera o signer por dispositivo, é impossível que 2 SCAs sejam possuídas pela mesma EOA, portanto o ataque de replay de assinatura não funciona contra a Argent. No entanto, projetos que fazem fork dos contratos da Argent sem fazer fork de toda a sua arquitetura podem estar em risco e devem adotar a arquitetura de wallet da Argent, ou lançar uma correção.

## Correção

Foram propostas duas correções para as SCAs. Os construtores de SCA devem notar que devem implementar uma dessas duas soluções para prevenir o ataque de replay acima:

Ambas as soluções previnem o ataque de replay de assinatura ERC-1271. A segunda solução é mais leve, mas significaria que os clientes de wallet teriam que exibir um hash opaco para os usuários assinarem. A primeira correção é um caminho mais fácil para garantir que as assinaturas não sejam opacas para o usuário, e é por isso que optamos pela primeira correção para a LightAccount. A maioria das outras SCAs também optou pela mesma correção.

## Agradecimentos

Muito obrigado à OKX por pagar uma recompensa por bug a Howy por esse problema!

Parabéns a [curiousapple](https://twitter.com/0xcuriousapple) por receber recompensas por bug da Ambire, Instadapp, Biconomy e Cowswap!

Além disso, um grande agradecimento a:

1. [Dror Tirosh](https://twitter.com/drortirosh) por fazer o brainstorming da abordagem de correção com struct EIP-712 que a maioria das SCAs adotou
1. [Frangio](https://twitter.com/frangio_) por compartilhar mais contexto sobre o ERC-1271 e pelo grande esforço em atualizar a implementação de referência do ERC-1271 via o comitê do EIP
1. [Ivo \(Ambire\)](https://twitter.com/ivshti) por seu mergulho profundo nas diferenças de implementação técnica entre as duas soluções propostas
1. [Vectorized](https://twitter.com/optimizoor) por disponibilizar e financiar uma recompensa de 0,5 ETH para uma implementação cliente da solução EIP-712 aninhada
1. [Juno \(ChainLight\)](https://twitter.com/junorouse) por aceitar o desafio acima, lançando uma [implementação cliente da solução EIP712 aninhada](https://github.com/junomonster/nested-eip-712) e reivindicando a recompensa da Vectorized
1. [David Eiber](https://twitter.com/eiber_david) por sua ajuda no brainstorming de vulnerabilidades relacionadas, na indexação de SCAs e protocolos afetados, e na criação de PoCs
1. [Yoav Weiss](https://twitter.com/yoavw) por sua ajuda durante todo o processo, incluindo nos conectar com pesquisadores de segurança e outras SCAs e aplicações afetadas
