code-423n4 / 2024-08-phi-validation

0 stars 0 forks source link

Unsanitized Input in mint() Allows JSON Injection, Compromising NFT Metadata Integrity #634

Closed c4-bot-3 closed 1 month ago

c4-bot-3 commented 1 month ago

Lines of code

https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/art/PhiNFT1155.sol#L283 https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/abstract/Claimable.sol#L47 https://github.com/code-423n4/2024-08-phi/blob/8c0985f7a10b231f916a51af5d506dd6b0c54120/src/art/PhiNFT1155.sol#L164

Vulnerability details

SUMMARY:

A confirmed vulnerability has been identified within the Phi Protocol's mint() function in the PhiNFT1155 contract, rooted in the unsanitized handling of user inputs. Specifically, the vulnerability arises from the direct assignment of the imageURI_ parameter, which can be exploited via JSON injection. This flaw allows attackers to introduce malicious metadata, consequently leading to incorrect interpretations by front-end applications. Functions such as claimFromFactory() in PhiNFT1155 and merkleClaim() in related contracts facilitate this issue by enabling the flow of crafted user inputs that compromise metadata integrity. Despite existing signature verification mechanisms, these functions lack adequate input sanitization to prevent such vulnerabilities.

RELEVANT CODE:

// src/PhiNFT1155.sol
function mint(
    address to_,
    uint256 tokenId_,
    uint256 quantity_,
    string calldata imageURI_,
    bytes32 data_
) internal {
    minterData[tokenId_][to_] = data_;
    advancedTokenURI[tokenId_][to_] = imageURI_; // Direct assignment is vulnerable
    if (!minted[to_]) {
        minted[to_] = true;
    }

    _mint(to_, tokenId_, quantity_, "0x00");
}
// src/abstract/Claimable.sol
function merkleClaim() external payable {
    (
        address minter,
        bytes32[] memory proof,
        address ref,
        uint256 tokenId,
        uint256 quantity,
        bytes32 leafPart,
        string memory imageURI
    ) = _decodeMerkleClaimData();

    uint256 artId = getFactoryArtId(tokenId);
    IPhiFactory phiFactory = getPhiFactoryContract();

    bytes memory claimData = abi.encode(minter, ref, artId);

    IPhiFactory.MintArgs memory mintArgs = IPhiFactory.MintArgs(tokenId, quantity, imageURI);
    phiFactory.merkleClaim{ value: msg.value }(proof, claimData, mintArgs, leafPart);
}
// src/PhiFactory.sol
function createArt(
    bytes calldata signedData_,
    bytes calldata signature_,
    CreateConfig memory createConfig_
) external payable nonReentrant whenNotPaused returns (address) {
    _validateArtCreationSignature(signedData_, signature_);
    (, string memory uri_, bytes memory credData) = abi.decode(signedData_, (uint256, string, bytes));
    ERC1155Data memory erc1155Data = _createERC1155Data(artIdCounter, createConfig_, uri_, credData);
    address artAddress = createERC1155Internal(artIdCounter, erc1155Data);
    artIdCounter++;
    return artAddress;
}

VULNERABILITY DETAILS:

The identified vulnerability within the Phi Protocol's mint() function facilitates metadata manipulation through JSON injection. Unsanitized direct assignment of the imageURI_ parameter in this function creates the potential for an attacker to supply a crafted input that alters the intended metadata structure. The indirect paths leading to this function, such as claimFromFactory() and merkleClaim(), allow external calls to incorporate malicious inputs into the mint() process.

Sequence and Integration:

Supporting Evidence:

The severity of this vulnerability is emphasized by its ability to manipulate the onchain identity's credibility, which is a core tenet of the Phi Protocol's mission to accurately showcase user achievements and attributes across the digital space.

TECHNICAL IMPACT

The technical impact of the identified vulnerability within the Phi Protocol's smart contracts primarily revolves around the unsanitized handling of input parameters, specifically the imageURI_ field in the mint() function. This vulnerability opens the door to JSON injection attacks that can manipulate the metadata associated with Non-Fungible Tokens (NFTs) within the protocol.

Exploitation Potential

  1. Metadata Manipulation: The mint() function in the PhiNFT1155 contract assigns the imageURI_ parameter directly to a state variable without validation. This lapse allows attackers to inject malicious JSON into metadata fields. Consequently, the metadata consumed by front-end applications may reflect altered or incorrect information, affecting the NFT's appearance or associated data.

  2. Propagation Through Contracts: The vulnerability is not isolated; it propagates through various interaction points in the protocol. Functions like claimFromFactory() and merkleClaim() from the Claimable and PhiFactory contracts facilitate the flow of unverified inputs, ultimately feeding into the mint() function. These entry points lack sufficient input sanitation, compounding the susceptibility to JSON injection attacks.

  3. Impact on System Integrity: By manipulating the imageURI_, attackers can alter how NFTs are perceived, potentially embedding malicious content that misguides users. This affects the core objective of the Phi Protocol—to construct a reliable and verifiable onchain identity—by subverting the trust and accuracy of the credentials and identities it aims to uphold.

