Hawk High

First Flight #39
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Severity: medium
Valid

Front-Running Vulnerability in LevelOne Contract Initialization

Summary

The LevelOne contract implementation is vulnerable to front-running attacks due to missing _disableInitializers() in its constructor. An attacker could initialize the implementation contract directly before the proxy does, potentially hijacking control of the system.

Vulnerability Details

Issue Description

The LevelOne contract inherits from Initializable and UUPSUpgradeable but fails to implement the critical security measure of disabling initializers in its constructor. This omission creates a window of vulnerability during deployment where an attacker could front-run the initialization process.

// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
// Missing constructor with _disableInitializers()
contract LevelOne is Initializable, UUPSUpgradeable {
// ...
}

Attack Vector

The vulnerability occurs during the deployment process:

levelOneImplementation = new LevelOne(); // Transaction #1
proxy = new ERC1967Proxy(address(levelOneImplementation), ""); // Transaction #2
LevelOne(address(proxy)).initialize(principal, schoolFees, address(usdc)); // Transaction #3

Between Transaction #1 and Transaction #3, the implementation contract address is public but not yet initialized. An attacker monitoring the mempool could:

  1. Detect the implementation contract deployment

  2. Submit their own transaction with a higher gas price to call initialize() directly on the implementation

  3. Set themselves as the principal and gain control over critical functions

This attack is possible because:

  • Each transaction is independently mined

  • There's an inherent timing gap between implementation deployment and initialization

  • The implementation doesn't prevent direct initialization

Impact

If successfully exploited, an attacker could:

• Gain funds

  • Set themselves as the principal of the implementation contract

  • Gain privileged access to critical functions including:

    • addTeacher()

    • removeTeacher()

    • expel()

    • startSession()

    • graduateAndUpgrade()

    • _authorizeUpgrade()

  • Disrupt the intended deployment workflow

  • Create inconsistency between implementation and proxy state

While this doesn't directly compromise the proxy contract's storage, it creates a vulnerable implementation contract that could potentially be used in future attacks or cause confusion.

Tools Used

Manual code review

Recommendations

Add _disableInitializers() to the constructor:

constructor() {_disableInitializers();}

in the LevelOne contract

Updates

Lead Judging Commences

yeahchibyke Lead Judge 6 months ago
Submission Judgement Published
Validated
Assigned finding tags:

contract can be re-initialized

The system can be re-initialized by an attacker and its integrity tampered with due to lack of `disableInitializer()`

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.