On July, 17, 2022, a JavaScript file was manipulated on PREMINT by an unknown third party that led to users being presented with a wallet connection that was malicious.
By 12pm PDT that day, we identified and fixed the compromise and implemented additional measures to prevent similar attacks.
PREMINT is again safe to use; the malicious code has been removed.
We have additional security improvements we are working on.
We are hiring a top-tier external cybersecurity firm to do a full independent investigation, and will update if we’ve missed anything regarding this incident.
Thanks to folks on Twitter for breaking down the compromise for us and giving us a lead on remediations — special callout to @Iamdeadlyz, @0x5749 and many others for dissecting what went on and helping flag the malicious wallets to Etherscan.
This post gives an overview of what we know happened, what we have done to protect our site, and what we’re planning on doing next.
What we know happened
When people create new projects at premint.xyz, they can customize the projects by uploading images — for example setting the primary image for a project to a GIF of the art available in the collection. This image upload process uses a piece of open source software to help facilitate users uploading their custom images to an Amazon S3 bucket.
Unfortunately, the open source tool for image uploads contained a vulnerability that allowed the attacker to evade upload restrictions we configured. As a result, the attacker could write uploaded files to destinations outside the specified directory within the bucket, including a folder that contained a small subset of the JavaScript PREMINT uses.
On July 16, at 7:11 p.m. PDT, the attacker edited the vulnerable JavaScript file to set up the attack. This change made it so premint.xyz included another JavaScript file from a separate, newly registered domain they had full control over. The file was initially benign.
Then, a little after midnight PDT, the attacker launched the attack by serving a full payload of malicious JavaScript from the newly registered domain. This additional code rewrote parts of the PREMINT login and project pages to replace our standard “Connect Wallet” dialog with a different, malicious dialog, which instead requested full access to the victims’ wallets.
It’s important to note that the attackers did not gain access to our web or database servers. This is a good reminder of the scale of damage an attacker can level against a website from access to client side JavaScript, especially in the realm of web3. Full stack security has never been more important.
Short-term remediations we have already made
On the morning of July 17, upon learning of the incident, we put the site in maintenance mode, preventing further access by end users. Then we implemented these additional security measures to prevent this type of incident from reoccurring:
We reverted the problematic JavaScript changes we identified.
We migrated assets to new buckets with heightened security controls.
We added subresource integrity hashes to the included JavaScript assets to prevent further modifications to the source from being accepted by a browser.
We reworked the image uploads process to use a separate, temporary upload bucket that does not serve any public content.
Out of an abundance of caution, we manually expired all of our web sessions, including those users who were not affected or active on the site during the attack.
We have also engaged a top-tier cybersecurity firm to do a full independent investigation of this incident. Upon conclusion of the investigation, we will publish a report of any new information we learn about what happened.
Long-term remediations going forward
PREMINT has always been concerned about security in web3, and we consider it our mission to help users partake in the explosion of creative energy in the NFT space without risking the security of their personal assets.
Over the coming weeks, we will also work with cybersecurity experts to identify opportunities to improve our overall security posture. We will begin by:
Rolling out a strict content security policy and ensuring that resources we include are verified with an integrity hash. We will also cull excess third party dependencies to move towards end to end script ownership.
Revisiting our deploy process and runtime environment to revoke all existing access credentials and reimplement finer-grained controls.
Finally, our third party security vendor will audit our runtime environment as well as our processes for preventing something like this from happening again.