Pages:
Author

Topic: SERIOUS VULNERABILITY related to accepting zero-confirmation transactions (Read 11482 times)

sr. member
Activity: 437
Merit: 415
1ninja
retep, thank you for the clarifications. Could you TL;DR in the OP? And mention it is patched in 0.8?
legendary
Activity: 1526
Merit: 1134
We can bring time locked and replaceable transactions back when somebody does the work necessary to properly unit test the code, think through the potential issues/angles of attack and patches them, makes sure the DoS/abuse potential is minimized etc.

For now, Luke-Jr has it right - the feature was unused as it's meant to be deployed along side replacement. So we'll have to bring them back together.
legendary
Activity: 1120
Merit: 1160
I've quite successfully double-spent non-final transactions by just putting a replacement in my wallet on a single well-connected node and waiting a few days.

But... doesn't that mean that people were treating a time-locked transaction as normal unconfirmed transaction? They should not be treated as the same thing, that's the actual problem.

That's exactly what people were doing, or really, what the software people were using was doing. Keep in mind that a non-time-locked transaction that depends on a time-locked transaction is effectively time-locked... fixing the issue that way isn't trivial and would have required a lot more careful testing to be absolutely sure it worked; I should know, I wrote a patch that did exactly that kind of analysis before writing a version of the nearly trivial fix that Gavin wrote. It took me a few days to be convinced, but I think he made the right choice. There are also other mostly theoretical vulnerabilities related to non-final transactions that have not been disclosed as far as I know. They are fixed by Gavin's patch and are not fixed by just handling non-final txs differently in the UI. They also can-not be used to steal funds.
legendary
Activity: 1106
Merit: 1004
I've quite successfully double-spent non-final transactions by just putting a replacement in my wallet on a single well-connected node and waiting a few days.

But... doesn't that mean that people were treating a time-locked transaction as normal unconfirmed transaction? They should not be treated as the same thing, that's the actual problem.
legendary
Activity: 1708
Merit: 1020
Am I correct in assuming that while this is a serious issue for some sites it does not currently affect most clients and can be fixed for those affected with relative ease?

Once again this makes me wonder if Bitcoin guts really have to be so twisted and complicated. All this just sounds like an invitation to overlook serious issues.
legendary
Activity: 1120
Merit: 1160
nLockTime isn't killed "for good", it's just considered non-standard so the default client won't relay or pay attention to it. Since the client already doesn't support replacement, this really is pretty harmless. A future client that does support replacement can add it back in after another conversation.

Specifically nLockTime is only considered non-standard when the transaction is not final yet. That is the locktime hasn't been reached, and the transaction is not eligible to be included in a block. Non-standard just means that nodes won't relay such transactions on the P2P network, but nothing stops you from saving the transaction yourself and broadcasting it when the locktime is reached and the transaction finalizes.

Such feature can be really useful. Think inheritance for instance. How would you implement inheritance in a "bank" which uses multi-signature? You die, all your money dies with you?
Even for password regeneration... suppose you run a multisig bank in BTC, and you don't really trust all your clients to never forget their passwords (people do often forget/lose their passwords, and I bet that in some jurisdictions you would be forced to give your client a way to retrieve their money even if he forgot his password). Using nLockTime would be just great for this. You periodically transfer the money to a cold storage address the bank fully controls. While the client is logging in, you periodically reverse that transaction and generates a new one. If your client ever forgets his password for good, you'd just need to positively identify him (docs etc) and ask him to wait like 3 months or something to have his coins back.

You can do that just fine even if non-final transactions are not-standard. Just create the transactions that send the money back to the client, set the nLockTime so that they will not be valid for 3 months, and then sign them. You can freely give the client copies of these transactions. As the three months approaches, move the coins to invalidate the txin's of the previous set of locked transactions and create new refund transactions. If the refund transactions are ever needed, just wait until they have finalized, and broadcast them on the P2P network as you would any other transaction.

Ultimately the thing is transaction replacement just doesn't work the way people want it to because you can always replace a transaction by finding a miner willing to ignore the non-final tx in their mempool and willing to mine another one for you. Additionally mempool contents don't last forever; I've quite successfully double-spent non-final transactions by just putting a replacement in my wallet on a single well-connected node and waiting a few days.
legendary
Activity: 2576
Merit: 1186
nLockTime isn't killed "for good", it's just considered non-standard so the default client won't relay or pay attention to it. Since the client already doesn't support replacement, this really is pretty harmless. A future client that does support replacement can add it back in after another conversation.
legendary
Activity: 1106
Merit: 1004
Gavin's pull request looks like it is disabling a feature needed by transaction replacement in favor of assisting those who are swapping tangible assets for unconfirmed transactions without waiting the lock time.

