#38111 [BC-High] Attackers can send a very large event in a Stacks block so that the Signer can neve

Submitted on Dec 24th 2024 at 17:11:10 UTC by @f4lc0n for Attackathon | Stacks

  • Report ID: #38111

  • Report Type: Blockchain/DLT

  • Report severity: High

  • Target: https://github.com/stacks-network/sbtc/tree/immunefi_attackaton_0.9/signer

  • Impacts:

    • Permanent freezing of funds (fix requires hardfork)

    • API crash preventing correct processing of deposits

Description

Brief/Intro

The /new_block api of Signer receives each block of Stacks and reads the events in it. Signer uses the axum::http package to run the api http service. The default payload limit of axum::http is 2M.

Attackers can emit more than 2M events in a Stacks block to make the Stacks node fail to access the Signer's /new_block. Then the Stacks node will make requests infinitely and fail infinitely, and the Signer will never be able to obtain new Stacks block events.

Vulnerability Details

The axum::extract::DefaultBodyLimit docs is as follows.

For security reasons, Bytes will, by default, not accept bodies larger than 2MB. This also applies to extractors that uses Bytes internally such as String, Json, and Form.

Extracted from: https://docs.rs/axum/latest/axum/extract/struct.DefaultBodyLimit.html

The signer/src/api/new_block.rs::new_block_handler code is as follows.

According to the comment, we can know that Stacks node will retry infinitely until it successfully accesses the /new_block api of Signer.

Impact Details

Signer will never receive events from Stacks again. The specific impacts are as follows:

  1. Since it cannot receive the WithdrawalCreate event, the Signer will not process the user's withdrawal request. The user's sBTC will be frozen.

  2. Since it cannot receive the KeyRotation event, the Signer will not receive the new rotate_key. Then the Signer will process the deposits.

Since it freezes the user's funds, but it is temporary, I consider this a High.

References

None

Proof of Concept

Proof of Concept

  1. Add some log to signer/src/api/new_block.rs. The log will print each new stacks block received

  2. Add a test address to docker/stacks/stacks-regtest-miner.toml. Please replace it with your wallet address!

  3. Build docker

  4. Wait for a while, use sandbox to deploy the POC contract. If you cannot deploy, please check your wallet nonce.

  5. Wait for a while, use sandbox to call the POC contract. If you cannot call, please check your wallet nonce and enable Allow Mode.

  6. Then, you will find that Signer can no longer receive Stacks events.

Last updated

Was this helpful?