Beginner FriendlyFoundry
100 EXP
View results
Submission Details
Severity: high
Valid

Attacker can burn any user's token and mint themselves a NFT

Summary

An attacker can exploit the protocol by burning off other user's tokens and minting themselves NFTs for those tokens by calling the buyPresent function.

Vulnerability Details

This vulnerability exists in the buyPresent function. The function takes an address parameter and then burns a token from that address and mints the caller of the function an NFT. The protocol provides 1e18 worth of Santa Token to EXTRA_NICE user's. This attack can only work on those users who have a balance of 1 or greater amount in SantaTokens.

function buyPresent(address presentReceiver) external {
i_santaToken.burn(presentReceiver);
_mintAndIncrement();
}

Proof of Concept for the exploit.

Overview:

The protocol allows attackers to mint themselves NFTs from the token balance of other users.

Actors:

  • Attacker: The attacker will call the buyPresent function with the address of a user who holds 1 SantaToken in the protocol, then the protocol will burn the SantaToken of the user and mint the attacker with the NFT.

  • Victim: The victim will first collect their present for being EXTRA_NICE and then the victim will lose their SantaToken once the attack is performed.

Working Test Case:

function testBuyPresentAttack() public {
vm.startPrank(santa); // santa will first set the status of the victim as EXTRA_NICE
santasList.checkList(victim, SantasList.Status.EXTRA_NICE);
santasList.checkTwice(victim, SantasList.Status.EXTRA_NICE);
vm.stopPrank();
vm.warp(santasList.CHRISTMAS_2023_BLOCK_TIME() + 1);
vm.startPrank(victim); // acting as victim
santasList.collectPresent(); // victim will first redeem the rewards
assertEq(santasList.balanceOf(victim), 1); // victim gains 1 NFT
assertEq(santaToken.balanceOf(victim), 1e18); // victim gains 1e18 worth of token
vm.stopPrank();
vm.startPrank(attacker); // acting as attacker
santasList.buyPresent(victim); // attacker calls buypresent but passes in the victims address, this burns the 1e18 token of the victim and mints the nft
to the msg.sender
assertEq(santasList.balanceOf(attacker), 1); // the attacker is the msg.sender hence they get a free NFT
assertEq(santaToken.balanceOf(victim), 0); // victim loses their token
vm.stopPrank();
}

Impact

The attacker can call this function on any number of addresses who have collected rewards for being EXTRA_NICE. The attacker will burn off the SantaTokens for all these addresses and for each token, the protocol will mint the attacker a NFT. The Attacker can gain as many NFTs as there are EXTRA_NICE users on the protocol. This disrupts the working of the protocol and makes it impossible for EXTRA_NICE users to purchase NFTs for their friends.

Tools Used

Manual Review, Foundry Test

Recommendations

Set up buyPresent function to burn the msg.sender's token instead of the receivers token. The receiver's address should be passed into the mint function. This will allow the msg.sender to burn their tokens and purchase a NFT for their friend(receiver's address).

Updates

Lead Judging Commences

inallhonesty Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

buyPresent should use msg.sender

Current implementation allows a malicious actor to burn someone else's tokens as the burn function doesn't actually check for approvals.

buyPresent should send to presentReceiver

Support

FAQs

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