Closed c4-bot-6 closed 8 months ago
0xRobocop marked the issue as insufficient quality report
0xA5DF marked the issue as unsatisfactory: Invalid
the attacker's(owner of the account tokens in our case) contract could then trick the 'withdrawBalancesTo' function into withdrawing the balance multiple times
You can't transfer the balance more than once, the function would simply revert (or send 0 balance the second time)
Lines of code
https://github.com/code-423n4/2024-02-althea-liquid-infrastructure/blob/bd6ee47162368e1999a0a5b8b17b701347cf9a7d/liquid-infrastructure/contracts/LiquidInfrastructureNFT.sol#L181
Vulnerability details
Impact
The 'withdrawBalancesTo' function makes an IERC20.transfer call to send balance to 'destination'. However, before updating the contract's internal balance, it checks if the transfer was successful.
' for (uint i = 0; i < erc20s.length; i++) { address erc20 = erc20s[i]; uint256 balance = IERC20(erc20).balanceOf(address(this)); if (balance > 0) { bool result = IERC20(erc20).transfer(destination, balance); require(result, "unsuccessful withdrawal"); amounts[i] = balance; } } emit SuccessfulWithdrawal(destination, erc20s, amounts); } '
This can be exploited by creating a malicious ERC20 contract that re-enters the 'withdrawBalancesTo' function after the transfer. The attacker's(owner of the account tokens in our case) contract could then trick the 'withdrawBalancesTo' function into withdrawing the balance multiple times before the state update occurs, essentially draining the contract's balance.
Proof of Concept
Steps
1.Attacker Deploys Malicious ERC20 Contract:
The contract implements a transferFrom function that allows the attacker to control the execution flow. When the contract calls transferFrom to transfer the balance, the attacker's contract can intercept the call and trigger its own malicious logic.
2.Attacker Initiates Withdrawal:
The attacker calls the withdrawBalancesTo function with the malicious ERC20 contract address as the destination.
3.'withdrawBalancesTo' function executes:
The withdrawBalancesTo function retrieves the balance of the ERC20 token in the contract. It then calls the transferFrom function of the malicious ERC20 contract to transfer the tokens to the attacker's address.
4.Attacker's Contract Re-Enters:
Inside the malicious transferFrom function, the attacker's contract: Calls the withdrawBalancesTo function again recursively, effectively re-entering the vulnerable function. This time, the attacker modifies the behavior of the transferFrom function to return a smaller amount of tokens (e.g., 0) to the contract.
5.Vulnerable Function Continues:
The withdrawBalancesTo function now receives the smaller amount of tokens back from the transferFrom call. Unaware of the re-entrance, it updates its internal balance with the smaller amount.
6.Attacker Drains Funds:
Since the attacker controlled the transferFrom behavior, they can repeat steps 4 and 5 withdrawing the stated balance as long as its not 0 an has not been updated. .
Tools Used
Manual review.
Recommended Mitigation Steps.
Check-before-effect patterns: Consider updating the internal balance before making the external transfer and also having reentrancy guards designed to prevent reentrancy.
Assessed type
Reentrancy