System-Wide Consequences

Code-Level Evidence

The vulnerability is isolated within the mint() function's direct assignment of the imageURI_:

function mint(
    address to_,
    uint256 tokenId_,
    uint256 quantity_,
    string calldata imageURI_,
    bytes32 data_
) internal {
    minterData[tokenId_][to_] = data_;
    advancedTokenURI[tokenId_][to_] = imageURI_; // Direct unsanitized assignment
    if (!minted[to_]) {
        minted[to_] = true;
    }

    _mint(to_, tokenId_, quantity_, "0x00");
}

Conclusion

In addressing the technical impact of this vulnerability, the protocol must employ input validation mechanisms to safeguard against JSON injection attacks. This should involve stringent checks at all points where user-controlled data, such as imageURI_, enters the system, ensuring the integrity and reputation of digital identities minted on the Phi Protocol.

PROOF OF CONCEPT

Explanation

This Proof of Concept (PoC) illustrates how an attacker can exploit the unsanitized handling of the imageURI_ parameter in the mint() function of the PhiNFT1155 contract. By crafting a specific malicious input, an attacker can inject unwanted JSON fields into the NFT metadata, affecting how the metadata is perceived and displayed by front-end applications.

The vulnerability arises due to the direct assignment of user inputs without validation, particularly the imageURI_. By leveraging functions such as merkleClaim() and claimFromFactory(), which eventually call the mint() function, attackers can transmit malicious inputs into the system. The PoC will demonstrate how a manipulated imageURI_ can alter an NFT's metadata.

Step-by-Step Vulnerability Exploitation:

  1. Target Function:

    • mint() in the PhiNFT1155 contract.
    • Directly assigns imageURI_ without sanitization.
  2. Input Preparation:

    • Craft a malicious imageURI_ that includes JSON injection.
    • Example of crafted input:
      string memory maliciousImageURI = '", "name": "Exploited NFT", "image": "https://maliciouscontent.com"';
  3. Function Calling Sequence:

    • merkleClaim() or claimFromFactory() can initiate the mint() call, passing the malicious imageURI_.
    • These functions do not sanitize imageURI_, forwarding the malicious payload to mint().
  4. Injected Content and Metadata Alteration:

    • The prepared imageURI_ input manipulates JSON metadata seen by any systems using this NFT's URI.
    • Effectively, the NFT's intended metadata could be overridden by injected data, misleading front-end interfaces and users.
  5. Proof of Manipulation:

    • Upon execution, the crafted input injects new fields into the metadata.
    • Front-end applications, expecting standard metadata, may display incorrect information or warnings.

Underlying Function Relationships:

Code Explanation:

pragma solidity ^0.8.25;

interface IPhiNFT1155 {
    function mint(
        address to_,
        uint256 tokenId_,
        uint256 quantity_,
        string calldata imageURI_,
        bytes32 data_
    ) external;
}

contract ExploitMint {
    function executeExploit(address phiNFT1155Address, uint256 tokenId, uint256 quantity) external {
        // Craft a JSON injection string exploiting the unsanitized handling of imageURI_
        string memory maliciousImageURI = '", "name": "Exploited NFT", "image": "https://maliciouscontent.com"';

        // Interface call to trigger the minting process with malicious imageURI_
        IPhiNFT1155(phiNFT1155Address).mint(
            msg.sender,     // Attacker's address
            tokenId,        // Target NFT token ID
            quantity,       // Quantity to mint
            maliciousImageURI, // Malicious input leading to metadata manipulation
            bytes32(0)      // Placeholder for data (not used in the injection)
        );
    }
}

Impact Verification:

This Proof of Concept vividly demonstrates the critical nature of input sanitization by highlighting the easy manipulation of NFT metadata when user input is not properly validated.

Assessed type

en/de-code

Pedroais commented 3 weeks ago

Hi @fatherGoose1, while the writing of this issue is too long, it's clearly duplicate of https://github.com/code-423n4/2024-08-phi-findings/issues/73 which is sponsor confirmed. Please take a look, the issue is exactly the same and clearly shows a user can freely chose the ImageUri without autorization since it's not included in the signature check.

fatherGoose1 commented 2 weeks ago

Agreed, will dupe