26104 - [SC - Insight] Governance mechanism could be exploited to free...

Submitted on Nov 24th 2023 at 21:40:44 UTC by @cheatcode for Boost | DeGate

Report ID: #26104

Report type: Smart Contract

Report severity: Insight

Target: https://etherscan.io/address/0xf2991507952d9594e71a44a54fb19f3109d213a5#code

Impacts:

  • Permanent freezing of funds from the Default Deposit Contract that requires malicious actions from the DeGate Operator.

Description

Governance mechanism could be exploited to freeze assets permanently in the case of a compromised admin.

Summary

The Timelock contract allows an admin to queue and later execute any transaction. This is a powerful feature intended for governance, giving the ability to perform various actions, including transferring funds. The executeTransaction function in the contract makes a generic call to any address with any provided data payload. This means it can call any function on any contract, including those that might lock funds. It should be noted that contract does not inherently distinguish between safe and unsafe transactions. If the admin queues a transaction that sends funds to a malicious contract designed to lock funds permanently, the Timelock contract has no built-in mechanism to prevent this.

For instance, a transaction could be queued to send Ether to a contract that has no function to withdraw funds, effectively locking them. The security of the Timelock contract heavily relies on the trustworthiness and security of the admin account. If this account is compromised, the attacker can queue malicious transactions. Also, if governance processes are not robust, a malicious or negligent admin could intentionally queue a harmful transaction.

The timelock mechanism delays the execution of transactions, which is a double-edged sword. While it provides time to review transactions, it also means once a malicious transaction is queued, and the delay period begins, there’s a window during which the funds are at risk if no one intervenes. There’s no built-in mechanism in the contract for stakeholders to intervene, cancel, or modify a transaction once it's queued (unless such actions are taken by the admin).

Example Scenario

Imagine the admin queues a transaction sending a large amount of Ether to a contract that functions as a "black hole" – it can receive Ether but has no functionality to transfer it out. Once the Timelock delay elapses and the transaction is executed, those funds become permanently locked in the black hole contract.

Mitigation Strategies

  1. Implementing a whitelist system, where only trusted contracts can be interacted with, could mitigate the risk.

  2. Requiring multiple signatures for queueing transactions can reduce the risk of a single compromised admin account.

  3. Establishing and following a strict governance process for reviewing and approving transactions before they are queued.

  4. Implementing a way for stakeholders to propose and vote on the cancellation of a queued transaction.

Impact

Permanent freezing of funds

Proof of Concept

The vulnerability arises from the potent combination of the Timelock contract's powerful capabilities and the reliance on the admin's role. Without additional safeguards, this setup can potentially be exploited to permanently freeze assets.

Objective

To show how a maliciously crafted transaction, once executed through the Timelock contract, can result in the permanent freezing of funds.

Setup

  1. Deploy the Timelock Contract: Deploy your Timelock contract on a test network.

  2. Deploy a Malicious Contract: Create and deploy a contract designed to freeze funds. This could be a simple contract with a function that can receive and lock funds, without a way to withdraw them.

    contract MaliciousContract {
        function lockFunds() external payable {
            // Funds are received but there are no methods to withdraw them
        }
    }
  3. Tools and Environment: Use a development environment like Remix, Truffle, or Hardhat for deploying and interacting with the contracts.

Execution Steps

  1. As an attacker with control over the admin account (or through a compromised admin account), queue a malicious transaction in the Timelock contract targeting the MaliciousContract with a significant amount of Ether.

    // Parameters for the malicious transaction
    address target = address(maliciousContract);
    uint value = largeEtherAmount;
    string memory signature = "lockFunds()";
    bytes memory data = abi.encodeWithSignature(signature);
    
    // Queue the transaction in Timelock
    timelock.queueTransaction(target, value, signature, data, eta);
  2. Wait for the time lock period (eta) to pass.

  3. Execute the queued transaction after the timelock period.

    timelock.executeTransaction(target, value, signature, data, eta);
  4. Check the balance of the MaliciousContract to confirm that the funds are locked and inaccessible.

Expected Results

  • The MaliciousContract receives and locks the funds sent from the Timelock contract.

  • There is no function in the MaliciousContract to withdraw or release the funds, demonstrating a permanent freeze.

Last updated