Address Spoofing Attack: The Combination of ERC2771 and Multicall is a Bomb
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.
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 is the utility contract in OpenZeppelin’s libraries. It provides a function to batch together multiple contract function calls in a single transaction call.
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.
Normally, the user call Forwarder contract (trusted by token) to execute
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:
req.data with below code:
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:
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.
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.