Closed c4-submissions closed 11 months ago
141345 marked the issue as duplicate of #962
alex-ppg marked the issue as not a duplicate
alex-ppg marked the issue as duplicate of #1926
alex-ppg marked the issue as satisfactory
alex-ppg changed the severity to 2 (Med Risk)
Lines of code
https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/AuctionDemo.sol#L57 https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/AuctionDemo.sol#L104
Vulnerability details
Impact
There are 2 problems here:
(Note: It is possible that A and B are just two bots placing bids for an auction in order to simply win the token, thus this attack can be both intentional or unintentional from their side. For example, bot A might be programmed to place a bid at the last moment followed by which A can claim (since A knows it is the winner) while bot B might just only place a bid and claim sometime later on)
The issue here originates since claimAuction() uses "<=" instead of "<" to check if current block.timestamp is less than or equal to auctionEndTime. This allows the attacker to perform such an attack, leading to loss for another user.
Note: This issue is different from the previous issue submitted by me (i.e. "Attacker can claim token without providing ETH"). This is because in the previous issue the root cause was either the use of "<=" instead of "<" in functions cancelBid() and cancelAllBids() or auctionDataInfo not being updated to false in claimAuction(), while in this issue the root cause is the use of ">=" instead of ">" in the claimAuction() function. As a Litmus test, we can see that even after solving the previous issue, the current issue here still exists.
Proof of Concept
Here is the whole process:
Address A = Attacker Address B = Another user
At auctionEndTime, both A and B call function participateToAuction() with bids 10 ETH and 11 ETH respectively.
A frontruns B's participateToAuction() call with both his participateToAuction() and claimAuction() calls by providing higher gas in order to move ahead in the mempool.
Here is the order of calls executing now. A's participateToAuction() call is executed first. Here the following occurs:
auctionInfoData[_tokenid]
A's claimAuction() call executes now. Here is what happens:
Now when B's participateToAuction() call executes. The following happens:
auctionInfoData[_tokenid]
Now when B tries to call claimAuction(), the call reverts due to auctionClaim for the _tokenId being true (since A already claimed the token).
Additionally, B's 11 ETH is now permanently locked in AuctionDemo.sol since cancelBid() function reverts due to time now being greater than auctionEndTime (see Line 125). (Note: By the time B realizes he cannot claim the token even though being the highest bidder, it will be too late since time has passed since auctionEndTime due to which cancelBid() reverts)
Coded POC
Here are some points to understand the POC:
forge test --match-test testAttackerCanFrontRunAnotherUserToClaimAuctionAndLockUserETH -vvvvv
forge test --match-test testAttackerCanFrontRunAnotherUserToClaimAuctionAndLockUserETH -vvvvv
command.Tools Used
Manual Review
Recommended Mitigation Steps
The solution is quite straightforward. Change ">=" to ">" in claimAuction() function. This prevents the attacker A from performing such an attack on another address B.
Solution:
Assessed type
MEV