False Bidding
hackthebox
Task: Become keyOwner in AuctionHouse contract by calling claimPrize() as top bidder after timeout passes. Solution: Exploit uint32 overflow on timeout variable (Solidity 0.7.x has no overflow protection) by performing 16 bid-withdraw cycles, bypassing blacklist by rejecting ETH in receive() function.
$ ls tags/ techniques/
$ cat /etc/rate-limit
Rate limit reached (20 reads/hour per IP). Showing preview only — full content returns at the next hour roll-over.
False Bidding — HackTheBox
Description
After weeks of stealthy spying, Alex's efforts finally paid off. Not only did she manage to steal the key, but she also overheard the rival group talking about a secret auction being held in a nearby town. According to them, the third and final key to the coveted secret treasure would be up for grabs at the auction. The group was excited by the news and immediately set out for the town. Upon arrival, they found a bustling market filled with all sorts of strange and exotic items. They made their way to the auction house, where they found a large crowd of treasure hunters all vying for the final key. The group watched as the auctioneer began the bidding. They knew that they had to get the key no matter what it took.
Goal: Become keyOwner in the AuctionHouse contract — call claimPrize() as top bidder, provided that timeout has already passed.
Analysis
Contracts
Setup.sol — deploys AuctionHouse with 0.5 ETH. Checks solution: isSolved(player) returns true when TARGET.keyOwner() == player.
AuctionHouse.sol — auction contract with several critical vulnerabilities:
contract AuctionHouse { struct Key { address owner; } struct Bidder { address addr; uint64 bid; } Key private phoenixKey = Key(address(0)); uint32 public timeout; // ← uint32, max ~4.29 billion Bidder[] public bidders; mapping(address => bool) private blacklisted; uint32 public constant YEAR = 31556926; // ← ~31.5 million constructor() payable { timeout = uint32(block.timestamp); // ← ~3.82 billion (2026) _newBidder(msg.sender, 0.5 ether); } receive() external payable { if ((uint64(msg.value) >= 2 * topBidder().bid) && (msg.sender != topBidder().addr) && (!blacklisted[msg.sender]) && (_isPayable(msg.sender))) { _newBidder(msg.sender, uint64(msg.value)); timeout += YEAR; // ← overflow after ~16 iterations } } ...
$ grep --similar
Similar writeups
- [blockchain][free]Magic Vault— hackthebox
- [blockchain][free]Honor Among Thieves— hackthebox
- [blockchain][free]Token to Wonderland— hackthebox
- [blockchain][Pro][Blackbox] Web3_Governance— caplag
- [blockchain][free]Survival of the Fittest— Hack The Box