#38270 [BC-Medium] A signer can send a large number of junk `WstsNetMessage::NonceRequest` through P
Submitted on Dec 29th 2024 at 18:28:23 UTC by @f4lc0n for Attackathon | Stacks
Report ID: #38270
Report Type: Blockchain/DLT
Report severity: Medium
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
Each time a signer receives a WstsNetMessage::NonceRequest message, it inserts the msg.txid into the wsts_state_machines. Then a malicious signer can send a large number of junk WstsNetMessage::NonceRequest messages to other signers to make the wsts_state_machines of other signers grow indefinitely, causing them to run out of memory.
Vulnerability Details
The signer/src/transaction_signer.rs::handle_wsts_message function is as follows.
WstsNetMessage::NonceRequest(request) => {
tracing::info!("handling NonceRequest");
if !chain_tip_report.sender_is_coordinator {
tracing::warn!("received coordinator message from non-coordinator signer");
return Ok(());
}
let db = self.context.get_storage();
let sig_hash = &request.message;
let validation_outcome = Self::validate_bitcoin_sign_request(&db, sig_hash).await;
let validation_status = match &validation_outcome {
Ok(()) => "success",
Err(Error::SigHashConversion(_)) => "improper-sighash",
Err(Error::UnknownSigHash(_)) => "unknown-sighash",
Err(Error::InvalidSigHash(_)) => "invalid-sighash",
Err(_) => "unexpected-failure",
};
metrics::counter!(
Metrics::SignRequestsTotal,
"blockchain" => BITCOIN_BLOCKCHAIN,
"kind" => "sweep",
"status" => validation_status,
)
.increment(1);
if !self.wsts_state_machines.contains_key(&msg.txid) {
let (maybe_aggregate_key, _) = self
.get_signer_set_and_aggregate_key(bitcoin_chain_tip)
.await?;
let state_machine = SignerStateMachine::load(
&db,
maybe_aggregate_key.ok_or(Error::NoDkgShares)?,
self.threshold,
self.signer_private_key,
)
.await?;
self.wsts_state_machines.insert(msg.txid, state_machine);
}
self.relay_message(msg.txid, &msg.inner, bitcoin_chain_tip)
.await?;
}As long as msg.txid is not contained in self.wsts_state_machines, this function will insert msg.txid into self.wsts_state_machines. Then, the attacker can send a large number of messages with different txid to make the self.wsts_state_machines of other signers grow infinitely.
Impact Details
It can cause signers to crash due to out of memory, which will cause signers to be unable to process deposits and withdrawls. The user's sBTC is frozen until signers manually process withdrawls.
It requires the attacker to be one of the signers, so I believe it is Medium.
References
None
Proof of Concept
Proof of Concept
Base on: https://github.com/stacks-network/sbtc/releases/tag/0.0.9-rc4
Patch
signer/src/config/mod.rs, add attacker tag configPatch
signer/src/main.rs, load attacker tagPatch
docker/docker-compose.yml, add attacker tagPatch
signer/src/network/libp2p/event_loop.rs, add attack actionPatch
signer/src/transaction_signer.rs, add some logRun docker
This PoC sets sbtc-signer-3 as an attacker, which will automatically attack other signers. Observe the log and you will find that
self.wsts_state_machinesof other signers keeps growingYou can observe the memory usage of signer through
docker stats sbtc-signer-1command
Last updated
Was this helpful?