Address Spoofing Attack: The Combination of ERC2771 and Multicall is a Bomb
Situation Summary
THIRDWEB is a platform for developers. They have a smart contract development toolkit with 1-click to deploy NFT, Marketplace, ERC20 tokens, etc.
In contracts that have been deployed by THIRDWEB, they depend on ERC2771 and Multicall from the OpenZeppelin Library. The bad interaction between them created a critical vulnerability that affected the large blockchain community around the world. More than 8,000 contracts from different chains were deployed under vulnerable code, resulting in almost a million dollars in damage.
Technical Background
ERC2771
ERC-2771 is a meta transaction standard. It specifies how the caller address should be resolved when a call is forwarded by a trusted forwarder. During such a call, msg.sender
is the forwarder's address, while the real caller is only known by the forwarder. Therefore, before sending the call, the forwarder must append the real sender's address to the end calldata. The _msgSender()
function divided 20bytes at the end to determine the real sender.
Multicall
Multicall is the utility contract in OpenZeppelin’s libraries. It provides a function to batch together multiple contract function calls in a single transaction call.
Vulnerability Analysis
These features themselves don’t trigger this issue when used independently. It is only when using the two together that the vulnerability appears. Thus, the affected contracts inherited the vulnerability from the combination of these two features.
Root cause
Normally, the user call Forwarder contract (trusted by token) to execute transfer
, transferfrom
, burn
, or other functions. In each call, the token contract will determine who the true sender is via splitting 20bytes at the end of the datacall was sent by Forwarder. Unfortunately, the determination logic was broken by the multicall
function. Why? I'll explain more below.
Here is snipe code Forwarder:
Create the req.data
with below code:
Let’s focus req.data
(example from attacker data):
We can see the length of the arrBytes
array in the first bytes of the call data (0x01). The contract appends req.from
at the end of req.data
before the Forwarder does an external call. It has no significance since the bytes were declared as a bytes array with a strict length. Finally, the whole chain assault is as follows:
Migration
OpenZeppelin released a new update to OpenZeppelin Contracts for both of the 4.x and 5.x versions, allowing the use of Multicall
together with ERC2771Context
. Let’s upgrade the contract (if possible).
The official migration tutorial released by the THIRDWEB is here: Link.
Conclusion
Finally, the discovery and prompt remediation of the vulnerability in THIRDWEB's smart contract creation toolkit highlight the crucial need of proactive security measures in the constantly growing blockchain world. The combination of ERC2771 and Multicall in deployed contracts generated an unanticipated issue, resulting in a wide-ranging influence on numerous blockchain networks.
In the long run, the commitment to security is necessary. THIRDWEB and blockchain organizations should consider doing a security audit of their whole smart contract development process, with the help of trustworthy third-party firms.
The Verichains team regularly updates the most recent vulnerabilities discovered in projects they have assessed and those they are presently auditing, as well as information from the blockchain security community.