Closed c4-submissions closed 10 months ago
raymondfam marked the issue as insufficient quality report
raymondfam marked the issue as primary issue
The user will be minted 0 RSETH if the call ever succeeds atomically because lrtOracle.getAssetPrice(asset) will be 0 for a non-existent/supported asset:
rsethAmountToMint = (amount * lrtOracle.getAssetPrice(asset)) / lrtOracle.getRSETHPrice();
Moreover, it's being denied by the modifier onlySupportedAsset(asset).
fatherGoose1 marked the issue as unsatisfactory: Invalid
Lines of code
https://github.com/code-423n4/2023-11-kelp/blob/4b34abc952205e2a34bff893a0de0c75b8052149/src/LRTDepositPool.sol#L116-L144
Vulnerability details
Impact
depositAsset
function allows an arbitrary address to be passed in as theasset
parameter. This opens up the contract to be exploited if a malicious contract address is passed in.Specifically, the problem lies in this line:
Here
transferFrom
is called on the address passed asasset
. If a malicious contract is passed in, itstransferFrom
function could execute arbitrary logic, which could steal funds, manipulate state, etc.This is possible because:
Solidity allows to call functions on any address, regardless of whether it contains code or not. So, calling
IERC20(asset).transferFrom
will attempt to execute thetransferFrom
function in the contract deployed atasset
.There are no checks on
asset
to ensure it is a valid token contract address and not a malicious contract.The
IERC20
interface declaration alone doesn't provide any protections. The calling contract still attempts to execute whatever code is present at that address.Proof of Concept
The depositAsset function in the LRTDepositPool.
This is dangerous because it trusts the
asset
address to be a valid ERC20 token contract. However, an attacker could provide a malicious contract address that executes arbitrary code in itstransferFrom
function. There is no validation on the asset parameter before callingtransferFrom
on it. This allows a malicious contract address to be provided.This is dangerous because it trusts the
asset
address to be a valid ERC20 token contract. However, an attacker could provide a malicious contract address that executes arbitrary code in itstransferFrom
function.If exploited, this would enable an attacker to execute arbitrary code inside
transferFrom
. This could allow them to:transfer
orsend
Attackers could steal potentially unlimited funds that are approved to the LRTDepositPool contract.
Exploitation
An example exploit:
depositAsset
with MaliciousToken addresstransferFrom
in MaliciousToken is executedtransferFrom
drains funds to the attackerTools Used
Manual review
Recommended Mitigation Steps
asset
is not a contract: For example.Address.isContract
to check indepositAsset
:Maintain a whitelist of allowed token addresses that are manually checked to not be contracts before adding to the list.
Use a low-level
call
instead oftransferFrom
so a malicioustransferFrom
can't be executed:The key is to validate
asset
is not a malicious contract before calling any of its functions. Checking!Address.isContract(asset)
or maintaining a whitelist are safer ways to do this.Assessed type
ETH-Transfer