Malicious Fungible Tokens
Weaponizing NFTs and Decentralized Protocols to create immortal C2 Servers
Introduction
In this era, anyone can play the malware game. Aided by LLMs or off-the-shelf solutions like Cobalt Strike, creating malware components or C2 servers has become trivial. It is no longer a matter of who can do it, but rather how creatively it can be done. We see this on a daily basis, with infection chains becoming as complex as they are creative, resorting to all kinds of tricks and sleights of hand: everything is a useful resource in the malware scene.
With the discovery of EtherHiding (a creative technique used by threat actors to persist code snippets related to Infostealers on Binance Smart Chain), I had an intrusive thought haunting me for days:
What if I weaponize blockchain-backed assets to create “immortal” C2 servers?
And after a couple of days, that haunting thought became code, and this experiment was born.
This research was featured at TyphoonCon in Seoul (Korea), Insomni'Hack in Lausanne (Switzerland) & PagedOut! eZine Issue #4. A second chapter called “More Fungible Threats” will be featured at DEF CON 32 Adversary Village in August.
On-Chain vs Off-Chain persistence
The obvious (and boring) way of creating an immortal blockchain-based C2 server would be to go fully on-chain, storing all the information of our asset on a blockchain. This can be achieved by either crafting (and signing) messages on the Ethereum blockchain or minting a fully-on-chain NFT. That being the case, it would be such a trivial process that it wouldn’t deserve an article, let alone a full technical talk.
So, I took the hard way by minting off-chain NFTs using OpenSea, the most popular NFT marketplace. The main benefit of this alternative is lower minting/gas fees due to the smaller transaction size, as metadata (like associated media) is stored somewhere else. Some projects store metadata on their own servers, while others opt for distributed protocols like IPFS (InterPlanetary File System), which is pretty much the standard at OpenSea.
“Interplanetary” != “To the moon”
IPFS is an interesting decentralization protocol trusted by big players like Lockheed Martin and Wikipedia, which I like to define as "a one-way GlusterFS” to simplify it for different audiences. If you have ever worked with replicated filesystems, you may have noticed that any change happening on a node is automatically replicated to the other ones:
If a file is modified at a node, the changes are broadcasted to other nodes.
If a file is created at a node, it is replicated across other nodes.
If a file is deleted, it is deleted across all nodes. But this does not apply to IPFS.
As I said before, IPFS is like a “one-way” GlusterFS. Propagation occurs naturally to guarantee decentralization, but deletion (called “unpining”) requires certain conditions to be met depending on each IPFS provider. Some place files to be deleted into a queue awaiting a specific time window to pass or a given total file size threshold to be exceeded, to invoke a GC (Garbage Collector) which will unpin affected files.
Now, this guarantees us resilience rather than persistence, but there’s more than meets the eye. On IPFS, there’s no technical way to force a node to take down specified content, so nodes may not honour our unpinning requests.
Aside from that, OpenSea uses FileCoin, a protocol which rewards users for sharing files over IPFS. Do you remember the old P2P days when people just downloaded content then deleted it without seeding it back? FileCoin aims to fix that by incentivizing users to share files. This may deepen the idea of nodes not honouring takedown requests (think of a node having the last copy of a file with high demand, being the only supplier).
Equipped with this context, we are able to foresee a good experiment creating malicious and persistent artifacts on NFTs.
A decentralized threat
OpenSea works in a peculiar way:
Uploaded images are processed and converted to AVIF format.
This conversion strips image metadata like EXIF fields or steganographic messages.
Still, both original and processed images are distributed via IPFS.
This means that whatever we place inside our media will still make it to decentralized storage.
With this information, I’ve decided to craft Base64 and ROT-13 encoded payloads which should be reachable with custom malware and hidden in multiple locations:
NFT Description Field (publicly visible).
NFT Traits (publicly visible).
Image EXIF Metadata (invisible).
Image LSB Steganographic Message (invisible).
Both Description and Traits may not seem decentralized at first sight, as this information is not directly stored on the blockchain. But, it is yet again sent in JSON format to IPFS, making it a suitable option to persist instructions.
EXIF Metadata is a tricky vector, as one cannot just place arbitrary contents inside most of the available fields. But there’s a particular one that allows this: ProfileCopyright, defined as “A UTF-8 encoded string containing the copyright information for the camera profile. This string always should be preserved along with the other camera profile tags“.
On the other hand, using the LSB Steganography method is a simple but still current method to quickly smuggle data. Both messages are stripped in the processed AVIF image but remain untouched in the original file still committed to IPFS.
All payloads can be queried using OpenSea’s API, which means all traffic initiated by the malware will hit OpenSea servers or, under specific circumstances (like reading EXIF or Stego messages), random IPFS nodes, maximizing stealth and decentralization.
With this run, we can confidently state that NFTs can be used as a trusted and immortal C2 server for as little as £5 GBP each.
The original Malicious Fungible Tokens collection is still up and running 8 months later, and I’m confident it will remain that way for a long, long time.
Stay safe out there… and don’t get rekt.