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

User can `buyLoan` with another user's `poolBalance` then auction it leading to loss of funds

Summary

A user can buy a loan using another user's pool since there are no checks to validate if the function caller is the pool's lender.

Vulnerability Details

Function buyLoan allows the caller to buy a loan using someone else's poolBalance, malicious user can then startAuction to auction it off to another legitimate buyer for monetary gain.

Proof of Concept

In function buyLoan, there is no check in place to validate if the function caller is pools[poolId].lender, all that is needed to specify as input is the loanId & poolId of the victim which are both accessible publicly on chain.

function buyLoan(uint256 loanId, bytes32 poolId) public is public and callable by anyone. The malicious user calls it and inputs the loanId & poolId of his victim.

Towards the end of the function we update the loan with the new info and the malicious caller (msg.sender) is assigned as the new [loanId].lender:

// update the loan with the new info
loans[loanId].lender = msg.sender;
loans[loanId].interestRate = pools[poolId].interestRate;
loans[loanId].startTimestamp = block.timestamp;
loans[loanId].auctionStartTimestamp = type(uint256).max;
loans[loanId].debt = totalDebt;

After acquiring the loan, they can startAuction to start a refinance auction where a legitimate buyer can buy the maliciously acquired loan, paying the new lender.

Impact

Once the stolen loan is bought by a user in an auction, this exploit leads to a loss of funds, thus I've classified it as High Impact.

Tools Used

VSCode

Recommendations

To mitigate this vulnerability add a check in the buyLoan function to validate that the function caller is the poolId.lender similar to what is used in addToPool.

if (pools[poolId].lender != msg.sender) revert Unauthorized();

Support

FAQs

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