Canto Identity Protocol contest - gzeon's results

Protocol Aggregating Protocol (PAP) for standardizing on-chain identity.

General Information

Platform: Code4rena

Start Date: 31/01/2023

Pot Size: $36,500 CANTO

Total HM: 5

Participants: 38

Period: 3 days

Judge: berndartmueller

Total Solo HM: 2

Id: 212

League: ETH

Canto Identity Protocol

Findings Distribution

Researcher Performance

Rank: 1/38

Findings: 2

Award: $6,680.61

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: popular00

Also found by: gzeon

Labels

bug
3 (High Risk)
satisfactory
duplicate-67

Awards

17055.7352 CANTO - $5,138.93

External Links

Lines of code

https://github.com/code-423n4/2023-01-canto-identity/blob/dff8e74c54471f5f3b84c217848234d474477d82/src/CidNFT.sol#L178-L182

Vulnerability details

Impact

CidNFT.mint(bytes[]) allow user to mint and add subprotocol NFTs directly after minting. The _addList args to the add call include the _cidNFTID param, which can change if there are other mint before the user's transaction. Additionally, CidNFT.add only check if the cid nft is owned by msg.sender, OR if the msg.sender is approved to to cidnft; Thus, an attacker can front run the mint and add call, approve the victim to his newly mint cid nft, let the victim tx to be executed and therefore assigning his subprotocol nft to the attacker's cid nft, and revoke the approval.

Unlike the DOS attack, this is high risk because asset can be stolen.

Proof of Concept

  1. Bob want to mint cid NFT with id = 1, and add subprotocol DOGE as PRIMARY entry in a single call using CidNFT.mint(bytes[])
  2. Alice frontrun bob to mint NFT with id = 1
  3. Alice approve Bob to use the NFT
  4. Bob's transaction in (1) is executed, but cid nft id = 2 is minted, however, the add call still have cidnftid = 1
  5. Bob's subprotocol DOGE nft is added to Alice's NFT
  6. Alice revoke Bob's approval to his cid NFT
  7. Alice call remove and stole Bob's subprotocol NFT

https://github.com/code-423n4/2023-01-canto-identity/blob/dff8e74c54471f5f3b84c217848234d474477d82/src/CidNFT.sol#L147-157

function mint(bytes[] calldata _addList) external { _mint(msg.sender, ++numMinted); // We do not use _safeMint here on purpose. If a contract calls this method, he expects to get an NFT back bytes4 addSelector = this.add.selector; for (uint256 i = 0; i < _addList.length; ++i) { ( bool success, /*bytes memory result*/ ) = address(this).delegatecall(abi.encodePacked(addSelector, _addList[i])); if (!success) revert AddCallAfterMintingFailed(i); } }

https://github.com/code-423n4/2023-01-canto-identity/blob/dff8e74c54471f5f3b84c217848234d474477d82/src/CidNFT.sol#L178-L182

if ( cidNFTOwner != msg.sender && getApproved[_cidNFTID] != msg.sender && !isApprovedForAll[cidNFTOwner][msg.sender] ) revert NotAuthorizedForCIDNFT(msg.sender, _cidNFTID, cidNFTOwner);

Instead of a self delegate call, use a switch statement with abi.decode to support different type of entry, and call the internal function according with the newly generated cid nft id.

#0 - c4-judge

2023-02-09T11:54:15Z

berndartmueller marked the issue as duplicate of #67

#1 - c4-judge

2023-02-17T21:03:36Z

berndartmueller marked the issue as satisfactory

Findings Information

🌟 Selected for report: shenwilly

Also found by: gzeon

Labels

bug
2 (Med Risk)
satisfactory
duplicate-115

Awards

5116.7206 CANTO - $1,541.68

External Links

Lines of code

https://github.com/code-423n4/2023-01-canto-identity/blob/dff8e74c54471f5f3b84c217848234d474477d82/src/CidNFT.sol#L143-L157

Vulnerability details

Impact

CidNFT.mint(bytes[]) allow user to mint and add subprotocol NFTs directly after minting. The _addList args to the add call include the _cidNFTID param, which can change if there are other mint before the user's transaction.

Proof of Concept

An attacker can DOS a user's mint and add by front-running their mint by another mint, bumping the cid nft id.

https://github.com/code-423n4/2023-01-canto-identity/blob/dff8e74c54471f5f3b84c217848234d474477d82/src/CidNFT.sol#L143-L157

/// @notice Mint a new CID NFT /// @dev An address can mint multiple CID NFTs, but it can only set one as associated with it in the AddressRegistry /// @param _addList An optional list of encoded parameters for add to add subprotocol NFTs directly after minting. /// The parameters should not include the function selector itself, the function select for add is always prepended. function mint(bytes[] calldata _addList) external { _mint(msg.sender, ++numMinted); // We do not use _safeMint here on purpose. If a contract calls this method, he expects to get an NFT back bytes4 addSelector = this.add.selector; for (uint256 i = 0; i < _addList.length; ++i) { ( bool success, /*bytes memory result*/ ) = address(this).delegatecall(abi.encodePacked(addSelector, _addList[i])); if (!success) revert AddCallAfterMintingFailed(i); } }

Instead of a self delegate call, use a switch statement with abi.decode to support different type of entry, and call the internal function according with the newly generated cid nft id.

#0 - c4-judge

2023-02-09T12:05:38Z

berndartmueller marked the issue as duplicate of #67

#1 - c4-judge

2023-02-17T21:16:18Z

berndartmueller marked the issue as not a duplicate

#2 - c4-judge

2023-02-17T21:17:11Z

berndartmueller marked the issue as duplicate of #115

#3 - c4-judge

2023-02-17T21:17:22Z

berndartmueller marked the issue as satisfactory

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