Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lenders can avoid sanction restrictions in FixedTermLoanHooks by transferring to another account #12

Open
c4-bot-2 opened this issue Sep 18, 2024 · 7 comments
Labels
bug Something isn't working downgraded by judge Judge downgraded the risk level of this issue grade-a primary issue Highest quality submission among a set of duplicates QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax 🤖_primary AI based primary recommendation 🤖_44_group AI based duplicate group recommendation sponsor disputed Sponsor cannot duplicate the issue, or otherwise disagrees this is an issue sufficient quality report This report is of sufficient quality

Comments

@c4-bot-2
Copy link
Contributor

Lines of code

https://github.com/code-423n4/2024-08-wildcat/blob/fe746cc0fbedc4447a981a50e6ba4c95f98b9fe1/src/access/FixedTermLoanHooks.sol#L848-L868
https://github.com/code-423n4/2024-08-wildcat/blob/fe746cc0fbedc4447a981a50e6ba4c95f98b9fe1/src/access/AccessControlHooks.sol#L812-L825

Vulnerability details

Impact

Lenders can evade sanctioning restrictions by sending their tokens to another of their addresses and continue earning interest in FixedTermLoanHooks.
Hooks templaets have inconsistent security levels.

Vulnerability Details

Although the documentation says that the two hooks templates AccessControlHooks & FixedTermLoanHooks are the "exact same" and lists the ways in which they are not; see [here](The https://github.com/code-423n4/2024-08-wildcat/blob/fe746cc0fbedc4447a981a50e6ba4c95f98b9fe1/docs/hooks/templates/Fixed%20Term%20Loan%20Hooks.md?plain=1#L5C1-L5C55), this is not the case with respect to withdrawal security as we will see below.

The isKnownLender flag is set when a lender deposits and is never removed.
It serves two purposes:
1. Prevents the borrower from blocking withdrawals from the market by removing genuine lender's credentials
2. Prevents unknown accounts from being able to withdraw tokens from the market

In AccessControlHooks if the onQueueWithdrawal hook is enabled a withdrawing user must be a knownLender or have an active credential.

        LenderStatus memory status = _lenderStatus[lender];

        if (
          !isKnownLenderOnMarket[lender][msg.sender] && !_tryValidateAccess(status, lender, hooksData)
        ) {
          revert NotApprovedLender();
        }

In FixedTermLoanHooks however; isKnownLender is only checked if both the hook is enabled AND market.withdrawalRequiresAccess is active.
If the hook is active but the market.withdrawalRequiresAccess = FALSE users with no credentials are allowed to withdraw.

This allows a user who suspects they may be sanctioned in the future to transfer all of their scaledTokens to another account of theirs and withdraw any time without restriction; avoiding having their funds sent to an escrow.

        LenderStatus memory status = _lenderStatus[lender];

 >>>    if (market.withdrawalRequiresAccess) {
          if (
            !isKnownLenderOnMarket[lender][msg.sender] && !_tryValidateAccess(status, lender, hooksData)
          ) {
            revert NotApprovedLender();
          }
        }

POC

Add the test function below to FixedTermLoanHooks.t.sol and run:

Users with no credentials can withdraw
  function test_POC_1() external {

    address bob = address(10);
    address market = address(1);

    DeployMarketInputs memory inputs;
    MarketState memory state;

    // Don't activate onQueueWithdrawal hook
    inputs.hooks = EmptyHooksConfig.setHooksAddress(address(hooks));
    hooks.onCreateMarket(
      address(this), 
      market,    
      inputs,        
      abi.encode(block.timestamp + 365 days, 1e18)
    );

    // Withdrawer does not have the isKnownLender credential
    bool isKnownLender = hooks.isKnownLenderOnMarket(bob, market);
    assertEq(isKnownLender, false);

    // Function will not revert though Bob is not a known lender
    vm.prank(market);
    vm.warp(block.timestamp + 366 days);
    hooks.onQueueWithdrawal(bob, 0, 1, state, '');
  }

Tools Used

Manual Review
Foundry Testing

Recommendations

Only known lenders should be able to withdraw if the hook is enabled:



        LenderStatus memory status = _lenderStatus[lender];

        if (market.withdrawalRequiresAccess) {
            // Requires access, must satisfy either condition
            if (
                !isKnownLenderOnMarket[lender][msg.sender] && 
                !_tryValidateAccess(status, lender, hooksData)
            ) {
                revert NotApprovedLender();
            }
        } else {
            // Doesn't require access, must be a known lender
            if (!isKnownLenderOnMarket[lender][msg.sender]) {
                revert NotApprovedLender();
            }
        }

Assessed type

Access Control

@c4-bot-2 c4-bot-2 added 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working labels Sep 18, 2024
c4-bot-10 added a commit that referenced this issue Sep 18, 2024
@c4-bot-12 c4-bot-12 added 🤖_44_group AI based duplicate group recommendation 🤖_primary AI based primary recommendation labels Sep 18, 2024
@laurenceday
Copy link

@howlbot-integration howlbot-integration bot added primary issue Highest quality submission among a set of duplicates sufficient quality report This report is of sufficient quality labels Sep 20, 2024
@laurenceday laurenceday added the sponsor disputed Sponsor cannot duplicate the issue, or otherwise disagrees this is an issue label Sep 20, 2024
@c4-judge
Copy link
Contributor

c4-judge commented Oct 3, 2024

3docSec marked the issue as unsatisfactory:
Invalid

@c4-judge c4-judge closed this as completed Oct 3, 2024
@c4-judge c4-judge added the unsatisfactory does not satisfy C4 submission criteria; not eligible for awards label Oct 3, 2024
@3docSec
Copy link

3docSec commented Oct 3, 2024

Hi @laurenceday would you mind having another look at this finding?

The point is frontrunning sanctions by transferring to another "unknown" address and keep interacting with the protocol from there, so the sanctions check at transfer time won't save the day if I get this right

@d1ll0n
Copy link

d1ll0n commented Oct 3, 2024

That'd only be possible if they knew the sanctions would be recorded soon but haven't yet, which IMO is not really something we can do anything about, or likely enough to be worth doing anything about

@3docSec
Copy link

3docSec commented Oct 4, 2024

Okay so the finding is valid.
Wrt severity, I think L is appropriate, because there is no impact on functionality or funds. Blockbuster tokens like USDC have the same issue - before being blocked one can give away tokens to some other address and keep using them. It is reasonable to expect the new address will be sanctioned too.

@c4-judge c4-judge added downgraded by judge Judge downgraded the risk level of this issue QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax and removed 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value labels Oct 4, 2024
@c4-judge
Copy link
Contributor

c4-judge commented Oct 4, 2024

3docSec changed the severity to QA (Quality Assurance)

@c4-judge
Copy link
Contributor

c4-judge commented Oct 4, 2024

3docSec marked the issue as grade-b

@c4-judge c4-judge reopened this Oct 4, 2024
@c4-judge c4-judge added grade-b and removed unsatisfactory does not satisfy C4 submission criteria; not eligible for awards labels Oct 4, 2024
@C4-Staff C4-Staff added grade-a and removed grade-b labels Oct 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working downgraded by judge Judge downgraded the risk level of this issue grade-a primary issue Highest quality submission among a set of duplicates QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax 🤖_primary AI based primary recommendation 🤖_44_group AI based duplicate group recommendation sponsor disputed Sponsor cannot duplicate the issue, or otherwise disagrees this is an issue sufficient quality report This report is of sufficient quality
Projects
None yet
Development

No branches or pull requests

7 participants