Skip to content

Latest commit

 

History

History
46 lines (28 loc) · 3.86 KB

M-05.md

File metadata and controls

46 lines (28 loc) · 3.86 KB

Incorrect BOOTLOADER_TYPE omits critical safety check to prevent address impersonation of system contracts

Summary

The Bootloader contains conditional code snippets denoted with <!-- @if {condition} --> that are parsed on build time to allow different environments to work on, such as production, or a playground.

There's a conditional block that has a wrong value, and omits a critical check on a production environment deployment. That allows setting the from value of a transaction to a system contract address.

Impact

An operator can attempt to impersonate a system contract address by bypassing the missing check and execute dangerous logic. Access control and permissions is an area of concern mentioned in the Attack Ideas of the Readme.

Impersonating system contracts allow the execution of logic protected by modifiers like onlyCallFromSystemContract and onlySystemCall

Some of the system contracts can act on behalf of the user or have a very important impact on the behavior of the account.

Proof of Concept

The Bootloader used to have conditional blocks with the condition BOOTLOADER_TYPE=='proved_block' as can be seen from the codebase of the last Code4rena contest.

There was a refactor in the codebase leading in the change proved_block -> proved_batch as can be seen here. The only instance of the former value is the one pointed out in this report as can be checked on the repository.

The deployment version of the Bootloader is set by the scripts/process.ts and now has a value of proved_batch.

The Bootloader now has this outdated block with the mentioned critical check of the from attribute of the transaction that won't be executed, as BOOTLOADER_TYPE now can't have the value proved_block after the refactor:

  <!-- @if BOOTLOADER_TYPE=='proved_block' -->
  assertEq(gt(getFrom(innerTxDataOffset), MAX_SYSTEM_CONTRACT_ADDR()), 1, "from in kernel space")
  <!-- @endif -->

bootloader.yul#L2661-L2663

This block is the one in charge to validate the structure of L2 transactions, specifically in this case they correspond to EIP-1559 transactions.

Recommendation

Replace proved_block with the expected proved_batch in the Bootloader:

-   <!-- @if BOOTLOADER_TYPE=='proved_block' -->
+   <!-- @if BOOTLOADER_TYPE=='proved_batch' -->
    assertEq(gt(getFrom(innerTxDataOffset), MAX_SYSTEM_CONTRACT_ADDR()), 1, "from in kernel space")
    <!-- @endif -->