I really thought this had been fixed, because I commented the problem of using IsFromMe / IsMine to the developers in the github forums (
https://github.com/bitcoin/bitcoin/pull/1648), but no. Not fixed, so I'd better alert people before they can be tracked...
The attack requires you to connect and be disconnected from the same node almost 11 times. Nodes do ban DoS offenders for some time, so the attack can take some days mounted from a single IP. Nevertheless, if you can control 11 different IPs (very easy), and you can re-connect to the peer, you cant still mount a successful attack in a few minutes.
The attack allows only to know the Bitcoin public address related to an IP. If a peer is using Tor, then there is no loss of anonymity.
Affected Systems
-----------------
The problem affects all versions of the Satoshi Bitcoin Client.
Summary
---------
The method CTxMemPool::accept() has a protection against 'penny-flooding'. The protection prevents a transaction with very low fees and big size to be forwarded or even stored in the memory pool.
The problem is that this protection tests if a transaction is from a wallet owned by the user, and if it's the case, then the protection is skipped. This fact can be used by the attacker as an oracle.
There are currently around 1M addresses with non-zero balance (an estimation based on
http://bitcoin.stackexchange.com/questions/3524/how-many-unspent-transaction-outputs-are-there).
An attacker can discover which of the addresses are owned by a peer by the following procedure:
1. For each address, the attacker choose one unspent output Out(i)
2. Group the 1M unspent outputs in 1632 transactions Tx(j), each one containing 613 previns. Each transaction would be approximately 26999 Kbytes long. Add one output. Put zero fees. (GetMinFee() will return zero)
3. Send each Tx(j) one by one to the victim node.
4. After sending each transaction, the victim node may:
- Reject the transaction because it penny-floods (normally). In this case you will be still able to send more transactions.
- Disconnect you (DoS detection) you since you are not providing the correct signature scripts (this is the case when you have hit an owned address)
5. If you have been disconnected, repeat recursively a binary search grouping the prevouts of this transaction until you find a single one that disconnects you. Note that you may need to add additional dummy previns or prevouts to the transaction if it becomes too small to be blocked by the peer with the penny-flooding protection system.
With a 54 Kb/sec link, sending each Tx takes 1/2 sec so finding the first tx takes in the worst case, 13 minutes. Afterwards each binary search step takes 1/2 seconds in the worst case, so with 10 additional tests you can find an prevout with the desired property in 2^10 prevouts, more than the 613 originally contained, in a few seconds.
I haven´t tested the attack but, check for yourself. The explanation is clear enough. But without testing the attack, I can be mistaken.
You can protect very easily from the attack by rising the "-limitfreerelay" value to something like 1000000. Of course, that will also disable the penny-flooding protection.
Until the next vuln report,
Yours sincerely, Sergio.