Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A bidder can cancel his bids after the execution of the auctionDemo.claimAuction #1028

Closed
c4-submissions opened this issue Nov 11, 2023 · 4 comments
Labels
3 (High Risk) Assets can be stolen/lost/compromised directly bug Something isn't working duplicate-1323 partial-50 Incomplete articulation of vulnerability; eligible for partial credit only (50%)

Comments

@c4-submissions
Copy link
Contributor

Lines of code

https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/AuctionDemo.sol#L105

Vulnerability details

The auctionDemo contract allows to call the cancelBid or the cancelAllBids even after the execution of the claimAuction if both calls are executed in a block with block.timestamp == minter.getAuctionEndTime(_tokenid). To illustrate it let's assume the following scenario:

  • Let's assume (for simplicity) that there is only one bidder, he made 2 bids (1 ether and 2 ether).
  • He sends two transactions which he hopes will be included in the same block (the order matters) with block.timestamp == minter.getAuctionEndTime(_tokenid):
    • claimAuction - the bidder can call this method since he is the winner and block.timestamp >= minter.getAuctionEndTime(_tokenid)
    • cancelAllBids - the bidder can call this method since block.timestamp <= minter.getAuctionEndTime(_tokenid) and the claimAution doesn't change the status of the bids.
  • If he succeeds then he will get:
    • the NFT as the winner of the auction
    • +1 ether as a refund of the first bid in the claimAution
    • +3 ether in the cancelAllBids since all of his bids can be canceled

So basically the bidder gets the NFT for free and additionally steals 1 ether (in this scenario; it is possible to steal everything with some preconditions) from the auction contract.

The attack above is simplified and therefore is not optimal. To increase the probability of success the bidder can deploy some proxy contract that can:

  • make bids
  • call the claimAuction
  • call the cancelAllBids in the receive if all attack conditions are met:
    • block.timestamp == minter.getAuctionEndTime(_tokenid)
    • it is the refund of the last non-winning bid

In this case, the bidder can send only one transaction, and therefore the probability of success is higher.

Since the timestamp of the next block on Ethereum is quite predictable the probability of this attack is relatively high. If the attack doesn't succeed the bidder will still get the NFT and receive all non-winning bids back so the user doesn't risk losing anything.

It is also worth mentioning that an attacker is not obligated to be a winner to perform this attack. If a bidder is not a winner he can still use the aforementioned proxy contract that will help him to call the cancelAllBids if all conditions are met. But since a bidder can't control the claimAuction call time the probability of success is much lower in this case.

Impact

A malicious user is able to steal ether from the auctionDemo contract with a significant probability.

Proof of Concept

-

Tools Used

Manual Review

Recommended Mitigation Steps

Consider replacing the condition block.timestamp >= minter.getAuctionEndTime(_tokenid) with the strict one block.timestamp > minter.getAuctionEndTime(_tokenid) in the auctionDemo.claimAuction.

Assessed type

Timing

@c4-submissions c4-submissions added 3 (High Risk) Assets can be stolen/lost/compromised directly bug Something isn't working labels Nov 11, 2023
c4-submissions added a commit that referenced this issue Nov 11, 2023
@c4-pre-sort
Copy link

141345 marked the issue as duplicate of #1370

@c4-pre-sort
Copy link

141345 marked the issue as duplicate of #962

@c4-judge
Copy link

c4-judge commented Dec 4, 2023

alex-ppg marked the issue as duplicate of #1323

@c4-judge
Copy link

c4-judge commented Dec 8, 2023

alex-ppg marked the issue as partial-50

@c4-judge c4-judge added the partial-50 Incomplete articulation of vulnerability; eligible for partial credit only (50%) label Dec 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3 (High Risk) Assets can be stolen/lost/compromised directly bug Something isn't working duplicate-1323 partial-50 Incomplete articulation of vulnerability; eligible for partial credit only (50%)
Projects
None yet
Development

No branches or pull requests

3 participants