Closed c4-submissions closed 11 months ago
141345 marked the issue as duplicate of #1632
141345 marked the issue as duplicate of #843
141345 marked the issue as duplicate of #486
alex-ppg marked the issue as not a duplicate
alex-ppg marked the issue as duplicate of #1782
alex-ppg marked the issue as satisfactory
alex-ppg changed the severity to 3 (High Risk)
Lines of code
https://github.com/code-423n4/2023-10-nextgen/blob/main/smart-contracts/AuctionDemo.sol#L116 https://github.com/code-423n4/2023-10-nextgen/blob/main/smart-contracts/AuctionDemo.sol#L134
Vulnerability details
Bug Description
claimAuction()
in AuctionDemo.sol returns ETH to losing bidders within a for loop and via a low-level call. If the for loop can be forced to revert by running out of gas then the winner won't recieve their NFT, the owner of the token being auctioned won't receive their high bid and losing bidders won't have their bids returned.The
claimAuction()
function in AuctionDemo.sol lines 104-120;Lines 112 (safesTransferFrom), 113 and 116 (low-level calls) all interact (yield) execution to an external EOA or contract.
The losing bidders are repaid on line 116 however the low-level ETH call does not limit the amount of returned data. Even though
bool success
is defined the low-level call will still return an array of bytes from the contract being called (the attacker's contract).An attack contract could be used with a
receive()
function such as the example below, returning an incredibly large byte array that the contract would need to expand in memory causing a revert - memory limit out of gas.Impact
Any revert of the for loop in
claimAuction()
(orcancelAllBids()
) will break the auction and repayment functionality. No token or ETH payments will be made and the ETH will be stuck in the contract if losing bidders don't cancel individual bids before the end of the auction.The attacker can submit some small transactions at the start of the auction, minimising their cost of the attack (bid + gas) and cause any auction to fail and funds would be stuck in the contract.
AuctionDemo.sol has no way for an administrator to withdraw the ETH within the contract. Any call to
claimAuction()
,cancelBid()
orcancelAllBids()
will fail. The auction will have ended andclaimAuction()
is DOS'd.Proof of Concept
The code below includes a test
test_ReturnBomb()
that leverages an attack contractBombTrack
.Execute the test with the following command after installing and configuring foundry;
test_ReturnBomb()
performs the following actions to prove the concept;BombTrack
attack contract to place multiple bids early in the auction.address(100)
places a legitimate bid of 10ETH.address(101)
places a legitimate bid of 11ETH.address(101)
callsclaimAuction()
transferring execution to the attacker'sreceive()
function.receive()
returns a large byte array and the transaction reverts out-of-gas.The output of the forge test looks like this;
Place this in a file like
BombTrack.t.sol
;Tools Used
Vim
Recommended Mitigation Steps
The protocol can either;
cancelBid()
but for retrieving funds after the winner and auction token hold has been paid.excessivelySafeCall
from the ExcessivleySafeCall library and limit the return data the protocol is willing to accept.Personally I would advocate a move to WETH throughout AuctionDemo.sol. The protocol can convert ETH to WETH within
participateToAuction()
and then return it in a for loop or for more safety use a pull model to return WETH.Assessed type
call/delegatecall