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

Security – ChainOracle allows loading of shares outside of the pointer range. #29

Closed
CryptoKass opened this issue Apr 24, 2024 · 0 comments · Fixed by #31
Closed

Security – ChainOracle allows loading of shares outside of the pointer range. #29

CryptoKass opened this issue Apr 24, 2024 · 0 comments · Fixed by #31
Labels
bug Something isn't working

Comments

@CryptoKass
Copy link
Collaborator

Summary

It's possible to load ANY shares into the ChainOracle so long as they were published in a Celestia block that that matches a committed pointers height.

These third party shares were not published by the publisher, or explicitly committed to in an rblock header. This affects all challenges which rely upon the integrity of the ChainOracle such as ChallengeL2Tx and can lead to malicious rollbacks.

Explanation

When shares are provided to the ChainOracle, they must reference a CelestiaPointer within a committed rollup header.

    function provideShares(
        bytes32 _rblock, //  The rblock (bundle) that the shares are related to.
        uint8 _pointer,  // The index of the Celestia pointer that contains these shares. 
        SharesProof memory _proof
    )

But only the height of pointer is checked against the provide shares/shareProof (The height refers to the block that contains shares). The Share start and Share end fields aren't checked. Meaning shares outside of the pointer can be loaded so long as they are in the same Celestia block.

    require(
        rHead.celestiaPointers[_pointer].height == _proof.attestationProof.tuple.height,
        "rblock height mismatch"
    );

Finally the shares are associated with a given rblock, even though they may not be part of the data the rblock is committing too.

    // store the sharekey to rblock
    _sharekeyToRblock[shareKey] = _rblock;

This association is taken as true in many challenges. For example in ChallengeL2Header:

    // 0. Check that the header headers are part of the correct rblocks
    // - This prevents rolled back l2 headers from being used to defend
    require(
        chainOracle.headerToRblock(_headerHash) == challenge.header.rblock,
        "l2 header not loaded for the given rblock"
    );

There are many side effects of this, the worst of which is a possible attack which allows valid rblocks to be rolled back.

Malicous Rollback Scenario

  • The publisher creates a rollup bundle for blocks 1-100 and submits the blocks to a Celestia block. Then pushing the rollup header to the Canonical State Chain.

  • The Rollup header contains a reference to the location of the shares containing the blocks 1-100 on Celestia (e.g. Celestia Height, StartShare, Length).

  • The Attacker submits a phoney header for block 99 into the same Celestia Block. Later these shares are loaded into the ChainOracle, claiming it is part of the rblock. (The ChainOracle only checks that the shares were published in same Celestia block as mentioned in the rblock header. The ChainOracle does not verify the provide shares are within the given StartShare - EndShare boundary.)

  • Finally the attacker can now call ChallengeL2Tx providing the given rblock, and the l2 header in the ChainOracle. This challenge requires proving the transaction root in the header is correct, but it because the block is phoney, it cannot be proved.

  • The block is rolled backed

Solution

The ChainOracle must verify that the provided shares are within the boundaries matching.

@CryptoKass CryptoKass added the bug Something isn't working label Apr 24, 2024
@Sledro Sledro linked a pull request May 2, 2024 that will close this issue
@Sledro Sledro closed this as completed in #31 May 2, 2024
Sledro added a commit that referenced this issue May 2, 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
Projects
None yet
1 participant