Root Cause: The withdrawAllFailedCredits function incorrectly clears the failedTransferCredits[msg.sender] balance instead of failedTransferCredits[_receiver], despite loading the withdrawal amount from failedTransferCredits[_receiver]. This mismatch allows any user to specify an arbitrary _receiver address (e.g., another user’s address) and withdraw those funds, as no ownership or authorization check is performed. The function’s logic fails to restrict withdrawals to the rightful recipient.
Impact: This vulnerability enables malicious actors to steal funds credited to any address by passing that address as _receiver, draining others’ failedTransferCredits while resetting their own (often empty) balance to zero. This undermines the contract’s financial integrity, exposes users to asset loss, and erodes trust in the marketplace.
The withdrawAllFailedCredits function loads the amount to withdraw from failedTransferCredits[_receiver] but clears the balance of failedTransferCredits[msg.sender]. This allows any user to withdraw funds credited to any _receiver address, regardless of whether they are entitled to those funds. For example, a malicious user could pass another user's address as _receiver to steal their funds, while clearing their own failedTransferCredits balance.
Likelihood: High. The vulnerability is exploitable by any user with access to the contract, requiring only a single transaction with an arbitrary _receiver address. Automated scripts or bots can easily target users with non-zero failedTransferCredits, especially in a busy marketplace.
Impact: High. Unauthorized withdrawals result in direct financial loss for victims, as attackers can drain credited funds. The ability to repeatedly exploit this without affecting the victim’s balance amplifies the damage, potentially leading to significant theft and irreparable trust issues in the platform.
This test demonstrates an unauthorized credit withdrawal vulnerability in BidBeastsNFTMarket::withdrawAllFailedCredits.
An attacker, who does not own any credits, can call withdrawAllFailedCredits(alice) to steal Alice’s credits while resetting their own (empty) credits to zero.
The test confirms that Alice’s credits remain unchanged, and the attacker receives the funds.
Results:
Alice has 10 ether in failedTransferCredits[alice] initially.
Attacker (with no credits) calls withdrawAllFailedCredits(alice).
Attacker receives 10 ether, Alice’s credits remain 10 ether, and the attacker’s credits are set to 0.
This confirms the incorrect logic in the function allowing unauthorized withdrawals.
Add the following to the BidBeastsNFTMarketTest.t.sol test file to reproduce the vulnerability:
Ensure that only the rightful recipient (_receiver) can withdraw their own funds by checking that _receiver == msg.sender.
Clear the balance of _receiver instead of msg.sender.
Example:
withdrawAllFailedCredits allows any user to withdraw another account’s failed transfer credits due to improper use of msg.sender instead of _receiver for balance reset and transfer.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.