---
title: "ERC-1271 簽章重放漏洞"
description: "2023 年 10 月 27 日，Alchemy 發現一個 ERC1271 合約簽章重放漏洞，影響大量智能合約帳戶（SCA），並在與多個應用程式互動時帶來風險。"
---

# ERC-1271 簽章重放漏洞

<ImageBlock
  src="https://media.alchemy.com/1711750158-smart-contract.png"
  alt="智能合約帳戶簽章重放漏洞"
  width={2400}
  height={1260}
  caption="智能合約帳戶簽章重放漏洞"
  priority
/>

2023 年 10 月 27 日，Alchemy 發現了一個 ERC1271 合約簽章重放漏洞，影響了大量的智能合約帳戶 \(SCA\)，並在與多個應用程式互動時帶來風險。受影響的 SCA 包括我們的 LightAccount 及 OKX 的 SmartAccount，而我們發現有風險的應用程式互動則包括 Permit2 及 [Cowswap](https://www.alchemy.com/dapps/cowswap)。我們隨即將此問題告知各受影響的 SCA 及應用程式，並發現獨立資安研究員 [curiousapple](https://twitter.com/0xcuriousapple) 在一個月前就已發現相同的漏洞。我們與 curiousapple、[Frangio](https://twitter.com/frangio_) \(ERC1271 作者\)、ERC4337 團隊以及其他 SCA 技術專家合作進行修復。目前為止，並無資金面臨風險，對應用程式的影響也相當有限。所有涉及的 SCA 皆已確認此風險或已推出修復。

## 技術細節

### ERC-1271 合約簽章

在 Ethereum 及所有以 Ethereum Virtual Machine \(EVM\) 為基礎的鏈上，有兩種不同類型的帳戶——外部擁有帳戶 \(EOA\) 及智能合約。EOA 能夠透過其所關聯的 ECDSA 金鑰對中的私鑰進行簽章，以驗證訊息。然而，由於智能合約在建立時就被賦予固定的地址，它並沒有現成的私鑰可用來簽署訊息。

為解決此問題，[ERC-1271](https://eips.ethereum.org/EIPS/eip-1271) 合約簽章標準於 2018 年被提出。透過此標準，智能合約可以對何謂有效簽章實作限制／檢查，應用程式則可呼叫 `contract.isValidSignature` 來驗證某項動作是否經過智能合約授權。

在智能合約帳戶 \(SCA\) 的情境下，ERC-1271 相當實用，因為它讓 SCA 的使用者能像 EOA 一樣使用以簽章為基礎的應用程式。這些應用程式包括 [OpenSea](https://www.alchemy.com/dapps/opensea)，以及大多數依賴代幣授權 → 呼叫這種使用者流程的 DeFi 應用程式。

### ERC1271 簽章重放漏洞

大多數 SCA 都採用上述參考實作來實作 ERC-1271。從工程角度來看，這是一種輕量的實作方式，也讓客戶端整合更加容易，因為我們可以沿用 `signTypedData`、`signMessage`、`eth\_signTypedData\_v` 及 `personal\_sign` 等方法，就像用在 EOA 上一樣。

然而，若同一個地址擁有多個 SCA，且應用程式沒有納入該次互動的來源地址，那麼同一個簽章便會對該應用程式的兩個帳戶都有效。

由於此漏洞只有在 SCA 與應用程式組合的情況下才會發生，此漏洞的嚴重程度取決於該互動適用於哪些應用程式。我們首先調查的應用程式是 [Permit2](https://github.com/dragonfly-xyz/useful-solidity-patterns/tree/main/patterns/permit2)，這是 Uniswap 建構的公共基礎設施，能改善整個產業中 [ERC20](https://www.alchemy.com/overviews/erc20-solidity) 代幣授權流程的安全性與使用者體驗，因此目前被廣泛使用。

下方的程式碼區塊顯示了 Permit2 簽章所涵蓋的結構。值得注意的是，`address owner`（即代幣被提取的地址）並未被簽章涵蓋，而是在呼叫 Permit2 時作為參數傳入。

攻擊者可能利用此簽章重放漏洞的方式大致如下：

1. Bob 向擁有 `n` 個 SCA 的 Alice 請求支付 `X` 個代幣，並要求透過 Permit2 完成
1. Alice 簽署第一個 permit 後，Bob 便可在 Alice 的所有 SCA 上重放此 permit，總共收到 `n X` 個代幣。

<ImageBlock
  src="https://media.alchemy.com/1711750457-diagram-of-bob-s-attack-on-alice-that-owns-2-scas.png"
  alt="Bob 攻擊擁有 2 個 SCA 的 Alice 示意圖"
  width={852}
  height={559}
  caption="Bob 攻擊擁有 2 個 SCA 的 Alice 示意圖"
/>

在此過程中，我們製作了一個概念驗證來確認此漏洞，可於此處找到：[**replay-sig-poc**](https://github.com/omgwiNNING/replay-sig-poc)​

## 影響範圍

在調查過程中，我們發現：

1. 多個 SCA 面臨風險。

1. 除了我們的 LightAccount 之外，其他受影響的 SCA 還包括 Zerodev 的 [Kernel](https://github.com/zerodevapp/kernel/blob/main/src/Kernel.sol)、[Biconomy](https://github.com/bcnmy/scw-contracts)、[Soul Wallet](https://github.com/SoulWallet/soul-wallet-contract)、eth-infinitism 為 Gnosis Safe 打造的 [EIP4337Fallback](https://github.com/eth-infinitism/account-abstraction/blob/8215b88768d993fb6459c2723d173791a537a2e7/contracts/samples/gnosis/EIP4337Fallback.sol)、[AmbireAccount](https://github.com/AmbireTech/wallet/blob/main/contracts/AmbireAccount.sol)、OKX 的 [SmartAccount](https://github.com/okx/AccountAbstraction/tree/main/contracts/wallet)、Argent 的 [BaseWallet](https://github.com/argentlabs/argent-contracts/blob/develop/contracts/wallet/BaseWallet.sol)，以及 [Fuse Wallet](https://github.com/fuseio/fuse-wallet-contracts)。
1. 多個應用程式面臨風險：

1. Permit2 - 以簽章為基礎的轉帳可被重放。不過，大多數 Permit2 的使用情境都是透過 Universal Router，若要利用此漏洞，還需要 Universal Router 本身存在另一個獨立的嚴重漏洞。
1. Cowswap - 透過 ERC-1271 路徑進行的交易可被重放。由於簽章涵蓋了 `address recipient`，此處的風險最多只是過時的價格及／或部分 MEV 損失。
1. [Gnosis Safe](https://www.alchemy.com/dapps/gnosis-safe) 不受此攻擊向量影響。

在此階段，我們透過 telegram 群組將此問題告知相關 SCA 及應用程式，並發現 curiousapple 早在一個月前就已發現相同的問題，並正與 Frangio 及其他 SCA 技術專家合作修復。截至目前為止，受影響的 SCA 與應用程式組合完整清單如下：

<ImageBlock
  src="https://media.alchemy.com/1711750508-screenshot-2024-02-06-at-1-59-14-pm-1.png"
  alt="受 ERC-1271 簽章重放漏洞影響的智能合約帳戶與應用程式列表"
  width={637}
  height={587}
  caption="影響範圍：帳戶與應用程式"
/>

注意：由於 Argent 是行動應用程式，並依裝置產生簽署者，因此不可能出現同一個 EOA 擁有兩個 SCA 的情況，所以此簽章重放攻擊對 Argent 無效。不過，若有專案複製 Argent 的合約卻沒有一併複製其整體架構，則可能面臨風險，這類專案應採用 Argent 的錢包架構，或推出修復。

## 修復方式

目前提出了兩種 SCA 修復方案。SCA 開發者應注意，須採用以下兩種解決方案其中之一，以防止上述重放攻擊：

這兩種解決方案都能防止 ERC-1271 簽章重放攻擊。後者較為輕量，但意味著錢包客戶端必須顯示一段不透明的雜湊供使用者簽署。前者則較易確保使用者所簽署的內容不會是不透明的，這也是我們為 LightAccount 選擇前者修復方案的原因。大多數其他 SCA 也選擇了相同的修復方案。

## 致謝

非常感謝 OKX 就此問題向 Howy 支付了漏洞賞金！

恭喜 [curiousapple](https://twitter.com/0xcuriousapple) 獲得來自 Ambire、Instadapp、Biconomy 及 Cowswap 的漏洞賞金！

此外，也要特別感謝：

1. [Dror Tirosh](https://twitter.com/drortirosh) 提出了大多數 SCA 採用的 EIP-712 結構修復方案構想
1. [Frangio](https://twitter.com/frangio_) 分享了 ERC-1271 更多的背景資訊，並大力推動透過 EIP 委員會更新 ERC-1271 的參考實作
1. [Ivo \(Ambire\)](https://twitter.com/ivshti) 深入分析了兩種提議解決方案之間的技術實作差異
1. [Vectorized](https://twitter.com/optimizoor) 提供並資助了 0.5 ETH 的賞金，徵求嵌套 EIP-712 解決方案的客戶端實作
1. [Juno \(ChainLight\)](https://twitter.com/junorouse) 接下了上述挑戰，推出[嵌套 EIP712 解決方案的客戶端實作](https://github.com/junomonster/nested-eip-712)並獲得 Vectorized 提供的賞金
1. [David Eiber](https://twitter.com/eiber_david) 協助發想相關漏洞、整理受影響的 SCA 及協定清單，並建立概念驗證
1. [Yoav Weiss](https://twitter.com/yoavw) 在整個過程中提供協助，包括引介我們與資安研究員及其他受影響的 SCA 與應用程式聯繫
