The LiquidationDistributor contract manages the distribution of funds after a liquidation auction is settled. It distributes the received funds to the lenders of the loan. If the lender has implemented the LoanManager interface, it will also call loanLiquidation() on the lender's address. The Pool, when loanLiquidation() is called, will conduct an accounting process to ensure that the received funds are fairly distributed to the depositors.
However, the distribute() function lacks access control. Consequently, an attacker could directly call it with malicious data, leading to incorrect accounting in the Pool.
Proof of Concept
Observe how the loanLiquidation() function is called
As shown above, the principalAddress is not passed in, meaning it will not be validated by the Pool. Therefore, an attacker can simply call the distribute() function with loan.principalAddress set to a random ERC20 token. This token will still be transferred to the Pool. However, the Pool will mistake this token as its asset token (USDC / WETH) and perform the accounting accordingly.
Tools Used
Manual Review
Recommended Mitigation Steps
Only allow Loan contracts to call the distribute() function.
Lines of code
https://github.com/code-423n4/2024-04-gondi/blob/b9863d73c08fcdd2337dc80a8b5e0917e18b036c/src/lib/LiquidationDistributor.sol#L32
Vulnerability details
Impact
The
LiquidationDistributor
contract manages the distribution of funds after a liquidation auction is settled. It distributes the received funds to the lenders of the loan. If the lender has implemented theLoanManager
interface, it will also callloanLiquidation()
on the lender's address. The Pool, whenloanLiquidation()
is called, will conduct an accounting process to ensure that the received funds are fairly distributed to the depositors.However, the
distribute()
function lacks access control. Consequently, an attacker could directly call it with malicious data, leading to incorrect accounting in the Pool.Proof of Concept
Observe how the
loanLiquidation()
function is calledAs shown above, the
principalAddress
is not passed in, meaning it will not be validated by the Pool. Therefore, an attacker can simply call thedistribute()
function withloan.principalAddress
set to a random ERC20 token. This token will still be transferred to the Pool. However, the Pool will mistake this token as its asset token (USDC / WETH) and perform the accounting accordingly.Tools Used
Manual Review
Recommended Mitigation Steps
Only allow Loan contracts to call the
distribute()
function.Assessed type
Access Control