Beginner FriendlyFoundryDeFiOracle
100 EXP
View results
Submission Details
Severity: high
Invalid

Steal underlying tokens from assetToken contract

Summary

Steal an assetTokens underlying tokens

Vulnerability Details

Address.functionCall will execute target.call{value: value}(data) using its context; implying it's executed directly by the Thunderloan in its context, which is dangerous for any access-controlled functions requiring onlyThunderLender. Thunderloan is manipulated to call any contract address, to execute any arbitrary function on that contract, with the permissions of Thunderloan.

Attacker can simply call flashloan

  • borrowing 0 tokens;

  • pass in receiverAddress as Asset Token address for token they want to steal e.g USDC;

  • pass in IERC20 token as address(0) for token input

  • pass in bytes calldata params that ensures its a payload that executes AssetToken.transferUnderlyingTo(address,amount) to transfer an amount of asset token from their preferred address e.g

bytes data = abi.encodeWithSignature(“transferUnderlyingTo(address,uint256)”, attackerAccount, amountToSteal));

The following is how the attack will be allowed to happen as it succeeds in many code aspects in ThunderLoan.sol

AssetToken assetToken = s_tokenToAssetToken[token]; // s_tokenToAssetToken[address(0)] -> default AssetToken address(0)
uint256 startingBalance = IERC20(token).balanceOf(address(assetToken)); // startingBalance -> 0
if (amount > startingBalance) {
revert ThunderLoan__NotEnoughTokenBalance(startingBalance, amount);
} // since borrowing amount = 0 and startingBalance=0 this passes
if (!receiverAddress.isContract()) {
revert ThunderLoan__CallerIsNotContract();
} // since attacker passes receiverAddress as the assetToken address which holds the ERC20 they want to steal
uint256 fee = getCalculatedFee(token, amount); //will result in fee =0 for passing in token=address(0)
assetToken.updateExchangeRate(fee); // will just continue as calling function on zero address kind
assetToken.transferUnderlyingTo(receiverAddress, amount); // just like above
receiverAddress.functionCall(
abi.encodeWithSignature(
"executeOperation(address,uint256,uint256,address,bytes)",
address(token),
amount,
fee,
msg.sender,
params // abi.encodeWithSignature(“transferUnderlyingTo(address,uint256)”, attackerAccount, amountToSteal))
)
); // This implies AssetToken.transferUnderlyingTo(attackerAccount, amountToSteal) is called
// We don't have to worry about checks that prevent stealing underlying token if we had passed token address other than ..
// ...address(0) being prevented by balance checks of account balances since in the below code that follows all checks pass
uint256 endingBalance = token.balanceOf(address(assetToken)); // balance = 0 for address(0)
if (endingBalance < startingBalance + fee) { 0 < 0+0 is false so this passes
revert ThunderLoan__NotPaidBack(startingBalance + fee, endingBalance);
}

By passing in token input = address(0), receiverAddress as assetToken contract, bytes data as function call to transferUnderlyingTo and borrowing amount = 0; attacker can steal and or drain underlying tokens held within an assetToken contract.

Impact

Attacker can use flashloan to transfer underlying token from asset token to their own account therefore stealing or draining asset Token contracts token balances.

Tools Used

  • Manual Analysis

  • Damn Vulnerable DeFi Challenge Truster Solution => https://stermi.medium.com/damn-vulnerable-defi-challenge-3-solution-truster-7a4e00233ecd

Recommendations

  • Enforce zero address checks for token input

  • Enforce amount borrowed is greater than zero

  • Enforce that receiverAddress implements IFlashLoanReceiver to reduce attack surfaces on arbitrary contract

  • Recommended to call executeOperation directly and drop receiverAddress.functionCall(), just like how Aave does it e.g

//execute action of the receiver
receiver.executeOperation(_reserve, _amount, amountFee, _params);
  • Extreme measure is to avoid passing in bytes calldata params which hinders the flexibility of flashloan to receiver but may be safer as its not rare to see flash loans implementing such simple formats
    Or any other such suitable measures to prevent this attack vector

Updates

Lead Judging Commences

0xnevi Lead Judge
over 1 year ago
0xnevi Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Other

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.