Network not being able to confirm new transactions (total network shutdown)
Description
Brief/Intro
Sbtc deposit handling by the Signer network starts with the user submiting a deposit request to the Emily API. The Emily API stores this deposit request together with a Status enum (Pending, Reprocessing, Accepted, Confirmed, Failed) starting as Pending. With each new bitcoin block all signers retrieve all Pending deposit requests from the Emily API using the get_deposits() method. As the deposit request progresses through the Signers execution process, the signers report back to the Emily API the request's updated status using the update_deposits method. update_deposits requires an ApiKey that only the Signers hold. However, a rogue signer can use this Api key to submit an incorrect status update for a Pending deposit that was not handled yet, thus preventing the deposit from ever getting retrieved by the Signers and from ever getting processed on the stacks blockchain.
Vulnerability Details
Following is the attack path for the described vulnerability:
A rogue signer decides to censor specific deposit requests, preventing them from being processed by the signers network.
The Signer monitors the Emily Api for new deposit requests (by calling the Api get_deposits method directly, outside of the Signer client)
When the Signer detects a deposit request they wish to censor, they immediatly send an update_deposits Api call to emily, setting the deposit request status to Accepted.
When the next bitcoin block is observed by all Signers, they will retrieve Pending deposit requests from Emily, but the censored request will not be retrieved because it is allready set to Accepted state.
The Censored transaction remains in the Emily DB as Accepted and will never be handled by the Signers because the Emily Api considers it handled.
If another signer tries to reset the deposit request back to Pending, the rogue signer can update the status back to Pending, which creates a race condition of whose status update lands last before signers retrieve deposits again (with each new bitcoin block).
Impact Details
Permanent censoring of any deposit request. The rogue signer can censor any deposit transaction they want with the method described above.
Create a backup for demo_cli.rs and replace its content with the code below.
Main changes:
a. Adds an update_deposit_status function that calls the Emily Api to change the status of a deposit request.
b. Changes exec_deposit to call update_deposit_status(Accepted) immediately after the deposit request is sent to Emily (to emulate the rogue signer changing the status immediately after the deposit request arrives).
Run the devnet docker with make devenv-up
Once the system is up, run ./signers.sh info to get the SIGNERS_KEY
Run cargo run -p signer --bin demo-cli deposit --amount 42 --max-fee 20000 --lock-time 50 --stacks-addr ST2SBXRBJJTH7GV5J93HJ62W2NRRQ46XYBK92Y039 --signer-key SIGNERS_KEY (Creates a bitcoin tx and a deposit request on the Emily Api and immediately sets the deposit request status on Emily to Accepted, even though is was not seen yet by the signers)
to see that the deposit request is in the emily db with status Accepted
run psql postgresql://postgres:postgres@localhost:5432/signer -c "SELECT * FROM sbtc_signer.deposit_signers AS dr" > output_file.
See that there are no actual decisions on the deposit by any signer
Check the Stacks explorer (http://localhost:3020/address/SN3R84XZYA63QS28932XQF3G1J8R9PC3W76P9CSQS?chain=testnet&api=http://localhost:3999) to see that no Deposit Completed transaction exists.