#37384 [BC-Medium] Attacker can front-run call to emily api with incorrect data, preventing legit us
Submitted on Dec 3rd 2024 at 16:26:12 UTC by @n4nika for Attackathon | Stacks
Report ID: #37384
Report Type: Blockchain/DLT
Report severity: Medium
Target: https://github.com/stacks-network/sbtc/tree/immunefi_attackaton_0.9/emily
Impacts:
A bug in the respective layer 0/1/2 network code that results in unintended smart contract behavior with no concrete funds at direct risk
Description
Summary
An attacker can "front-run" legitimate users' requests to create_deposit of the emily api (emily/handler/src/api/handlers/deposit.rs#206) with malformed deposit requests, censoring those users' deposits.
Rootcause
Since the create_deposit endpoint of the emily api (emily/handler/src/api/handlers/deposit.rs#206) does not do any verification that the submitted scripts match the scripts at the submitted bitcoin_txid[bitcoin_tx_output_index], meaning we can specify arbitrary scripts which do not match the actual bitcoin transaction. If we manage to make such a request to emily before the legitimate user does, their deposit request will not be accepted and since our request is malformed, it will fail the signer verification later on.
Impact
Now if we manage to fit our malicious request in before the user's goes through, their deposit request will fail. As far as I can see (please correct me if I'm wrong), the deposit_entry added to the database here is never removed from it later. Since the key for the database entry is based on the txid and tx_output_index (seen here), the legit user will be unable to re-submit their deposit request.
Therefore this allows the attacker to censor the user's deposit, essentially freezing their assets for the user specified lock_time.
Mitigation
Consider already checking whether the deposit request sent to emily is legit (cross-check the claimed information with the information written in the specified bitcoin transaction).
Proof of Concept
In order to run the PoC, please apply the following two diffs (one updates the demo_cli, the other updates the signers.sh script):
After that, this can be confirmed by:
launching the devnet
executing
./signers.sh pocand taking the returnedTXIDexecuting
./signers.sh s2 [SIGNER_KEY] [TXID] SP2QKVPXG87TZ01JMRH1VP3S38AWN32NBS5B4CWT0, hereSIGNER_KEYcan be taken from the cargo run output of the previous command (sorry the script is a bit hacky)The last argument is a random stacks address I took from the stacks explorer
This step is the "frontrun" of the attacker, providing a
recipientwhich does not match the one of the bitcoin transaction on-chain
executing
./signers.sh get-> this returns the current deposit requests; here we can see that the recipient is the one we providedIf we now execute
./signers.sh s2 [SIGNER_KEY] [TXID](which defaults to using the recipient of the on-chain transaction)and afterwards again execute
./signers.sh get, we see that now the recipient was not updated (which is good, otherwise we would have another bug)
Since all these steps work, this shows that we can submit an invalid deposit request for a valid transaction. That this later on fails should be pretty clear; we verify the script integrity in the sbtc library before signers sign the deposit here
Last updated
Was this helpful?