code-423n4 / 2023-10-nextgen-findings

5 stars 3 forks source link

TokenURI leaves users vulnerable to cross-site scripting (XSS) #1796

Closed c4-submissions closed 11 months ago

c4-submissions commented 11 months ago

Lines of code

https://github.com/code-423n4/2023-10-nextgen/blob/main/smart-contracts/NextGenCore.sol#L353 https://github.com/code-423n4/2023-10-nextgen/blob/main/smart-contracts/NextGenCore.sol#L246

Vulnerability details

Impact

Collection admins can inject arbitrary collection javascript libraries

Vulnerability Explanation

inside NextGenCore#updateCollectionInfo, a collection admin can update their collection with an arbitrary collection library or through a generative script.

   function updateCollectionInfo(uint256 _collectionID, string memory _newCollectionName, string memory _newCollectionArtist, string memory _newCollectionDescription, string memory _newCollectionWebsite, string memory _newCollectionLicense, string memory _newCollectionBaseURI, string memory _newCollectionLibrary, uint256 _index, string[] memory _newCollectionScript) public CollectionAdminRequired(_collectionID, this.updateCollectionInfo.selector) {
        require((isCollectionCreated[_collectionID] == true) && (collectionFreeze[_collectionID] == false), "Not allowed");
         if (_index == 1000) {
            collectionInfo[_collectionID].collectionName = _newCollectionName;
            collectionInfo[_collectionID].collectionArtist = _newCollectionArtist;
            collectionInfo[_collectionID].collectionDescription = _newCollectionDescription;
            collectionInfo[_collectionID].collectionWebsite = _newCollectionWebsite;
            collectionInfo[_collectionID].collectionLicense = _newCollectionLicense;
@>            collectionInfo[_collectionID].collectionLibrary = _newCollectionLibrary;
@>            collectionInfo[_collectionID].collectionScript = _newCollectionScript;
        } else if (_index == 999) {
            collectionInfo[_collectionID].collectionBaseURI = _newCollectionBaseURI;
        } else {
@>            collectionInfo[_collectionID].collectionScript[_index] = _newCollectionScript[0];
        }

 }

When tokenURI() is called, the collection library is used to construct a json string which includes the base64 encoding of the collection library and script being embedded into into an HTML string..

    function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
        //...

        //@audit arbitrary collectionLibrary injected as JS
@>        string memory b64 = Base64.encode(abi.encodePacked("<html><head></head><body><script src=\"",collectionInfo[tokenIdsToCollectionIds[tokenId]].collectionLibrary,"\"></script><script>",retrieveGenerativeScript(tokenId),"</script></body></html>"));
        string memory _uri = string(abi.encodePacked("data:application/json;utf8,{\"name\":\"",getTokenName(tokenId),"\",\"description\":\"",collectionInfo[tokenIdsToCollectionIds[tokenId]].collectionDescription,"\",\"image\":\"",tokenImageAndAttributes[tokenId][0],"\",\"attributes\":[",tokenImageAndAttributes[tokenId][1],"],\"animation_url\":\"data:text/html;base64,",b64,"\"}"));
        return _uri;
    }

Here is what the constructed string looks like:

  data:application/json;utf8,{"name":"here is my name","description":"here is my desc","image":"","attributes":[],"animation_url":"data:text/html;base64,PGh0bWw+PGhlYWQ+PC9oZWFkPjxib2R5PjxzY3JpcHQgc3JjPSJ3d3cubGlicmFyeS5jb20iPjwvc2NyaXB0PjxzY3JpcHQ+d3d3LnNjcmlwdC5jb208L3NjcmlwdD48L2JvZHk+PC9odG1sPg=="}

The arbitrary javascript will then be rendered in a users browser and can result in

  1. Login cookies being stolen
  2. modification of HTML page resulting in users being social engineered
  3. escalation to RCE if access to 0-day or a user is using an outdated browser with publicly available exploits

Tools Used

VIM

Recommended Mitigation Steps

Only allow collection owners to add whitelisted javascript libraries and scripts that are approved by the owner.

Assessed type

Invalid Validation

c4-pre-sort commented 11 months ago

141345 marked the issue as duplicate of #1284

c4-judge commented 11 months ago

alex-ppg marked the issue as unsatisfactory: Out of scope