The burnNFT() function in 1155tech does not verify ownership before burning NFTs. This allows any user to burn NFTs belonging to another user and receive the underlying tokens. An attacker could drain all value from minted NFTs by burning them without authorization.
Proof of Concept
NFT burning does not verify token ownership. Anyone can burn anyone else's NFTs.
function burnNFT(uint256 _id, uint256 _amount) external {
uint256 fee = getNFTMintingPrice(_id, _amount);
SafeERC20.safeTransferFrom(token, msg.sender, address(this), fee);
_splitFees(_id, fee, shareData[_id].tokensInCirculation);
// The user does not get the proportional rewards for the burning (unless they have additional tokens that are not in the NFT)
uint256 rewardsSinceLastClaim = _getRewardsSinceLastClaim(_id);
rewardsLastClaimedValue[_id][msg.sender] = shareData[_id].shareHolderRewardsPerTokenScaled;
tokensByAddress[_id][msg.sender] += _amount;
shareData[_id].tokensInCirculation += _amount;
_burn(msg.sender, _id, _amount);
SafeERC20.safeTransfer(token, msg.sender, rewardsSinceLastClaim);
// ERC1155 already logs, but we add this to have the price information
emit NFTsBurned(_id, msg.sender, _amount, fee);
}
Lines of code
https://github.com/code-423n4/2023-11-canto/blob/335930cd53cf9a137504a57f1215be52c6d67cb3/1155tech-contracts/src/Market.sol#L234-L236
Vulnerability details
Impact
The
burnNFT()
function in 1155tech does not verify ownership before burning NFTs. This allows any user to burn NFTs belonging to another user and receive the underlying tokens. An attacker could drain all value from minted NFTs by burning them without authorization.Proof of Concept
NFT burning does not verify token ownership. Anyone can burn anyone else's NFTs.
The key logic is in Market.sol#L234-L236
This increments the sender's balance and burns the NFTs without checking that
msg.sender
owns them.An attacker could:
burnNFT()
for NFTs belonging to the victimamount
amount
By repeating this, the attacker can drain all value from minted NFTs.
The problem is it never checks that msg.sender actually owned the NFTs prior to burning.
This means:
A malicious actor could:
The root cause is improperly assuming
msg.sender
owns the NFTs being burned._burn
andtokensByAddress
increment both operate only onmsg.sender
without verifying ownership.This allows:
For example:
Alice owns 100 NFTs representing social tokens
Eve calls
burnNFT(Alice'sTokenId, 50)
The
_burn
call reduces Alice's NFT balance by 50tokensByAddress
increments Eve's underlying tokens by 50Eve has stolen 50 of Alice's tokens by burning her NFTs
The maximum risk here is the total value of NFTs minted can be drained by an attacker.
For instance:
I think this is a critical issue that subverts ownership entirely.
Test demonstrating exploiting the lack of ownership check in
burnNFT()
to steal tokens.Recommended Mitigation Steps
burnNFT()
to verifymsg.sender
owns the NFTs:mintNFT()
to prevent unauthorized minting.Assessed type
Invalid Validation