41714 [BC-High] tampering the id of signed transactions to prevent others from executing

#41714 [BC-High] Tampering the ID of signed transactions to prevent others from executing

Submitted on Mar 17th 2025 at 18:32:40 UTC by @Capybara for Attackathon | Movement Labs

  • Report ID: #41714

  • Report Type: Blockchain/DLT

  • Report severity: High

  • Target: https://github.com/immunefi-team/attackathon-movement/tree/main/networks/movement/movement-full-node

  • Impacts:

    • Causing network processing nodes to process transactions from the mempool beyond set parameters

Description

Vulnerability Details

The format of transactions submitted to the sequencer

Transactions are represented as:

pub struct Transaction {
	data: Vec<u8>,
	application_priority: u64,
	sequence_number: u64,
	id: Id,
}

data is a SignedTransaction turned into a bytes array:

When the DA layer receives a Transaction before including it in the mempool it verifies the following:

  • The transaction's signature is valid

  • The transaction ID does not exist in the mempool pool already

During this process, there are no checks to validate whether the transaction id received in the blob is legit, or an arbitrary value set by a malicious node.

This value should be recalculated instead of blindly trusting the node submitting the transaction to set the correct id for the transaction.

Tampering the ID to prevent another transaction from being added to the mempool

Suppose there are 2 transactions, one is from Bob with ID 0xAA and the other one is from Alice with ID 0xBB.

When submitting a batch of transaction blobs a node can't manipulate the value inside .data because it is signed and the DA layer verifies its signature.

But there are no checks on the validity of the ID in the DA layer, therefore, the node can manually set the ID of Bob_Transaction to be the one of Alice_Transaction and submit the blobs:

As a consequence, only one of the transactions will be sequenced, because the system believes he already added to the mempool the other transaction based on its ID.

Example

Bob sends funds to Alice in a transaction and Alice sends an NFT to Bob in a different transaction.

Maliciously manipulating transaction IDs in a batch of txs allows for only one of the 2 transactions to get processed.

Impact Details

Causing network processing nodes to process transactions beyond set parameters. Tampering the ID of signed transactions may prevent others from executing.

Proof of Concept

Proof of Concept

In the proof of concept below Alice sends funds to Bob in a transaction and Bob sends funds to Alice in a different transaction.

Maliciously, a node sets Alice's transaction ID to the same value as Bob's transaction ID before submitting a batch write to the DA layer.

As a result, only one of the transactions gets processed.

Add the test to the file ./attackathon-movement/protocol-units/da/movement/protocol/tests/src/test/e2e/raw/sequencer.rs, import modules if needed.

The test is run in a custom malicious node that communicates with the DA layer to submit blobs of transactions. The set_id function is added by the malicious node to ./attackathon-movement/util/movement-types/src/transaction.rs:

The test will print Alice and Bob addresses like this:

Different values will be shown to you

Verify the balances of Alice and Bob by sending an HTTP request to the REST endpoint:

Replace ${ACCOUNT} with the address of the account

Alice will have 1010000 coins and Bob 989300, which means Alice's transfer did not executed, but Bob's transfer did.

Was this helpful?