amiuhle / kasisto

A Monero Point of Sale payment system
https://amiuhle.github.io/kasisto/
MIT License
159 stars 39 forks source link

0-conf possible attack #31

Open emesik opened 6 years ago

emesik commented 6 years ago

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?

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

Preliminary conclusions:

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

emesik commented 6 years ago

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.

iamsmooth commented 6 years ago

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

amiuhle commented 6 years ago

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