Canto Identity Subprotocols contest - J4de's results

Subprotocols for Canto Identity Protocol.

General Information

Platform: Code4rena

Start Date: 17/03/2023

Pot Size: $36,500 USDC

Total HM: 10

Participants: 98

Period: 3 days

Judge: leastwood

Total Solo HM: 5

Id: 223

League: ETH

Canto Identity Subprotocols

Findings Distribution

Researcher Performance

Rank: 32/98

Findings: 3

Award: $82.51

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

Awards

19.8705 USDC - $19.87

Labels

bug
2 (Med Risk)
downgraded by judge
satisfactory
edited-by-warden
duplicate-212

External Links

Lines of code

https://github.com/code-423n4/2023-03-canto-identity/blob/main/canto-bio-protocol/src/Bio.sol#L43-L117

Vulnerability details

Summary

// https://github.com/code-423n4/2023-03-canto-identity/blob/main/canto-bio-protocol/src/Bio.sol#L43-L117

The function will generate SVG data and insert the bioText of the specified NFT into it. Front-end developers are likely to insert this SVG data to the webpage, and attackers may use this to carry out XSS attack.

Impact

Attackers may use this to carry out XSS attack.

Proof of Concept

    function testXssString() public {
        string memory XssString = unicode"<script>alert('XSS');</script>";
        uint256 len = bytes(XssString).length;
        bio.mint(XssString);
        uint256 tokenId = bio.numMinted();
        string memory uri = bio.tokenURI(tokenId);
        string memory json = string(Base64.decode(slice(uri, 29, bytes(uri).length)));
        string memory svg = string(Base64.decode(slice(json, 74 + bytes(XssString).length, bytes(json).length - 2)));
    }

The return of tokenURI function is:

data:application/json;base64,eyJuYW1lIjogIkJpbyAjMSIsICJkZXNjcmlwdGlvbiI6ICI8c2NyaXB0PmFsZXJ0KCdYU1MnKTs8L3NjcmlwdD4iLCAiaW1hZ2UiOiAiZGF0YTppbWFnZS9zdmcreG1sO2Jhc2U2NCxQSE4yWnlCNGJXeHVjejBpYUhSMGNEb3ZMM2QzZHk1M015NXZjbWN2TWpBd01DOXpkbWNpSUhCeVpYTmxjblpsUVhOd1pXTjBVbUYwYVc4OUluaE5hVzVaVFdsdUlHMWxaWFFpSUhacFpYZENiM2c5SWpBZ01DQTBNREFnTVRBd0lqNDhjM1I1YkdVK2RHVjRkQ0I3SUdadmJuUXRabUZ0YVd4NU9pQnpZVzV6TFhObGNtbG1PeUJtYjI1MExYTnBlbVU2SURFeWNIZzdJSDA4TDNOMGVXeGxQangwWlhoMElIZzlJalV3SlNJZ2VUMGlOVEFsSWlCa2IyMXBibUZ1ZEMxaVlYTmxiR2x1WlQwaWJXbGtaR3hsSWlCMFpYaDBMV0Z1WTJodmNqMGliV2xrWkd4bElqNDhkSE53WVc0Z2VEMGlOVEFsSWlCa2VUMGlNakFpUGp4elkzSnBjSFErWVd4bGNuUW9KMWhUVXljcE96d3ZjMk55YVhCMFBqd3ZkSE53WVc0K1BDOTBaWGgwUGp3dmMzWm5QZz09In0=

The base64 decoded SVG data is:

<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 400 100"><style>text { font-family: sans-serif; font-size: 12px; }</style><text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle"><tspan x="50%" dy="20"><script>alert('XSS');</script></tspan></text></svg>

After opening this data in a brower, an XSS bullet box pops up.

Tools Used

Manual

Do XSS verification when converting to uri or implement the conversion logic externally (such as the front-end).

#0 - c4-judge

2023-03-28T03:50:47Z

0xleastwood marked the issue as duplicate of #212

#1 - c4-judge

2023-03-30T20:27:00Z

0xleastwood changed the severity to 2 (Med Risk)

#2 - c4-judge

2023-04-11T19:31:31Z

0xleastwood marked the issue as satisfactory

Findings Information

🌟 Selected for report: juancito

Also found by: Chom, J4de, Ruhum, adriro, igingu, leopoldjoy, luxartvinsec, pipoca, popular00, reassor

Labels

bug
2 (Med Risk)
downgraded by judge
partial-50
duplicate-130

Awards

39.8657 USDC - $39.87

External Links

Lines of code

https://github.com/code-423n4/2023-03-canto-identity/blob/main/canto-namespace-protocol/src/Tray.sol#L150-L168

Vulnerability details

Summary

// https://github.com/code-423n4/2023-03-canto-identity/blob/main/canto-namespace-protocol/src/Tray.sol#L150-L168

    /// @notice Buy a specifiable amount of trays
    /// @param _amount Amount of trays to buy
    function buy(uint256 _amount) external {
        uint256 startingTrayId = _nextTokenId();
        if (prelaunchMinted == type(uint256).max) {
            // Still in prelaunch phase
            if (msg.sender != owner) revert OnlyOwnerCanMintPreLaunch();
            if (startingTrayId + _amount - 1 > PRE_LAUNCH_MINT_CAP) revert MintExceedsPreLaunchAmount();
        } else {
            SafeTransferLib.safeTransferFrom(note, msg.sender, revenueAddress, _amount * trayPrice);
        }
        for (uint256 i; i < _amount; ++i) {
            TileData[TILES_PER_TRAY] memory trayTiledata;
            for (uint256 j; j < TILES_PER_TRAY; ++j) {
                lastHash = keccak256(abi.encode(lastHash));
                trayTiledata[j] = _drawing(uint256(lastHash));
            }
            tiles[startingTrayId + i] = trayTiledata;
        }
        _mint(msg.sender, _amount); // We do not use _safeMint on purpose here to disallow callbacks and save gas
    }

Each NFT tiles is hashed from the previous NFT tile, so all tiles are predictable.

Impact

Tiles are used to generate SVG with a fixed algorithm. If tiles are predictable, so are all SVGs. The SVG of each Tray NFT is the only factor that distinguishes it from other NFTs. Whether the SVG looks good or not is an important factor affecting the price of each NFT.

If all SVGs are predictable, the attacker can buy their favorite (higher value) NFT at a base price based on the predicted value.

Proof of Concept

Tools Used

Manual

Add some random factors when generating tiles.

#0 - c4-judge

2023-03-28T18:46:15Z

0xleastwood marked the issue as duplicate of #121

#1 - c4-judge

2023-04-10T13:28:25Z

0xleastwood changed the severity to 2 (Med Risk)

#2 - c4-judge

2023-04-11T19:54:01Z

0xleastwood marked the issue as satisfactory

#3 - c4-judge

2023-04-11T20:03:19Z

0xleastwood marked the issue as duplicate of #121

#4 - c4-judge

2023-04-12T00:54:57Z

0xleastwood marked the issue as duplicate of #130

#5 - c4-judge

2023-04-12T00:56:32Z

0xleastwood marked the issue as partial-50

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter