Critical privacy vulnerability — getting exposed by MetaMask
Lately, I’ve been spending time with my team, researching different NFT airdrop scenarios, and we’ve stumbled upon a pretty dark use case that can compromise the privacy of more than 21 million people — all MetaMask users.
It’s quite a potent scenario, too, as it has the potential to be eight times more devastating than a Distributed Denial of Service (DDoS) attack. And I’m saying that after comparing it to some of the most notorious attacks to hit the news last year.
Before diving in, let me tell you about what this article is NOT about:
P.S. For the sake of simplicity I will use URI & URL interchangeably and refer to the same thing.
In this article, I demonstrate how a malicious actor can mint an NFT, send it to a victim and obtain their IP address, thus compromising their privacy. This is a huge privacy issue in the blockchain ecosystem that is exploitable by anyone, with costs as little as $50.
Do not underestimate the risk associated with IP leaks — if malicious actors derive more information from the IP address (think geolocation, GSM carrier, etc.), they can turn it into physical risk, such as kidnapping.
The impact of this vulnerability is much more than just privacy leaking.
A highly motivated actor could craft a large number of NFTs, point them all to a single URL and airdrop them to millions of users, that way performing DDoS attacks on that URL at an unprecedented scale. We are talking about 8 times the size of the Mirai botnet that took down several high-profile websites, including GitHub, Twitter, Reddit, Netflix, Airbnb, and many others.
To have a better understanding about how it works and why this vulnerability exists, let’s go through the basics of how a collectible NFT works:
The NFT item is stored on the blockchain but since it is very expensive to store large quantities of data in public chains, the common practice is to store the actual image on a remote server and only keep the URL of the image in the chain.
A usual lifecycle and interaction with an NFT is as follows:
- Upload collectible’s image on a server;
- Mint the NFT on the blockchain and only store the holder’s address and URL of remote image;
- Optionally transfer the NFT to another blockchain address;
- Holder’s crypto wallet reads the blockchain to scan what collectibles it owns and finds the aforementioned NFT;
- Crypto wallet fetches the remote image from the URL associated with the NFT.
At this point I asked myself what if the server is controlled by a malicious actor and what consequences arise from this ?
The above diagram is self explanatory — if the server hosting the image is controlled by a malicious actor, then the IP address of the NFT holder is leaked by his mobile phone when the crypto wallet fetches the collectible’s remote image.
The same applies for a non-mobile crypto wallet. However, I chose to exemplify with mobile phone crypto wallet applications, since it’s most likely to use mobile data and also expose geolocation, GSM carrier, and other data, based on the IP address.
If a malicious actor only knows your blockchain address, he can mint an NFT with a URL pointing to his server and transfer the NFT’s ownership to your address. Thus, when your crypto wallet fetches the remote image from the server, it will compromise your privacy.
Pretty straightforward, right ?
At least in theory, because the part “when your crypto wallet fetches the remote image from the server” is crucial.
More questions started to pop up — is this something that happens automatically, when opening the crypto wallet app? Does it need explicit consent from the user? How, and when exactly, is this fetch triggered?
Unfortunately, I found the answers rather fast. All it took was a quick glance into the popular MetaMask Mobile wallet. From its source code on github, it seems that the remote image is fetched automatically without any prompt for the user’s explicit consent. This is also confirmed in their support desk which states that collectibles will be shown automatically based on the data they pull from opensea.io.
With all the details found so far, I decided to give it a try and mint an NFT on the OpenSea platform.
After creating the NFT, I checked the details for the default URL set on blockchain for the collectibles created through OpenSea. To do that, I first checked the smart contract address and NFT’s ID.
Now that I got the smart contract address, NFT (token) ID and the hint of using ERC-1155 standard, I jumped into the Remix Etherum IDE to start interacting with the smart contract more flexibly.
All I needed was these 8 lines of code (see Fig. 5) to compile and generate an ERC1155-based smart contract interface for interacting with the NFT previously minted on OpeanSea.
In the Deploy & Run transactions section (see Fig. 6) you can enter the smart contract address from OpenSea and expand the already deployed contract. Voilà, now you have a “uri” function to read the URL.
At this point I was curious about how I can update the URL to point to a server under my control so that I can confirm this vulnerability, by obtaining the IP address of my device.
After scrolling a bit through the transactions that were sent to this smart contract, I noticed a “Set URI” function call (Fig. 8) that is not part of the ERC1155 standard, so I opened it to see the function’s signature (Fig. 9).
Added this function into Remix IDE and re-compiled the smart contract to have this function on the interface (Fig. 10). The function has an empty body since I’m not deploying the smart contract, but only using it to generate an interface that will trigger the same “Set URI” function call on the existing smart contract.
The only thing that I am missing right now is a server publicly exposed on the internet that I can configure as the URL of the NFT. There are multiple solutions such as renting a virtual server in the cloud, but luckily, I remembered I used ngrok at some point to generate public URLs for internal resources on the local network, so I decided to use this.
I used Netcat to open a TCP server socket on my computer with “nc -l 80” command and also started ngrok with “ngrok http 80” command.
I now have a public URL — that forwards all the traffic to my local server (Fig.11). Ngrok should add an X-Forwarded-For HTTP header with the IP address of whoever is accessing that specific URL.
I should be able to see these headers dumped into my local TCP server when someone accesses the URL.
With everything set up, I updated the NFT’s remote image URL with the previously generated one with ngrok.
As a final step I installed the iOS Metamask Mobile app v3.7.0 and created a basic account to which I transferred the ownership of the NFT from the OpenSea interface.
After opening the MetaMask Mobile application, I could now see the NFT that has been airdropped (Fig. 13), but also on my Netcat TCP server, I could see the HTTP headers dumped by ngrok that expose the IP address of my phone (see Fig. 14 below).
This is a demonstration of how a malicious actor can mint an NFT with the remote image hosted on his server, then airdrop this collectible to a blockchain address (victim) and obtain his IP address, thus compromising his privacy.
However, the consequences are even bigger than privacy leaking.
A highly motivated actor could craft a large number of NFTs, point all of them to a single URL and airdrop to millions of users, thus performing DDoS attacks on that URL at a scale that was never seen before.
Of course, it depends on the size of the user base and time interval on which they open their crypto wallet application. In the case of Metamask — there are 21 million active monthly users.
Why is this important ?
First of all, a botnet with 21 million potential bots would make it 8 times bigger than what the Mirai botnet had (800k — 2.5M infected devices). Mirai’s attack peaked at an unprecedented 1Tbps and is estimated to have used about 145,000 devices during the assault, managing to take down several high-profile websites, including GitHub, Twitter, Reddit, Netflix, Airbnb and many others.
Now imagine 8x this firepower.
At the same time, having a mechanism that allows attackers to reveal the IP address of crypto users based on their blockchain address also exposes the community to unprecedented risks of having their personal data leaked, which could ultimately lead to kidnapping.
We only confirmed this scenario with the MetaMask wallet, but who knows how many crypto wallet implementations are replicating the same behavior in the wild.
Potential mitigation solutions
One of the solutions would be for the crypto wallet application to require explicit user confirmation for accessing abc.xyz domain when fetching the remote image of the NFT, informing the user that this may result in an IP address leak. Another option would be to fetch the remote image in the backend and not in the mobile application, but this still leaves unaddressed the DDoS issue without proper egress rate limits.
This is not an exhaustive solution list, but mainly our first thoughts about how this vulnerability could be mitigated.
I would like to thank Iman Hossini and Cristian Lupascu for helping with this research.
Responsible disclosure and motivation
We discovered this vulnerability in the beginning of December 2021 and after reviewing Metamask’ Mobile security policy, we reached out to them on December 14, 2021.
They told us this is a known issue already under a responsible disclosure timeline and they are actively working on it.
We pushed further by asking for a patch deadline and volunteered to implement the first proposed mitigation solution ourselves, by opening a pull request on Github. They told us they are looking to fix the issue by Q2 2022. For us, it is unacceptable to leave such a large user base at risk for so long, especially if this was known beforehand, as they say.
We tested the iOS Metmask Mobile app v3.7.0 for the flaw, but it seems to be applicable to the Android version as well. Also, re-confirmed the behaviour with the latest version v3.8.0.
We decided to share this information to exert further public pressure, and force MetaMask into reacting faster.
Share it — the community will thank you for it, and we’ll greatly appreciate it!
MetaMask founder, Daniel Finlay also confirmed this issue and promised to fix it ASAP.
Thanks for making it a priority.