Transaction replacement is currently disabled. Multiple parties discussed this issue extensively, and the consensus was that the minor utility of being able to broadcast non-final transactions was not important enough given the drawbacks.

That's what I feared. You're seriously killing nLockTime for good?

Such feature can be really useful. Think inheritance for instance. How would you implement inheritance in a "bank" which uses multi-signature? You die, all your money dies with you?
Even for password regeneration... suppose you run a multisig bank in BTC, and you don't really trust all your clients to never forget their passwords (people do often forget/lose their passwords, and I bet that in some jurisdictions you would be forced to give your client a way to retrieve their money even if he forgot his password). Using nLockTime would be just great for this. You periodically transfer the money to a cold storage address the bank fully controls. While the client is logging in, you periodically reverse that transaction and generates a new one. If your client ever forgets his password for good, you'd just need to positively identify him (docs etc) and ask him to wait like 3 months or something to have his coins back.

Anyways. This is a powerful feature. The fact that's not yet exploited doesn't mean otherwise: multisig itself is not really exploited so far, and I don't think you'd say that feature is "not important enough".
legendary
Activity: 1120
Merit: 1160
Gavin's pull request looks like it is disabling a feature needed by transaction replacement in favor of assisting those who are swapping tangible assets for unconfirmed transactions without waiting the lock time.

Transaction replacement is currently disabled. Multiple parties discussed this issue extensively, and the consensus was that the minor utility of being able to broadcast non-final transactions was not important enough given the drawbacks.

True transaction replacement probably needs to be done as a separate P2P layer, and in any case always has the problem that there is nothing stopping miners from mining older versions of the transaction that they know about.

Satoshi's wait 10 seconds for unconfirmed transactions to listen for a double spend applies to transactions that can feasibly make it to a block. Not for ones with lock times decades in the future?!?

That's the main reason this was considered a serious issue: code was doing exactly that and not taking into account that transactions can be made invalid until thousands of years in the future. (Maximum nLockTime setting locks the transaction until July 18, 11515) There are lots of UI's that make no distinction between transactions that can be mined now and ones that can't. The same applied to services; I did after all steal 5BTC from blockchain.info exploiting this oversight.

It also seems like no miner made the wrong choose for greed rather they took a committed transaction and put it in a block instead of its uncommitted locked version? Again am I wrong?

A non-final transaction can not be included in a block until it finalizes and thus miners have nothing to do with the issue.
sr. member
Activity: 437
Merit: 415
1ninja
Can someone now disclose the issue as promised? .... retep?

It appears to me that Mike Hearn has had the correct non-panicky level headed approach to this. Can someone explain how this is an exploit as opposed to expected functional behavior? It took me a lot of reading to determine this is a non issue?!? Am I wrong?

Gavin's pull request looks like it is disabling a feature needed by transaction replacement in favor of assisting those who are swapping tangible assets for unconfirmed transactions without waiting the lock time.

Satoshi's wait 10 seconds for unconfirmed transactions to listen for a double spend applies to transactions that can feasibly make it to a block. Not for ones with lock times decades in the future?!?

 It also seems like no miner made the wrong choose for greed rather they took a committed transaction and put it in a block instead of its uncommitted locked version? Again am I wrong?
legendary
Activity: 1596
Merit: 1100
well... duh?

Who would have thought it was a good idea to consider a transaction complete if a guy claims to have sent you funds but they haven't actually been verified as legit by ANYONE yet?

In general...  agreed, with this sentiment and the opinions others have expressed in this thread.

However, it should be noted that certain situations may benefit from a mixed approach.  If you are a merchant shipping a physical product, the purchase process might look like
  • Request payment
  • User sends bitcoins
  • "Payment received!"
  • Hours or days pass, while product is packed and prepped for shipment
  • Order validation: Check and make sure bitcoins have not been double-spent
  • Ship product

So it is really product/situation dependent.  A situation like bitcoin exchange or SatoshiDICE would seem like the ideal example of when to not accept zero-conf transactions; alternately BitcoinStore.com would seem like an excellent example of what could follow the multi-step order flow above.

Multi-step Zero-conf-now-check-later gives the best user experience: fast immediately confirmation of funds receipt, with the security of multiple confirmations before final product delivery/enablement.

