hats-finance / Metrom-0xfdfc6d4ac5807d7460da20a3a1c0c84ef2b9c5a2

Smart contracts for the Metrom project.
GNU General Public License v3.0
0 stars 0 forks source link

Malicious campaign owner with multiple campaigns can steal funds from other campaigns by exploiting a specific edge case. #43

Open hats-bug-reporter[bot] opened 6 months ago

hats-bug-reporter[bot] commented 6 months ago

Github username: -- Twitter username: -- Submission hash (on-chain): 0x1a9f25a7bb87c90fb32479655c8f2c5fe1e8f92dffc595fde21488ede82c3bf3 Severity: high

Description: Description\ Malicious campaign owner with multiple campaigns can steal funds from other campaigns by exploiting a specific edge case.

Attack Scenario\ It has been mentioned by the sponser here and here that how backend generates ever-increasing claims for the rewards. This can be exploited by a malicious campaign owner with multiple campaigns.

recoverRewards() function actually accepts the array of ClaimRewardBundle[]. Meaning an campaign owner having multiple campaigns can recover unassigned rewards all at once.

./Metrom.sol

    function recoverRewards(ClaimRewardBundle[] calldata _bundles) external override {
        for (uint256 _i; _i < _bundles.length; _i++) {
            ClaimRewardBundle calldata _bundle = _bundles[_i];

            Campaign storage campaign = _getExistingCampaign(_bundle.campaignId);
            if (msg.sender != campaign.owner) revert Forbidden();
            uint256 _claimedAmount = _processRewardClaim(campaign, _bundle, address(0));

...

Let's consider this scenario:

  1. Owner A want to recover rewards from two campaigns with first campaign having reward token dai and second campaign having reward token WETH/any high token with high price.
  2. The backend generates claim for bundle 1 with reward token dai, a token claim of 100e18(100$ worth of dai) and bundle 2 with reward token WETH, a token claim of 200e18(100e18 previous dai one + 100e18 weth unassigned rewards(around 37000$ worth).
  3. Now, the owner can simply use call recoverRewards() function with only bundle 2 calldata to steal 100e18 more WETH from other campaigns.
  4. Thus, the owner will not be able to recover rewards from campaign with reward token dai, but the owner will only lose around 100$ which is nothing in terms of what he gained(~37000$). But, there are still unassigned rewards and backend may allow to generate calldata again to recover rewards for campaign with dai reward token.

Attachments

  1. Proof of Concept (PoC) File : Theoretical PoC is provided above!
luzzif commented 6 months ago

Not sure how this applies. Claims are token-specific so could you maybe provide a PoC or elaborate on this?