GalloDaSballo - l2BlockNumber()` can be used to prevent creating new Games #95
Labels
Duplicate
A valid issue that is a duplicate of an issue with `Has Duplicates` label
Medium
A valid Medium severity issue
Reward
A payout will be made for this issue
Sponsor Confirmed
The sponsor acknowledged this issue is valid
Won't Fix
The sponsor confirmed this issue will not be fixed
GalloDaSballo
high
l2BlockNumber()` can be used to prevent creating new Games
Summary
In
FaultDisputeGame.initialize
,l2BlockNumber
is only validated to be a newer valueAs discussed in the scope, we are to assume that Games can result in incorrect settlement
Due to that, we can quickly imagine a scenario in which
l2BlockNumber
, can be used to make this line revert:https://github.com/sherlock-audit/2024-02-optimism-2024/blob/main/optimism/packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol#L539-L540
This is possible because if we assume an invalid proof can pass as
DEFENDER_WINS
, then the incorrectl2BlockNumber
will be used as the starting block number for future games.Vulnerability Detail
By having
rootBlockNumber = type(uint256).max
it will be impossible toinitialize
new gamesl2BlockNumber
can be set to an arbitrarily high valueThe factory doesn't sanitize
_extraData
The data is arbitrary and interpreted to be the L2BlockNumber by the implementation
That will be passed to
AnchorStateRegistry
Impact
That will cause all future Games to be unitializable, meaning that all withdrawals, with the in-scope configuration can never work after the attack
Code Snippet
extraData
set totype(uint256).max
POC - Output
The output shows the second game
create
ion reverting, the line will be in initialize and it will compare theextraData
with therootBlockNumber
from theANCHOR_STATE_REGISTRY
Since
type(uint256).max
is the highest possible value, the line will cause permanent revertsPOC - Code
To allow the code to compile more rapidly I edited the source code in this way:
Changed
DisputeGameFactory
Change
AnchorStateRegistry
Tool used
Manual Review + Foundry
Recommendation
Since the goal of this contest is to ensure safe fallbacks are in place, it would be best to change newer games to ignore L2Blocks from blacklisted games, meaning instead of using the last l2BlockNumber from any successful game, the last l2BlockNumber from a non blacklisted game should be used
A registry of: l2Blocks <-> Roots that allows the Guardian choosing a valid Root against all accepted roots may be a step in the right direction
Redeploying doesn't seem like a viable strategy as the exploit will be performed every time
Duplicate of #90
The text was updated successfully, but these errors were encountered: