Open codehawks-bot opened 1 year ago
This issue and all of its duplicates are same as H6: #1166 and its duplicates . Actually so many of issues that are selected for both this (H8) and (H6) are contains both labels. Both issues are talking about stealing loan's from other pools because there is no access control to check if msg.sender is pool's lender. I can provide more details if necessary but I believe it is not hard to see when compared side to side.
H9: #2008 and all of its duplicates are also same as this issue (hence with H6). Although the impact is different the root cause, and solution to issues are same. Because CodeHawks does not have proper documentation regarding duplicate rules yet, I would like to provide rules from other contest platforms documentation. Sherlock:
Issues identifying a core vulnerability can be considered duplicates. Scenario 1: There is a root cause/error/vulnerability A in the code. This vulnerability A -> leads to two attacks paths:
- B -> high severity path
- C -> medium severity attack path/just identifying the vulnerability. Both B & C would not have been possible if error A did not exist in the first place. In this case, both B & C should be put together as duplicates.
All issues which identify the same functional vulnerability will be considered duplicates regardless of effective rationalization of severity or exploit path. However, any submissions which do not identify or effectively rationalize the top identified severity case may be judged as “partial credit” and may have their shares in that finding’s pie divided by 2 or 4 at judge’s sole discretion (e.g. 50% or 25% of the shares of a satisfactory submission in the duplicate set).
Adding to what @kosedogus said. I believe this is a duplicate issue at the root, and the impact stated by this auditor is not exactly right. The auditor stated: Once a borrower repays the loan, the attacker address will be used to compute the poolId. The computed poolId will point to the attacker's pool. This way, the attacker can steal the loan principal (loan.debt) and interest (lenderInterest).
But this assumption is wrong, the borrower wouldn't be able to repay the loan, hence the attacker cannot steal the loan, what would happen is a DOS.
I wrote a POC for this: https://github.com/Cyfrin/2023-07-beedle/issues/1009#issue-1839716687
The reason the borrower wouldn't be able to repay the loan is from the repay
function, the poolId
is recalculated as shown using the attacker's address as the loan.lender
, this would generate an invalid pool Id, and it would revert due to underflow at this line.
Agree with @kosedogus
Being able to buy loans on behalf of other lenders pools opens up a lot of different variations and possible attack vectors. I don't see a reason why every variation should be considered a separate issue when just fixing the root cause fixes all of them.
This just leads to finding 1 issue and describing it in 5 different ways about how something can go wrong and submitting them as separate.
Thanks for all the context here. I think in this case, the attack paths are important, and I lean more towards sherlock's methodology. We will have to update the docs for CodeHawks takes on these. Might have to do some voting.
For this context, I thought the attack paths were different enough to include them as separate findings, which would be similar to Sherlock's "partial credit". Hence why I gave many of these many tags of similar issues.
For the moment, I think these are different findings:
finding-buyLoan-steal-collateral-pool-drain
- that the attacker can make the repay work by having their own poolBecause issues can have multiple tags for v0.1 of CodeHawks, I think this is a partial duplicate of https://github.com/Cyfrin/2023-07-beedle/issues/1166.
We should update the judging for paths like this moving forward. Thank you all for your help on this. At the end of the day, the protocol is going to get the information they need from these findings to fix, and we have opted for the max(oldReward, highReward)
so that there is some lee-way in the prize pools for this first contest.
Any of you down to make a PR to the codehawks docs for what you think make sense in this scenario?
https://github.com/Cyfrin/codehawks
Thank you
Stealing any loan opening for auction through others' lending pool
Severity
High Risk
Relevant GitHub Links
https://github.com/Cyfrin/2023-07-beedle/blob/658e046bda8b010a5b82d2d85e824f3823602d27/src/Lender.sol#L489
https://github.com/Cyfrin/2023-07-beedle/blob/658e046bda8b010a5b82d2d85e824f3823602d27/src/Lender.sol#L518
https://github.com/Cyfrin/2023-07-beedle/blob/658e046bda8b010a5b82d2d85e824f3823602d27/src/Lender.sol#L304
https://github.com/Cyfrin/2023-07-beedle/blob/658e046bda8b010a5b82d2d85e824f3823602d27/src/Lender.sol#L311-L312
Summary
An attacker can steal any loan opening for auction for free by executing the
Lender::buyLoan()
and inputting anyone else'spoolId
as an argument.Vulnerability Details
Root cause: the
buyLoan()
lacks verification that a caller (msg.sender
) must be the new pool's lender.Therefore, an attacker (which can be anyone, including a current pool's lender) can execute the
buyLoan()
to force anyone else's lending pool to pay the loan's total debt for the attacker.Subsequently, the forced pool has to pay for the debt but the attacker will become a new lender for free.
The forced pool has to pay for the debt
: https://github.com/Cyfrin/2023-07-beedle/blob/658e046bda8b010a5b82d2d85e824f3823602d27/src/Lender.sol#L489The attacker will become a new lender
: https://github.com/Cyfrin/2023-07-beedle/blob/658e046bda8b010a5b82d2d85e824f3823602d27/src/Lender.sol#L518Once a borrower repays the loan, the attacker address will be used to compute the
poolId
. The computedpoolId
will point to the attacker's pool. This way, the attacker can steal the loan principal (loan.debt
) and interest (lenderInterest
).The attacker address will be used to compute the poolId
: https://github.com/Cyfrin/2023-07-beedle/blob/658e046bda8b010a5b82d2d85e824f3823602d27/src/Lender.sol#L304The computed poolId will point to the attacker's pool
: https://github.com/Cyfrin/2023-07-beedle/blob/658e046bda8b010a5b82d2d85e824f3823602d27/src/Lender.sol#L311-L312Impact
An attacker can steal any loan opening for auction for free by executing the
buyLoan()
and inputting anyone else'spoolId
as an argument. This vulnerability is considered a high-risk issue.Tools Used
Manual Review
Recommendations
I recommend verifying that a caller (
msg.sender
) of thebuyLoan()
must be the new pool's lender, as shown below.