The withdrawAllFailedCredits function lacks proper access control. Currently, any caller can specify an arbitrary _receiver address and withdraw its failed credits, even if the caller is not the rightful owner of those funds.
This design flaw allows an attacker to:
Steal funds belonging to other users in failedTransferCredits.
Reenter the function during withdrawal and drain the entire contract balance.
The function should enforce that only the intended recipient can withdraw their credits.
Unauthorized Fund Theft: Attackers can withdraw credits belonging to other users by simply passing their address as _receiver.
Reentrancy Exploit: Since withdrawals transfer ETH, attackers can reenter and repeatedly drain funds.
Complete Loss of Funds: The contract’s entire failedTransferCredits pool can be wiped out.
High User Impact: Honest users will be unable to claim their funds if drained by attackers.
Severity: High – this is a direct loss-of-funds vulnerability.
Scenario:
Victim has a non-zero balance in failedTransferCredits.
Attacker deploys Attacker.sol with the vulnerable market contract.
Attacker calls withdrawAllFailedCredits(address(attackSupporter)).
Due to missing access control, the attacker successfully withdraws the victim’s funds.
Via the receive() fallback, the attacker can reenter and continue draining the contract.
Add an ownership validation check to ensure only the rightful owner can withdraw their credits:
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.