Skip to content
This repository has been archived by the owner on May 26, 2023. It is now read-only.

usmannk - Crafted p2p spam can render nodes permanently unable to process L2 blocks #177

Open
github-actions bot opened this issue Feb 20, 2023 · 1 comment
Labels
Medium A valid Medium severity issue Reward A payout will be made for this issue

Comments

@github-actions
Copy link

usmannk

medium

Crafted p2p spam can render nodes permanently unable to process L2 blocks

Summary

The constraints in BuildBlocksValidator are meant to prevent p2p spam from bogging down the network. However they are not sufficient for stopping spam, but are strong enough to render nodes unable to catch up.

Vulnerability Detail

The p2p.BuildBlocksValidator function has several constraints that must be met before a gossiped block is considered valid. If a block is considered valid then it is gossiped to peers and ingested into the current node.

The constraints on a gossiped block block are, in order:

  • block must be <10MB
  • block must be compressed as valid snappy data
  • block must be signed by the sequencer
  • block must be a valid SSZ encoded block
  • block.timestamp must within 60 seconds in the past and 5 seconds in the future
  • block.BlockHash must be correctly calculated
  • block.BlockNumber must not be in the set of the previous 100 unique block numbers that reached this step

These constraints are applied here:

https://github.com/sherlock-audit/2023-01-optimism/blob/main/optimism/op-node/p2p/gossip.go#L208

However, it is often the case that there are over 100 valid L2 blocks emitted per minute. For example, the 253 blocks between block 71404110 and 71404363 were emitted within 60 seconds.

In this example, an attacker would take the 200 blocks from 71404110-71404310 and replay them in order to a node for 60 seconds. Every block would be valid because they each pass all constraints and the 100 block LRU cache for marking seen blocks would be evicted twice over during the process.

After 60 seconds, block 71404310 + 1 would be invalid to this node because its timestamp would be too old. At this point, for any new L2 block the node would either:

  • mark it as invalid because it is too old
  • or ingest it and throw it away because it is waiting for block 71404311

As a result, the node will no longer be able to successfully process any L2 blocks from the p2p network.

Furthermore, because all 200 blocks are marked as valid several times, the node would gossip all of these blocks (potentially several times) to its peers who would suffer the same effect and impact their peers.

Impact

Attackers may halt targeted nodes.

Further knock-on potential halting of the node's peers, peers of peers, and so on.

Code Snippet

Tool used

Manual Review

Recommendation

Increase the size of the blockHeightLRU cache to more effectively catch and reject previously seen nodes. It would be reasonable to set it to 1000 instead of 100. Even at 1000 the cache should occupy less than 500kb in memory.

@github-actions github-actions bot added the Medium A valid Medium severity issue label Feb 20, 2023
@rcstanciu
Copy link
Contributor

Comment from Optimism


Description: P2P buffer is too small

Reason: This is a valid attack, wherein the attacker replays blocks and eclipses a node from the P2P network.

Action: Increase buffer size

@sherlock-admin sherlock-admin added the Reward A payout will be made for this issue label Feb 21, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Medium A valid Medium severity issue Reward A payout will be made for this issue
Projects
None yet
Development

No branches or pull requests

2 participants