missing validation means that bids can be stolen from auction contract #425
Labels
3 (High Risk)
Assets can be stolen/lost/compromised directly
bug
Something isn't working
duplicate-1323
edited-by-warden
satisfactory
satisfies C4 submission criteria; eligible for awards
Lines of code
https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/hardhat/smart-contracts/AuctionDemo.sol#L124-L130
https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/hardhat/smart-contracts/AuctionDemo.sol#L115-L117
Vulnerability details
Impact
AuctionDemo::claimAuction
is missing validation, which may cause ETH to be left in the contract. This remaining ETH can be stolen by any bidder given their bid was <= the ETH in the contract.Proof of Concept
This POC will first include a description of the vulnerability, then a coded POC to demonstrate below.
First assume in this scenario there are 4 bidders (Alice, Bob, Charles, Daniel) who each bid 1 eth, 2 eth, 3 eth 4 eth respectively. Let's also assume Daniel also bid 1.5 eth previously. So in total, there are 5 bids.
When the highest bidder (Daniel) or the ADMIN calls
claimAuction
, Daniel is sent the NFT. Alice, Bob & Charles are refunded their ETH as shown below:( Given that the auction end time is known ahead of time, we can expect
block.timestamp==minter.getAuctionEndTime(_tokenid)
)Both of the
call
are missing a validation for thebool success
, so any failed calls will result in stuck ETH in the contract, however this is more significant here:else if (auctionInfoData[_tokenid][i].status == true) { (bool success, ) = payable(auctionInfoData[_tokenid][i].bidder).call{value: auctionInfoData[_tokenid][i].bid}(""); emit Refund(auctionInfoData[_tokenid][i].bidder, _tokenid, success, highestBid); }
Let's assume in this scenario Charles' refund failed for any reason, this means his 3 ETH will remain in the contract.
The problem with this is each before each
call
in the loopauctionInfoData[_tokenid][index].status = false;
is missing.Daniel who won the auction, also receives a
call
to refund his prior bid of 1.5 eth. Daniel is using a smart contract wallet which has areceive
fallback function which is configured to maliciously to callcancelBid
:However as
auctionInfoData[_tokenid][index].status = false;
was not set inclaimAuction
, Daniel's call tocancelBid
is valid and he receives an additional 1.5 ETH from the 3 ETH left in the contract.This is also exploitable by Bob or Alice, who may also be using a smart contract wallet and have configured their
receive
fallback function to callcancelBid
in the case there is remaining ETH.POC:
Copy this test directly in Context
Minting
:Add this to fixtures deployment script:
Create
Thief.sol
:Create SCW.sol
Resulting in this output:
Tools Used
manual
Recommended Mitigation Steps
Firstly I would recommend redesigning this contract to use pull-over-push architecture.
If this architechture remains then:
<
not<=
Assessed type
Invalid Validation
The text was updated successfully, but these errors were encountered: