Do Not Mess With ETH Classic, It Will F You Up

This is a letter sent out to my security/audit clients, but I wanted to publish it, as it is germane to a wide variety of Ethereum participants.

It looks like, sadly, ETH classic is a going concern, at least for a little while.

This raises a whole set of terrible and weird issues for exchanges, casinos and other large-scale hot wallet providers. Also, of course, any participant in Ethereum that might care what happens to their coins in Classic-land, in case Classic ends up being the dominant chain.

I wrote about some attack vectors here, and Dr. Emin Gün Sirer wrote some thoughts up here, both are worth reading first.

Now, though we aren't talking theoretical problems, but real ones.

TL;DR from @LilButerin:

ETH classic aint da answer, y'all chillen wit a dead chain playin necromancer, terminal illness, ur chain got cancer

Worries

The simplest worry is that you're going to get replayed in one chain, whenever you do something in the other: any strictly increasing subset of your contract calls can be replayed on the other chain.

More complex, and harder to reason about, are worries about multi-contract interactions, calls happening with varying state, all the things that are bread and butter for attackers in distributed systems or complex software.

Simplest Example: Selling Coins at Poloniex

You wish to get a little Bitcoin in exchange for your Classic coins, which you think are worthless. You send them to Poloniex, at their ETC deposit address.

You sell the coins, withdraw Bitcoin, and are happy. Until.. you log back in to your client tracking the non-Classic fork and see that your coins are gone. Where did they go?

Some ETH-Classic supporter has sent them on to the same address as Poloniex' ETH-Classic deposit address, but this time on the main chain, by simply replaying the transaction in the main chain.

If you are very, very lucky, Poloniex may be able to keep track of these coins on the main chain for you. But, probably, they are going to be lost until and unless someone can manually see what's going on and help you out.

Worse: Call Authorizations And Mucking With State

Any contract which relies on ordered state concerns has real trouble coming. Dr. Sirer posed to me a simple game to get the point across: Tic-Tac-Toe (TTT).

Imagine a contract takes moves in a TTT game, and implements the following rules: users must alternate moves, and standard win conditions apply.

A replayer can force a loss on either side in Classic by selectively withholding one side's moves, and double-playing the other's. The TTT contract will note an illegal move, and give the win to the other side.

Or, a game player can get a guaranteed win without a forfeit -- she will know her opponents moves ahead of time, and can interject new moves of her own that lead to a win.

Another way of saying this is that most Ethereum contract calls are not idempotent -- they rely on the blockchain to encapsulate enough state to function.

If your mind is running through some questions about your own multisig wallets or DAOs in which you control funds or are part of an authorization team, it should be. The answers are not pretty.

Because contracts can rely on anything, existing balances, output from other contracts outside their control, block hashes, you may be in for a pretty bad time.

DAO Vulnerabilities

Let's imagine you have a list of payout addresses in Classic, and one in the main chain. And let's imagine that the main chain contract continues on merrily, while the Classic one doesn't, because your DAO has decided to use the main chain.

Now, let's imagine a large payout is made and approved, perhaps an "upgrade" -- moving all funds to a new version of the contract -- using the following set of steps:

  1. Address is added to a list of payout proposals
  2. Payout proposal is voted on and accepted
  3. Payout is made

If anyone is allowed to add a payout proposal, then the attack looks like this:

  1. Replay txs for the DAO under attack until one before the address being added
  2. Add your own address as a proposal
  3. Replay additional votes and payout transaction from main chain

Boom, you've got control of the money.

This is like the TTT vulnerability above; we replace one 'move' with a new one, and the rest of the calls can remain invariant.

There are hundreds of possibilities like this, from casino attacks to exchange attacks. It is going to be insanity, real and true insanity.

Mitigation

In my first essay about this, I recommended simultaneously moving your ethereum to different contracts, one per chain.

All contracts that can manage to do this should do so immediately.

Since writing up my thoughts, I have learned about a proposal by Tjaden Hess -- a 'many universes' contract which could make this a bit easier.

The idea of the many universes contract is to create a number of 'slots', each one owned by a different address. For safety, I would recommend that each of these addresses be generated by a different private key -- in the ideal world, you will put your original wallet's private key on ice, and not use it, except in emergency.

When money comes in, the contract checks the most recent blockhash, and uses that to choose a slot, sending all money to that slot.

If the blockhashes differ (and they will differ post-fork), then the money will be controlled by different addresses in each universe. This makes replay attacks on cash difficult.

Note that it may not protect against authorization or function-call attacks.

How Many Slots?

Of course, you might end up in the same slot. Especially if you're going to be hand-coding in the addresses, the question of how many slots are needed is worth considering.

This is a variant of the birthday problem. If you'd like less than a 1% chance of overlapping, then you'll need about 200 slots. That could be a lot of work.

Instead, I would suggest instrumenting a 10 slot contract, and allowing ether to be re-sent through it in case of a collision -- 10 slots yields about a 18% chance of collision; in a small number of re-sends, one will be found which splits the funds in the two universes.

In Conclusion

Don't send ether out on the Classic chain for any reason unless you want to be replay attacked; first split your ether into new addresses, one per chain. Then you can enjoy.

If you have more difficult circumstances, e.g. money or tokens are locked by a committee, or other mechanism, you need a plan of action, and fast -- the details will vary.

I and my team are available for consultation around issues like these: feel free to contact me: [email protected].

Peter Vessenes

Read more posts by this author.

Subscribe to Peter Vessenes

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!