Attacker can grief any lender they wish by calling buyLoan() functionality for the loan which is under auction.
Protocol charges the existing debt to new pool and grants msg.sender's pool, a right to interest and claim to collateral instead of granting it to the pool from which the debt was taken.
As result some arbitrary pool ends up paying for someones debt for nothing.
There is auction functionality in the beedle protocol using that lender can initiate dutch auction to sell the loan to another lender.
Ideally interested lender are supposed to call the buyLoan() function with the loanId of loan under auction and their own pool ID, Inorder to buy the loan by paying the debt and interest accrued so far, to the previous lender (Auction Initiator).
This will make them the new loan lender and thus giving them right to future interest and claim to collateral in case of liquidation.
However problem here is that anyone can call buyLoan() with loanId and poolId of any pool they wish once the auction has started, since there isn't any check to validate that, the msg.sender is indeed an owner of the given poolId.
As a result following changes happen :
Previous loan lenders (Auction initiator) pool balance is increased and outstanding reduced (Essentially debt is paid).
Outstanding debt is increased ( and pool.balance is decreased) of the pool with PoolID (victim) provided by attacker (msg.sender).
Now instead of making the pool.lender(victim) the new loan.lender, msg.sender (attacker) is set as new loan.lender.
Now the msg.sender (Attacker) has the right to interest of the said loan as well as claim to the collateral in case of liquidation, as his/her address is set as loan.lender.
Since Attacker does not have the outstanding of the loan.debt on their pool, they wont be able to claim the loan via SiezeLoan(), as it will write off their Outstanding which is not there.
https://github.com/Cyfrin/2023-07-beedle/blob/658e046bda8b010a5b82d2d85e824f3823602d27/src/Lender.sol#L575
Attacker also wont be able to withdraw these funds via removeFromPool() as these are not update into their poolBalance.
Anyway , Attacker does have power to grief any lender they want with this exploit.
Here i have showcase how Attacker address calling the buyLoan() function with someone else pool ID becomes the loan.lender.
To produce this add the final in the current repo and run "forge test"
Anyone can grief any lender they wish for the loan under auction.
Manual review and Foundry
Implement access control validate that, the msg.sender is indeed an owner of the given poolId when calling buyLoan().
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.