29288 - [SC - Critical] all NFTs can be stolen by calling VestedZeroNFT...
Submitted on Mar 13th 2024 at 11:27:54 UTC by @EricTee for Boost | ZeroLend
Report ID: #29288
Report type: Smart Contract
Report severity: Critical
Target: https://github.com/zerolend/governance
Impacts:
Direct theft of any user NFTs, whether at-rest or in-motion, other than unclaimed royalties
Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield
Description
Brief/Intro
Wrong implementation in VestedZeroNFT::split() causes users' NFT to be stolen by anyone. Specifically, the problem arises from the ERC721Upgradeable.sol::_requireOwned check in VestedZeroNFT::split() which fails to check the caller is the owner of the NFT, allow anyone to split the pendingAmount and upfrontAmount of any tokenId up to 99%.
Vulnerability Details
In VestedZeroNFT::split():
function split(
uint256 tokenId,
uint256 fraction
) external whenNotPaused nonReentrant {
_requireOwned(tokenId);
// REDACTED by ericteethe _requireOwned check is not implemented correctly. Let's take a look at ERC721Upgradeable.sol::_requireOwned in Openzeppelin:
This function only return the address of the NFT owner but never revert if the caller is not the NFT owner. Therefore, anyone can call VestedZeroNFT::split() with any tokenId and to steal pendingAmount and upfrontAmount up to 99%.
Impact Details
Direct theft of any user rewards.
Recommendation
Consider making the following changes in VestedZeroNFT::split():
References
https://github.com/zerolend/governance/blob/main/contracts/vesting/VestedZeroNFT.sol#L234
Proof of Concept
Install foundry.
Rename the original test folder to
hardhat-testand create a new folder nametest.Add forge-std module to lib with command:
git submodule add https://github.com/foundry-rs/forge-std lib/forge-stdadd
remappings.txtfile incontractsfolder with the following content:
Add
VestedZeroNFT.t.solfile within test folder with the following content:
Finally, run the foundry test with :
forge test --match-test test_StealAmountBySplitting -vv
Foundry Result:
Last updated
Was this helpful?