Hawk High

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

Implementation Contract Initialization Vulnerability

Summary

Vulnerability Type: Front-Running / Initialization Control
Contract: LevelOne
Component: Constructor Implementation

Technical Analysis

During examination of the LevelOne smart contract codebase, we identified a significant security risk related to the initialization process of upgradeable contracts. The LevelOne contract extends the OpenZeppelin Initializable and UUPSUpgradeable patterns but critically fails to implement proper initialization protections.

Vulnerability Details

Root Cause

The vulnerability stems from the absence of an initialization blocking mechanism in the contract's constructor:

// Current Implementation - Missing Constructor
contract LevelOne is Initializable, UUPSUpgradeable {
// Contract body...
}
// Required Implementation
contract LevelOne is Initializable, UUPSUpgradeable {
constructor() {
_disableInitializers();
}
// Contract body...
}

The missing _disableInitializers() call creates a security gap that breaks the trusted initialization flow of the proxy pattern.

Exploitation Scenario

The deployment sequence typically follows these steps:

  1. Deploy LevelOne implementation contract

  2. Deploy ERC1967Proxy pointing to the implementation

  3. Initialize the proxy with business logic parameters

Due to Ethereum's transaction processing model, these steps execute as separate transactions. An attacker monitoring the mempool can identify when the implementation is deployed and exploit the gap between steps 1 and 3:

+----------------+ +----------------+ +----------------+
| Implementation | | Proxy | | Initialization |
| Contract |----->| Deployment |----->| of Proxy |
| Deployment | | | | |
+----------------+ +----------------+ +----------------+
^
|
+--------------------------------------+
|
+----------------+
| Attacker |
| Front-Running |
| Implementation |
| Initialization|
+----------------+

The attacker can front-run the intended initialization by:

  1. Observing the implementation contract deployment transaction

  2. Submitting a competing transaction with higher gas to call initialize() directly on the implementation

  3. Setting themselves as the principal, gaining administrative privileges

Impact

Direct Consequences

  • Administrative Control: An attacker could seize control of the implementation contract

  • Attacker gain funds of principal

  • Function Access: Unauthorized access to privileged functions:

    • School management (addTeacher, removeTeacher, expel)

    • System operation (startSession)

    • Upgrade controls (graduateAndUpgrade, _authorizeUpgrade)

Tools Used

manual review

Recommendations

Immediate Fix

Implement the missing constructor with initialization protection:

constructor() {
_disableInitializers();
}

This one-line change effectively prevents the implementation contract from being initialized directly.

Deployment Improvements

  1. Atomic Deployment: Where possible, use deployment factories that initialize in the same transaction

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.