Malicious actor can win a NFT for free from auction #823
Labels
3 (High Risk)
Assets can be stolen/lost/compromised directly
bug
Something isn't working
duplicate-1323
edited-by-warden
partial-50
Incomplete articulation of vulnerability; eligible for partial credit only (50%)
Lines of code
https://github.com/code-423n4/2023-10-nextgen/blob/main/smart-contracts/AuctionDemo.sol#L104-L120
Vulnerability details
Impact
There are a different reasons why this attack vector is possible. If we consider the M-01 Unchecked return value of low-level
call()/delegatecall()
instances pertaining to theclaimAuction()
function in theAuctionDemo.sol
contract are fixed and the success of the low level calls are checked this will turn into an another way to brick theclaimAuction()
function. Using the same attacking contract and test provided in the POC, as the function will always revert, the attacker won't be able to receive the NFT, or get his funds back but he will also block all other previous bidders funds. This will still be a different issue than the other issue pertaining to bricking theclaimAuction()
that I have summited Auction can be bricked by a malicious user. As the root problem in Auction can be bricked by a malicious user is that a contract can be crafted in such a way that it can't receive an NFT. This will also break an invariant specified by the team:The highest bidder will receive the token after an auction finishes, the owner of the token will receive the funds and all other participants will get refunded.
. The second reason why this is possible is because the require statement in theclaimAuction()
function isrequire(block.timestamp >= minter.getAuctionEndTime(_tokenid) && ...)
and the require statements incancelBid()
andcancelAllBids()
arerequire(block.timestamp <= minter.getAuctionEndTime(_tokenid), "Auction ended");
. The third reason is reentrancy. Whenblock.timestamp
==minter.getAuctionEndTime(_tokenid)
a malicious actor can first executeclaimAuction()
, from a purposely created contract (ReentrancyAuctionDemo.sol
from the POC) and when the NFT is sent to the specified contract executecancelBid()
. This will first sent back the bids of all the users that have bid for the NFT but didn't win, then thecancelBid()
will be executed and the attacker will claim his bid as well. Thus the attacker will get the NFT for free, and the initial owner of the NFT will be left empty handed. Keep in mind this is a different issue from Auction can be gamed by a malicious user because as explained in Auction can be gamed by a malicious user changing the require statementsrequire(block.timestamp <= minter.getAuctionEndTime(_tokenid), "Auction ended");
in bothcancelBid()
andcancelAllBids()
torequire(block.timestamp < minter.getAuctionEndTime(_tokenid), "Auction ended");
, won't fully mitigate the issue. Here the main roots of the issue are the reentrancy combined with the<=
check in the require statements.Proof of Concept
To run the POC first follow the steps in this link: https://hardhat.org/hardhat-runner/docs/advanced/hardhat-and-foundry in order to add foundry to the project.
Create a
AuditorTest.t.sol
file in the test folder and add the following to it:Create a
ReentrancyAuctionDemo.sol
file in the test folder and add the following to it:To run the test use:
forge test -vvv --mt test_ReentrancyAuctionDemo
Tools Used
Manual review & Foundy
Recommended Mitigation Steps
In order to fix the reentrancy vulnerability you can add a
nonReentrant
modifier to theclaimAuction()
or change the require blockrequire(block.timestamp >= minter.getAuctionEndTime(_tokenid) && ...
torequire(block.timestamp > minter.getAuctionEndTime(_tokenid) && ...
. You can also change the require statementsrequire(block.timestamp <= minter.getAuctionEndTime(_tokenid), "Auction ended");
in bothcancelBid()
andcancelAllBids()
torequire(block.timestamp < minter.getAuctionEndTime(_tokenid), "Auction ended");
. But the contract have too many different vulnerabilities, I would recommend to rewrite the whole contract following best practices and suggestions from auditors and most of all utilizing the Pull over Push pattern, as well as aggregating specific users bids.Assessed type
Reentrancy
The text was updated successfully, but these errors were encountered: