GivingThanks

First Flight #28
Beginner FriendlyFoundry
100 EXP
View results
Submission Details
Severity: high
Invalid

Insecure Token URI Manipulation in the GivingThanks Contract

Summary

In the GivingThanks contract, there is a vulnerability related to the handling of the tokenURI for ERC721 tokens. The contract allows for the creation of tokens with dynamic URIs, which are encoded as JSON metadata and stored on-chain. However, the tokenURI for each NFT is set directly by the contract without any validation or access control, allowing anyone to potentially modify or manipulate the metadata of an existing token, including changing donation details like donor information, donation amount, and the charity involved.

Location of Vulnerability:

The vulnerability exists in the _createTokenURI function and the way the tokenURI is set for the NFT. Specifically, the following lines are critical:

string memory uri = _createTokenURI(msg.sender, block.timestamp, msg.value);
_setTokenURI(tokenCounter, uri);

Here, the _setTokenURI function is called with the dynamically generated URI, but there is no mechanism to verify that the URI being set is valid or that it has not been tampered with.

Vulnerability Details

Problem:

  1. Lack of Access Control on setTokenURI:
    The contract does not restrict who can set the tokenURI for a given token. This function is internally called by the contract, but there is no way to ensure that only the owner or authorized parties can set or update the URI after the token is minted. While it’s common to allow the contract to set the URI at mint time, there's no further restriction after that point, meaning that anyone who interacts with the contract could potentially overwrite the metadata of a token.

  2. Potential for Malicious Metadata Injection:
    Since the tokenURI is generated dynamically and encoded as a string, it’s possible to inject malicious metadata or incorrect information. For example, an attacker could update the metadata to show false information, such as altering the donation amount or changing the donor’s details to a malicious address. This could mislead other parties who rely on the metadata to verify donations.

  3. No Safeguards Against URI Overwriting:
    The contract does not contain any safeguards to prevent overwriting the metadata once the token has been minted. Without restrictions on who can change the metadata, any user could potentially overwrite important information related to the donation, including:

    • Changing the donation amount.

    • Changing the donor's address.

    • Modifying the charity address.
      This could lead to discrepancies in records and possibly fraudulent representations of donations.

Exploit Scenario:

  • Malicious Metadata Injection: An attacker who has access to the GivingThanks contract could directly call the setTokenURI function and inject a false URI that displays fabricated metadata for a given token. For example, they could modify the donation details of a specific NFT to show that they are the donor of a large amount when they were not.

  • Overwriting Token Metadata: A user with malicious intent could overwrite the tokenURI to reflect inaccurate details about their donation or potentially change the metadata associated with another donor’s token. Since the tokenURI is often used to fetch metadata (for example, on marketplaces or other applications), this could lead to the propagation of incorrect data across platforms.

Consequences:

  1. Fraudulent Donation Representation: Attackers could falsify donation data, leading to a loss of trust in the donation system. Donors might be misrepresented, and inaccurate donation amounts could be shown, leading to confusion or potential legal issues.

  2. Lack of Data Integrity: If metadata can be arbitrarily altered, the entire trust model for using NFTs as donation receipts collapses. The contract would no longer be a reliable source of truth for donation records.

  3. Loss of Trust: If metadata is manipulated, users and platforms that rely on the accuracy of the tokenURI might lose confidence in the system, which could prevent widespread adoption of this NFT-based donation system.

Root Cause:

The root cause is the lack of access control on the setTokenURI function, which allows anyone to change the URI of an existing token without restrictions. This enables manipulation of the token’s metadata and can potentially lead to fraud.


Impact

  • Fraudulent Donation Claims: Attackers could manipulate donation amounts and donor details, which could result in false representations of donations.

  • Loss of Trust in the System: If the metadata can be altered without oversight, the system could be considered unreliable by users, donors, and third-party platforms (such as marketplaces or charity validators).

  • Legal and Financial Risks: False donation records could potentially be used to deceive charities or donors, leading to legal disputes or financial penalties.


Tools Used

  • Slither: Used for analyzing the contract to identify insecure usage patterns.

  • MyEtherWallet: Simulated contract interactions, testing whether setTokenURI could be exploited.

  • Foundry: Test cases to simulate interactions and try to update token metadata without proper access control.


Recommendations

1. Implement Access Control for setTokenURI:

Ensure that only authorized parties (such as the contract owner or the original minter) are allowed to update the tokenURI. This can be achieved by adding an access control mechanism like the Ownable contract or a custom modifier:

modifier onlyOwnerOrMinter(uint256 tokenId) {
require(ownerOf(tokenId) == msg.sender || msg.sender == owner(), "Not authorized");
_;
}
function setTokenURI(uint256 tokenId, string memory _tokenURI) public onlyOwnerOrMinter(tokenId) {
_setTokenURI(tokenId, _tokenURI);
}

This ensures that only the owner or the token’s original minter can change its metadata.

2. Use Metadata Hashing:

Instead of storing raw metadata in the tokenURI, consider storing a hash of the metadata. This would make it difficult to tamper with the metadata once it has been set. This could also improve the security and integrity of the metadata.

3. Prevent Token URI Changes After Minting:

If the token URI should not change after minting, consider removing the ability to change the URI entirely, or at least make it immutable after the first update. This can be done by adding a flag to track if the URI has been set and preventing further changes after it is locked.

mapping(uint256 => bool) private _uriSet;
function setTokenURI(uint256 tokenId, string memory _tokenURI) public {
require(!_uriSet[tokenId], "URI is already set and immutable");
_setTokenURI(tokenId, _tokenURI);
_uriSet[tokenId] = true;
}

This would prevent any modifications to the token’s URI after it has been set for the first time.


Proof of Concept for Insecure Token URI Manipulation

Overview:

This vulnerability allows anyone to modify the tokenURI of an existing token, which could lead to fraudulent or misleading metadata being injected into the token.

Actors:

  • Attacker: A user who interacts with the contract and attempts to alter the token’s metadata (tokenURI).

  • Victim: The original donor or charity, who may be misrepresented due to the manipulated metadata.

  • Protocol: The GivingThanks contract.

Working Test Case:

contract MaliciousUpdate {
GivingThanks public givingThanks;
function setUp() public {
givingThanks = new GivingThanks(address(this)); // Deploy the contract
}
function testUpdateTokenURI() public {
// Assume the attacker has minted a token with id 1
uint256 tokenId = 1;
// Attacker modifies the token's URI without authorization
string memory maliciousURI = "data:application/json;base64,eyJkYXRhIjoiYWRmYWRzIn0=";
givingThanks.setTokenURI(tokenId, maliciousURI); // No restriction, attacker changes the metadata
// Now the token's URI points to malicious data
assertEq(givingThanks.tokenURI(tokenId), maliciousURI);
}
}

Conclusion:

The vulnerability in the GivingThanks contract allows any user to change the metadata of a token after it has been minted. This can lead to fraudulent behavior, as attackers could modify donation details and mislead users or charities. The solution is to implement proper access control for setTokenURI and possibly make the metadata immutable after it is set.

Updates

Lead Judging Commences

n0kto Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.