amiuhle/kasisto

0-conf possible attack

emesik opened this issue · 3 comments

Let's have an attacker with modified wallet trying to purchase goods from a merchant using Kasisto. The attacker's wallet is modified in a such way, that while apparently sending the transaction, it does as follows:

  1. Prepares the real transaction R to the merchant.
  2. Prepares false transaction F, sending the same inputs to a wallet controlled by the attacker.
  3. Simultaneously injects these transactions into the network through different nodes.

The results are:

  1. Both transactions spread across the network.
  2. Once a node has received either R or F, it rejects the other transaction as double spend.
  3. The network divides in two groups. One holds R in the mempool, the other holds F.
  4. When a block is mined, one of those transactions gets included, depending on which group the lucky miner was in.
  5. The other transaction either gets purged from the mempool or stays there as invalid until it times out (I don't know which one will happen, that depends on daemon's behavior).

What scenarios can we expect?

  • A: the node used by the merchant receives R but actually F is mined: in 0-conf mode this is the worst scenario. The merchant thinks he received the money but actually he doesn't.
  • B: merchant's node receives R and R is mined: the attack fails, the scammer actually pays for the merchandise.
  • C: merchant's node receives F and R is mined: because F is illegible for merchant's wallet (is encrypted with a different key) nothing happens until R has been mined, and the real payment succeeds then. The attack fails.
  • D: merchant's node receives F and F is mined: merchant doesn't see any incoming payment

By rough statistics, the attacker has 25% of success, however:

  • if case D occurs, the attack can be easily repeated at no other cost for the attacker than another tx fee,
  • if the attacker knows which node the merchant is using, he may inject R there directly (if merchant uses a public node) or to its peer, dramatically increasing the possibility (100% or close) that the real payment shows up on POS
  • if the attacker has knowledge on hashrate distribution among nodes, he may inject F to the nodes having powerful hashrate at their disposal, dramatically increasing chance of F being mined.

Preliminary conclusions:

  • 0-conf mode should be described with a big red warning recommending to wait for at least 1 conf at payments of significant value,
  • it should be recommended to the users to run their own node,
  • Kasisto should detect when variant A happens and warn about scam, (I'm very curious how the standard wallet behaves here, too)
  • it's important to check how actually daemon deals in situation from step 8 - having a double spend in the mempool when a block with the other tx arrives

I think I could help with staging such attack scenario on the testnet, if you decide it's worth investigating.

I've just realized there's a possibility of making this attack 100% effective:

  1. The attacker injects R to the merchant's node with do_not_relay flag set to True. As a result, the transaction stays only at that node and doesn't propagate to the network, still poisoning the mempool.
  2. Then the attacker sends F to any other node in the network, saturating it with the desired transaction and making 100% sure it will get mined.

Please note that timing is not important here. There's no hurry in executing step 2, as merchant's node is already poisoned and yet it will not propagate R any further.

I'm afraid it makes 0-conf extremely vulnerable.

The attacker can't set the do_not_relay flag unless the attacker has the ability to access the RPC port on the merchant's node. That is highly unlikely (merchants relying on a node for their own security should certainly not make the same node available to the public).

Nevertheless 0-conf that relies on relay will never be safe or secure. That doesn't mean it can't be done, it is just an exercise in cost (risk) benefit tradeoff, which likely depends a lot on the nature and size of the transaction, along with similar factors.

This is worth reading for another method of attacking https://bitcoin.stackexchange.com/questions/4942/what-is-a-finney-attack

Thanks for the input on this!

Keeping the node private is already recommended in the server setup, but I will explicitly point this out in the documentation.

As a result, I will implement waiting for transaction confirmation when the payment exceeds a configurable amount as part of Milestone 2 or 3 of my FFS.

For a completely trustless setup (eg running own node), I don't know if anything else can be done to further reduce the risk except waiting for confirmation.

For additional security, the merchant could rely on a wallet hosting service which could provide additional security by reducing the risk of 0-conf double spending attacks.

https://bitcointalk.org/index.php?topic=423.msg3819#msg3819