20,000 USDC
View results
Submission Details
Severity: high
Valid

Lending.sol#buyLoan() - no authorization for pool owner

Summary

The buyLoan() function is used to buy a loan off of a refinance auction to claim it to a provided it's id, but the effective check for making sure it is the sender's pool is missing.

Vulnerability Details

Unlike other functions regarding pools, checking for ownership of the pool, this function does not implement the necessary check: if (pools[poolId].lender != msg.sender) revert Unauthorized();
A user can buy a loan to an existing pool which isn't owner by him, the new loan lender would be the msg.sender effectively freezing the loan, making it unpayable, since the outstanding loan of the non-existing pool that the new id would point to is 0, reverting on a repay attempt, locking the borrowers collateral.
We update the balances of the loan's old pool and the balances of the pool which's id we provided but we as the malicious msg.sender pay only the protocol fee on the loan and then set it's parameters to the pool we provided + msg.sender as the lender, who may not have a pool or even if he does, it might not be the one he provides as a function parameter. The loan would become unrepayable and thus the malicious user can put it up for auction (outstanding loan still defaults to 0, nobody can buy it off), wait until it ends, seize the loan and steal the collateral.

Impact

Loans up for auction can get stolen by malicious users leading to loss of collateral.

Tools Used

Manual Review

Recommendations

Add the necessary if (pools[poolId].lender != msg.sender) revert Unauthorized(); to make sure the lender is buying the loan to his existing pool.

Support

FAQs

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