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

No access control checks for buyLoan() function, which can be exploited to cause DoS of loan/loanId

Summary

No access control checks for buyLoan() function, which can be exploited to cause DoS of loan/loanId, as well as griefing attack.

Vulnerability Details

Anyone can call buyLoan(), but only owner/lender of poolId buying the loan, SHOULD be able to call it, and not anyone else.

But currently it seems non-lender/non-pool owner can call buyLoan() and assign himself as invalid lender of loan after loan was bought & transferred to any other suitable/matching pool and poolId.
This will effectively DoS the loan because the new and invalid lender of the loan will NOT be the owner/legit lender of the pool who's accounting was updated for receiving this loan. So whenever the pool owner/legit lender wants to manage this loan, any relevant function will revert, because msg.sender and loan's invalid lender will be different.

Impact

DoS of loan/loanId, because the valid lender from the pool who bought the loan wont be able to manage the loan because the loan's actual recorded lender, as per loan's struct record, will be a different address, and not equal to the pool's lender address. So the pool's newly acquired loan will have correctly updated the pool's internal accounting via the mapping balances, but the lender of loan will be the wrong address. Not only that, this invalid lender will be able to create a new auction for this loan at any time, and they will also be able to grief attack force either this same victim pool or any other suitable pool to buy this loan from the auction, while the attacker remains the loan owner after successful buyLoan() call. This is via another additional attack vector which I have submitted too.

Tools Used

VSC, manual.

Recommendations

Ensure that caller(msg.sender) of buyLoan() function cannot assign the loanId to any other poolId besides the one that they belong to.

For example:

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

This line can probably be added near the top of the function logic.

Support

FAQs

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

Give us feedback!