Bid Beasts

First Flight #49
Beginner FriendlyFoundrySolidityNFT
100 EXP
View results
Submission Details
Severity: high
Valid

Unauthorized NFT Burning Vulnerability - Anyone Can Destroy Any NFT

Root + Impact

Description

  • The normal behavior should require that only the NFT owner or approved operators can burn their own NFTs, following standard ERC721 authorization patterns.

  • The burn() function lacks any authorization checks, allowing any user to permanently destroy any NFT regardless of ownership, approval status, or any other access controls.

function burn(uint256 _tokenId) public {
_burn(_tokenId); // @> Missing authorization check before burning
emit BidBeastsBurn(msg.sender, _tokenId);
}

Risk

Likelihood:

  • Any external account can call the public burn() function with any valid token ID

  • No authentication or authorization barriers exist to prevent malicious burning

  • Attack can be executed in a single transaction

Impact:

  • Complete permanent loss of NFT assets for legitimate owners

  • Destruction of marketplace listings

  • Loss of user funds and trust in the platform

Proof of Concept

This PoC demonstrates how any external account can permanently destroy NFTs belonging to other users. The attack requires no special privileges, approvals, or ownership, highlighting the complete absence of access controls in the burn() function.

function test_burnNFT_UnauthorizedBurn() public {
// Owner mints NFT to SELLER
vm.prank(OWNER);
uint256 tokenId = nft.mint(SELLER);
vm.stopPrank();
// Verify SELLER owns the NFT
assertEq(nft.ownerOf(tokenId), SELLER);
// RANDOM_USER can burn SELLER's NFT without authorization
vm.prank(RANDOM_USER);
nft.burn(tokenId); // This should revert but succeeds
// NFT is permanently destroyed
vm.expectRevert();
nft.ownerOf(tokenId); // Token no longer exists
}

Recommended Mitigation

The fix replaces the vulnerable _burn() call with _update(address(0), _tokenId, _msgSender()). Here's why this works:

  1. _update() is OpenZeppelin's core transfer function that handles minting, transferring, and burning with optional authorization

  2. The third parameter (auth) controls security checks:

    • address(0) = Skip all authorization

    • _msgSender() = Require caller authorization

  3. When auth != address(0), _update() calls _checkAuthorized() which verifies the caller is either:

    • The token owner, OR

    • Approved for this specific token, OR

    • Approved for all tokens of the owner

  4. address(0) as the to parameter indicates this is a burn operation (transfer to zero address)

function burn(uint256 _tokenId) public {
- _burn(_tokenId);
+ _update(address(0), _tokenId, _msgSender());
emit BidBeastsBurn(msg.sender, _tokenId);
}
Updates

Lead Judging Commences

cryptoghost Lead Judge about 1 month ago
Submission Judgement Published
Validated
Assigned finding tags:

BidBeasts ERC721: Anyone Can Burn

In the BidBeasts ERC721 implementation, the burn function is publicly accessible, allowing any external user to burn NFTs they do not own. This exposes all tokens to unauthorized destruction and results in permanent asset loss.

Support

FAQs

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