legendary
Activity: 1526
Merit: 1134
Do you know the miner who mined the double spends?

Although playing games with the consensus protocol will always be possible, the difficulty of executing such attacks can be made much harder through some simple community policing work to ensure that legitimate miners don't accidentally get co-opted into creating double spends.
legendary
Activity: 1120
Merit: 1160
Yup, that's another known attack. bitcoinj is going to support recursive analysis of transaction depth IIRC, so you'd be able to say "don't accept chains more than x long"
legendary
Activity: 1540
Merit: 1002
This particular attack we endured doesn't seem to be related to lockntime, as far as I can tell. The coins are originally sent back and forth across a few addresses a few times in small values and finally they get aggregated in one address like A (http://blockchain.info/tx-index/46601326/e586b0cfa885c5fc8960205a9bfec228dc0dfa496c04b20172c66d1f9760076d) and B (http://blockchain.info/tx-index/46646986/2076b8e5be0fcaed6e6652ea2a89a45d755462764f852e3e3b9fcda3bb035e3e).

One vout from each of A and B (18 and 1 is one particular example) are then aggregated into C, which is then bet on Martingale at DoC with tx D. The long chain of tx without any fees takes a long time to get confirmed by the network and somewhere along the line C is replaced by another Tx, completing the double spend.

The now rolled back transactions C and D were:

Code:
{
"hex" : "0100000001f677169e7a5739be1e4c462e88fb1cc394a4ea061e4a1defc1f4d0e4e4aca9cf000000008b483045022100a086c038850b5f683abec9f04a43b2408b698cbd31d24e716f92737c114a9ee7022043b1f928c7f57d905260a0faf0b8f307e111f5f6566ccbc9f15961abcb8c9a4d014104e168f0402da84fafc564594cb18abf720567cbc58b118caf6698298d0f34404cfd784c30cf49dc18e0eabf58301791170e8db56ff792ca78470f15045a501bdcffffffff016a48c323000000001976a9142ddfe9616ddf358d81546a3a18034fc88b34965688ac00000000",
"txid" : "2b1cecb3046e1f951dfb0237b6318ce3685585e14d1541938d08b1c56e2ae6c0",
"version" : 1,
"locktime" : 0,
"vin" : [
{
"txid" : "cfa9ace4e4d0f4c1ef1d4a1e06eaa494c31cfb882e464c1ebe39577a9e1677f6",
"vout" : 0,
"scriptSig" : {
"asm" : "3045022100a086c038850b5f683abec9f04a43b2408b698cbd31d24e716f92737c114a9ee7022043b1f928c7f57d905260a0faf0b8f307e111f5f6566ccbc9f15961abcb8c9a4d01 04e168f0402da84fafc564594cb18abf720567cbc58b118caf6698298d0f34404cfd784c30cf49dc18e0eabf58301791170e8db56ff792ca78470f15045a501bdc",
"hex" : "483045022100a086c038850b5f683abec9f04a43b2408b698cbd31d24e716f92737c114a9ee7022043b1f928c7f57d905260a0faf0b8f307e111f5f6566ccbc9f15961abcb8c9a4d014104e168f0402da84fafc564594cb18abf720567cbc58b118caf6698298d0f34404cfd784c30cf49dc18e0eabf58301791170e8db56ff792ca78470f15045a501bdc"
},
"sequence" : 4294967295
}
],
"vout" : [
{
"value" : 6.00000618,
"n" : 0,
"scriptPubKey" : {
"asm" : "OP_DUP OP_HASH160 2ddfe9616ddf358d81546a3a18034fc88b349656 OP_EQUALVERIFY OP_CHECKSIG",
"hex" : "76a9142ddfe9616ddf358d81546a3a18034fc88b34965688ac",
"reqSigs" : 1,
"type" : "pubkeyhash",
"addresses" : [
"15BZeHbK4gX8YugqBsHwyTnUAqF5GJjgBW"
]
}
}
]
}

Code:

