📍Cross-Site Scripting (XSS) Vulnerability via SVG Construction in Smart Contracts

Introduction

SVG (Scalable Vector Graphics) is an XML-based file format used for rendering two-dimensional vector graphics. While it is a powerful tool for creating dynamic images in web applications, it can also be an avenue for Cross-Site Scripting (XSS) attacks. This vulnerability arises because SVG files can embed malicious JavaScript, leading to potential security risks when these files are rendered in web browsers.

In the context of smart contracts, specifically in a Solidity-based contract that constructs and serves SVGs, a lack of sanitization for user-provided input can lead to serious consequences. This tutorial explores how an SVG construction vulnerability in a smart contract can lead to an XSS attack, with a special focus on how this issue can arise in NFT (Non-Fungible Token) projects that generate SVGs.


What is Cross-Site Scripting (XSS)?

XSS is a type of injection attack where an attacker injects malicious scripts (usually JavaScript) into a web page viewed by other users. In this case, when users view the injected script, it gets executed in their browser, potentially leading to:

  • Stealing session cookies: An attacker can access and steal a user's session cookies, potentially allowing account takeover.

  • Malicious redirection: The attacker can redirect users to malicious websites.

  • Denial of Service (DoS): An attacker can cause performance degradation or crashes by overwhelming the browser with malicious code.

SVGs, being XML-based, allow embedding of JavaScript using <script> tags or other inline event handlers (e.g., onload, onclick). If an SVG file is not properly sanitized, malicious users can embed harmful code within the SVG, which will be executed when viewed by users on NFT marketplaces like OpenSea or other platforms.


Vulnerability in SVG Construction Contracts

In Solidity, smart contracts can be designed to generate SVGs dynamically, especially in the context of NFTs where visual representation is often crucial. However, this also opens up opportunities for XSS if the inputs that contribute to the SVG generation are not properly sanitized.

Example Scenario: NFTTokenURIScaffold Contract

Let’s consider the following scenario:

  • An NFT contract dynamically generates SVGs to represent different assets.

  • The SVG is generated using a function like NFTSVG.constructSVG in Solidity.

  • The input used in the SVG construction includes user-provided data, such as the ERC20 token symbol.

  • An attacker creates an ERC20 token with a malicious token symbol containing JavaScript.

The Vulnerability:

In this scenario, the malicious ERC20 token symbol is passed as input to the NFTSVG.constructSVG function. If the input is not sanitized, the SVG generated by the contract will embed the malicious JavaScript code. When this SVG is loaded in any web browser (for instance, when viewed on a marketplace like OpenSea), the malicious code will execute, leading to an XSS attack.


Example of XSS via SVG Construction

Step 1: Crafting a Malicious ERC20 Token Symbol

Suppose an attacker deploys an ERC20 token with a symbol containing JavaScript code. Here's an example of a malicious ERC20 symbol:

contract MaliciousERC20 is ERC20 {
    constructor() ERC20("Malicious Token", "<svg><script>alert('XSS');</script></svg>") {}
}

In this example, the ERC20 symbol contains SVG syntax that embeds a <script> tag with JavaScript code (alert('XSS')). This code will execute if the SVG is rendered in a browser.

Step 2: Interaction with an NFT Contract

The attacker now uses this malicious token as an asset in an NFT contract that dynamically generates an SVG using the token's symbol. For example:

contract NFTTokenURIScaffold {
    function constructTokenURI(address asset) public view returns (string memory) {
        string memory svg = NFTSVG.constructSVG(ERC20(asset).symbol());
        return svg;
    }
}

Here, the constructTokenURI function fetches the ERC20 token's symbol using ERC20(asset).symbol() and passes it to NFTSVG.constructSVG. If no sanitization is applied to the symbol(), the malicious JavaScript will be included in the generated SVG.

Step 3: Rendering the SVG

When the SVG is rendered on a platform (like OpenSea), the malicious JavaScript executes. This can lead to:

  • Stealing user cookies: The attacker can steal user sessions or authentication tokens.

  • Redirecting users: Users can be redirected to phishing sites.

  • Running arbitrary code: Malicious actions like downloading files or executing additional scripts.

Mitigation Steps: Preventing XSS via SVG in Solidity

Preventing XSS vulnerabilities in Solidity-based contracts requires careful handling of user-provided input. Unfortunately, there are no Solidity libraries at the time of writing that directly sanitize strings or inputs to prevent XSS. Therefore, developers need to be extra cautious when generating SVGs or HTML-like outputs within their contracts.

Mitigation Strategies:

  1. Avoid Using User-Provided Input in SVGs:

    • One of the simplest solutions is to avoid including user-provided input (like ERC20 symbols) in the generated SVGs. Instead, use hardcoded values or restrict the input sources to trusted entities.

  2. Sanitize Input Before Including It in SVGs:

    • Although Solidity lacks a native sanitization library, external systems (such as off-chain services) could sanitize the input before passing it to the smart contract.

  3. Validate Inputs Rigorously:

    • Implement validation logic to ensure that symbols and other user-provided inputs do not contain malicious characters (e.g., <, >, or ").

    • For example, reject ERC20 symbols that contain any potentially dangerous characters.

  4. Escape Dangerous Characters in SVG Construction:

    • If dynamic data must be included in SVGs, escape potentially dangerous characters before including them in the SVG construction.

Conclusion

XSS vulnerabilities, especially through dynamic SVG construction in smart contracts, are a growing concern, especially in NFT ecosystems where visual representation is critical. A malicious actor could exploit this to inject JavaScript into an SVG, leading to attacks when the SVG is rendered on external platforms.

Developers building smart contracts that handle user-generated content, such as ERC20 symbols or metadata, must take care to sanitize inputs and avoid exposing the contract to XSS vulnerabilities. While Solidity does not provide native tools for handling XSS, developers can employ off-chain validation, escaping strategies, and input validation to mitigate the risks.

By following these best practices, you can reduce the risk of exposing your smart contract to XSS attacks and ensure a more secure decentralized ecosystem.

Last updated