This is part 2/2 in our series on one of the most exploited issues in Web3: Offline signatures.
In part 1/2, we investigated the use of different standards of offline signatures in Web3 Dapps, and revisited one of the biggest hacks in this domain: The OpenSea-related offline signature phishing attack earlier this year that resulted in the theft of NFTs valued at millions of USD and demonstrated how it is still relevant.
Soon after, Zengo discovered an additional layer of vulnerabilities that had remained overlooked: ERC-20 tokens are vulnerable to hackers as well. In this second technical blogpost we will explore some recently-discovered attack vectors taking advantage of OpenSea’s newest smart contracts, to steal ERC-20 tokens as well and not just NFTs. Since our discovery, we responsibly disclosed our findings to OpenSea and later found evidence for actual use of such exploits as speculated by our research, in the wild against actual OpenSea users. We will conclude with some practical recommendations for users.
In June 2022, OpenSea migrated to the SeaPort contract. The main purpose of this migration was to improve the trading experience and allow additional features, including: Collection offers, more advanced exchange options, and gas savings by using more efficient implementation mechanisms.
First, in order to better understand the more recently-discovered ERC-20 scam we will briefly review the original scam process.
If you are already familiar with our first blogpost you can skip and directly proceed below to Part 2: Using Seaport to take your ERC-20 tokens for free.
Step 1: The NFT seller first needs to approve the OpenSea contract as an operator for the relevant NFT collection – meaning the OpenSea contract will have the permissions to move the collection’s NFTs from the seller’s wallet.
Step 2: Next, the seller is asked to sign an offline message that represents the listing parameters (e.g. price) that they submitted on the OpenSea application UI.
Step 3: The listing value is represented by an array called “consideration,” where each of the array’s cells represents a recipient of the buying transaction.
When choosing a regular listing (not auction), startAmount and endAmount will be the same and are calculated in WEI (if listing for ETH). OpenSea’s Dapp automatically calculates the value for each recipient (based on the creator fees) and prompts the user to sign:
Step 4: Once the seller signs that message, OpenSea updates the NFT’s status application as available for buying.
Step 5: When buyers make a purchase using the OpenSea Dapp, they send the listing parameters to the contract along with the listing signature as stored on OpenSea DB. The smart contract then compares the purchase parameters against the seller’s listing parameters and if they are met, the purchase event will go through successfully and the OS contract will move the NFT to the buyer and ETH (or any other token) to the seller.
The most critical step of the aforementioned listing process is the Signature, in which the OpenSea Dapp uses this signed hash signature in order to serve it to the SeaPort contract when a purchase is made.
In case the seller, for whatever reason, wants to list their NFT for free, then the consideration array is simply left empty, as they do not expect anything in return for the NFT:
And the message JSON would look like this:
It’s important to note that the usage of these signatures is not limited to the OpenSea Dapp. Therefore, anyone that obtains a valid signature hash of a certain listing can use it in order to process an NFT purchase using SeaPort contract, scammers included.
Scammers often use malicious Dapps in order to trick victims to sign an NFT listing for free, taking advantage of the fact the message to sign is not comprehensible to most users.
The SeaPort protocol was designed to accommodate a wide selection of features making it extremely generic, and potentially allowing users to trade ERC-20 tokens with each other.
At the same time, OpenSea’s Dapp does not implement all the protocol’s capabilities, but puts its focus on the extensive support of NFT listings (as described earlier) and NFT offers in return for ERC-20 tokens.
So how does the ERC-20 offer work?
For Offers (user offers an ERC-20 in favor of NFT) the process is the opposite of the listing process:
In this case the offer itemType is “1”, meaning ERC-20:
Given all the information above, the astute reader is probably already wondering what happens when users sign an empty ERC-20 offering (meaning, an ERC-20 offer with an empty consideration array) in a similar manner to the empty NFT listing shown above.
The answer, it is technically possible as shown below:
Since the feature of listing an ERC20 (for any price, free included) is not supported by the OpenSea Dapp, we created our own simple Dapp, which we will use in order to sign a listing of 1 WETH for free:
To illustrate the potential attacker’s next move we will send the signature hash along with the listing parameters to the SeaPort contract in order to get that 1 WETH from the victim (on our demo we have used a local fork of Goerli using Anvil, so no real harm could be caused to any user):
As seen on the video, once the attackers obtain the victim’s signature on the free 1 WETH listing, they could simply serve it to the SeaPort smart contract.
In early September 2022 (four months ago) when we originally discovered that potential issue and implemented a Proof of Concept (PoC) it had yet to be discovered “in the wild.”
Therefore, we decided to disclose it to OpenSea via HackerOne.
The OpenSea team responded that they are aware of such a capability, but won’t plan to address this potential issue as it involves phishing, which OpenSea cannot defend against.
We later discovered such variant was reported to be used in the wild, actively stealing OpenSea’s customers’ ERC-20 tokens, as seen in the tweet below:
Further down this thread, the renowned security researcher (https://twitter.com/0xQuit) adds that currently not much can be done by OpenSea to thwart such attacks.
Having said that, we realize that currently offline signatures are hazardous and there are no practical relevant solutions for everyday users that do not require a PhD in Web3. As a result we are working on a novel paradigm to revolutionize offline signatures security.
In part 1 and 2 we identified a truly challenging problem for the industry: But our Zengo X research team is up to the task.
We are finalizing a novel solution that has the potential to unlock additional layers of security industry-wide. We will share more soon. 👀