{
"hex" : "0100000001c0e62a6ec5b1088d9341154de1855568e38c31b63702fb1d951f6e04b3ec1c2b000000008b4830450220310e5c39ac668739c8938180a10fc304615fda593c99216a1b3691cf4887d835022100c2bd43eb443013b7e1c1543c37d2e0c491b48bae165964a34a8b9583349493e5014104696b060ed1de0bac92d72cf4afbb3ac6627464b90466eff282f3ff01c0b19a2da261f2bbad9c501332ebd87b82ad4e64b86f7248f7eaf7040b02d44fbbbc415fffffffff016a48c323000000001976a9147d3b0ada4990415ac12b968174371c8e67dc691b88ac00000000",
"txid" : "acaebd04202864eef6af5b9df8ca70b88875bc4cf540a6d0f8b010a87f00145c",
"version" : 1,
"locktime" : 0,
"vin" : [
{
"txid" : "2b1cecb3046e1f951dfb0237b6318ce3685585e14d1541938d08b1c56e2ae6c0",
"vout" : 0,
"scriptSig" : {
"asm" : "30450220310e5c39ac668739c8938180a10fc304615fda593c99216a1b3691cf4887d835022100c2bd43eb443013b7e1c1543c37d2e0c491b48bae165964a34a8b9583349493e501 04696b060ed1de0bac92d72cf4afbb3ac6627464b90466eff282f3ff01c0b19a2da261f2bbad9c501332ebd87b82ad4e64b86f7248f7eaf7040b02d44fbbbc415f",
"hex" : "4830450220310e5c39ac668739c8938180a10fc304615fda593c99216a1b3691cf4887d835022100c2bd43eb443013b7e1c1543c37d2e0c491b48bae165964a34a8b9583349493e5014104696b060ed1de0bac92d72cf4afbb3ac6627464b90466eff282f3ff01c0b19a2da261f2bbad9c501332ebd87b82ad4e64b86f7248f7eaf7040b02d44fbbbc415f"
},
"sequence" : 4294967295
}
],
"vout" : [
{
"value" : 6.00000618,
"n" : 0,
"scriptPubKey" : {
"asm" : "OP_DUP OP_HASH160 7d3b0ada4990415ac12b968174371c8e67dc691b OP_EQUALVERIFY OP_CHECKSIG",
"hex" : "76a9147d3b0ada4990415ac12b968174371c8e67dc691b88ac",
"reqSigs" : 1,
"type" : "pubkeyhash",
"addresses" : [
"1CRACKLiwFrZbAQz1yb9w22onHCMLbiMTY"
]
}
}
]
}
legendary
Activity: 1120
Merit: 1160
And diceoncrack fell on to this attack, it seems... https://bitcointalksearch.org/topic/diceoncrack-attacked-138988

I have a requirement that isn't satisfied on the 0.8 series, an effect of the leveldb implementation. I need to be able to read raw tx for non wallet transactions, and these are no longer kept, so for now I can't update. I think that there are only two things I can do at this point; don't accept 0 confirmation wagers without fee and make sure the coins used on the wager tx are already on a block. Had I these measures in place the attack would have failed.

Luke is correct above, and you can also simply apply the patch Gavin posted to your 0.7 bitcoind src. I've tested this before - I wrote a slightly different version of the patch a few weeks ago - and it worked fine.

If anyone need details about this attack let me know, I can dig the transactions that got rolled back.

I'd be very interested to know; there are many variations of this attack.
legendary
Activity: 2576
Merit: 1186
I have a requirement that isn't satisfied on the 0.8 series, an effect of the leveldb implementation. I need to be able to read raw tx for non wallet transactions, and these are no longer kept, so for now I can't update.
This will be fixed in 0.8 (though require you to use a new option the first time you start it).
legendary
Activity: 1540
Merit: 1002
And diceoncrack fell on to this attack, it seems... https://bitcointalksearch.org/topic/diceoncrack-attacked-138988

I have a requirement that isn't satisfied on the 0.8 series, an effect of the leveldb implementation. I need to be able to read raw tx for non wallet transactions, and these are no longer kept, so for now I can't update. I think that there are only two things I can do at this point; don't accept 0 confirmation wagers without fee and make sure the coins used on the wager tx are already on a block. Had I these measures in place the attack would have failed.

That or simply not take 0 confirmation wagers, of course.

If anyone need details about this attack let me know, I can dig the transactions that got rolled back.
legendary
Activity: 1652
Merit: 2311
Chief Scientist
The reference implementation patch is scheduled for the (real soon now!) 0.8 release:
  https://github.com/bitcoin/bitcoin/pull/2223
legendary
Activity: 1526
Merit: 1134
For what it's worth, I'm working on changes to bitcoinj so that apps built on that library are protected from this and related issues. It's not done yet but making progress. I'm not sure if anything is being done to the main C++ client.
legendary
Activity: 2576
Merit: 1186
still no details? you got me curious...
Take a look at bitcoin magazines website.
The article does not cover the vulnerability this thread is about.

I'm sure disclosure will come in time.
Pages:
Jump to: