Last week EtherDelta, a decentralized exchange on the Ethereum network, experienced a security breach that impacted their users’ tokens. Compared to some of the security breaches of centralized exchanges in the past, the damage was relatively minimal, but it still seems like a good opportunity to have a discussion about the security of decentralized applications in general, and decentralized exchanges in particular.
What Happened?
At the time of this writing, many of the details of the breach are still unclear. What we know is that a hacker managed to hijack the DNS for EtherDelta.com, and route it to a malicious site that looked and acted like EtherDelta. The site was then able to steal funds from EtherDelta users who accessed the site while it was compromised.
What Went Wrong?
DNS hijacking is not a problem exclusive to decentralized services. At this point it’s unclear whether the hijacking was possible due to weak or poorly managed credentials on the part of EtherDelta, or if the problem might have originated with their registrar. What’s clear is that EtherDelta.com was, for a period of time, pointing to a malicious server.
Once the hacker was in control of EtherDelta.com, there were serveral ways they were able to take advantage of users who came to the site.
In-Dapp Wallets
One of the things the hacker may have exploited was EtherDelta’s in-dapp wallets. EtherDelta has a feature where users who aren’t using MetaMask or an Ethereum browser can create a wallet within EtherDelta. EtherDelta will generate a private key, encourage the user to save a backup of that key, and allow users to send, receive, and trade from the wallet that exists entirely within EtherDelta. This is convenient for users who don’t want to install a plugin or use a special browser, and simplifies the user experience for people who either may not know how to install a browser plugin, or may not want to.
The In-Dapp Wallets were stored in the user’s browser using HTML5 localStorage, a feature of modern browsers that allows websites to save information in the user’s browser to be accessed by the JavaScript application in the future. Unlike cookies, which also store information for future use, localStorage doesn’t get sent to the remote server with HTTP requests, and is only available to the application; this is convenient for sensitive information like private keys, which you don’t want the remote server to possess. Additionally, localStorage is only accessible to websites on the domain that stored the information, so private keys stored by EtherDelta.com wouldn’t be accessible when you visit any other website.
Unfortunately when the hacker compromised EtherDelta.com, they were able to replace the JavaScript application with one that may have retrieved the keys from localStorage and sent them to the hacker. Anyone who uses EtherDelta’s in-dapp private keys and visited EtherDelta.com during the compromise should assume that the hacker is in possession of the private keys, even if they have not yet used them.
Key Uploads
Another consequence of using In-Dapp wallets is that if a user wants to access EtherDelta from multiple devices (or even multiple browsers on the same device) they have to import their private keys. Anyone who imported their private keys while the hacker was in control of EtherDelta.com should assume those keys have been compromised.
How could this be prevented?
While In-Dapp wallets are convenient, Ethereum browsers like Mist and browser plugins like MetaMask offer a much better security model. With Mist and Metamask, applications never get possession of your keys. They can request that the browser sign messages or transactions, and the browser will prompt the user to confirm that they want to sign this message or send that transaction. The web application will get the signed message or a hash of the sent transaction, but very importantly it never comes into contact with the private keys.
If Dapps consider In-Dapp wallets an absolute must for their user experience, there are additional steps they can take to get a bit more security. The application could require the user to provide a password, and encrypt the generated private key with that password. At a minimum, this means that the user has to input their password before their keys can be compromised, instead of having them stolen from localStorage the moment they land on the website.
What does this mean for OpenRelay?
While we think the 0x protocol offers some security advantages over EtherDelta, both systems have to deal with the trade-offs of the convenience and user experience of In-Dapp wallets, vs the security offered of an Ethereum Browser or Plugin.
OpenRelay’s affiliate model means that many different websites may provide front-ends for OpenRelay. Once we are ready to launch our affiliate program, we will have a well-defined security policy for our affiliates to follow. We are currently discussing whether we will even allow affiliates to use In-Dapp wallets in a context associated with OpenRelay, but we will certainly encourage the use of Ethereum browsers like Mist and MetaMask.
Exchange Contract Control of Assets
Even if you’re using MetaMask or Mist instead of the In-Dapp wallets, EtherDelta requires users to send their tokens to the EtherDelta Exchange Contract. When the hacker took over EtherDelta.com, they could change what address the tokens were sent to. A very astute user might have noticed that the tokens were being sent to an address that wasn’t the usual EtherDelta contract address, but the vast majority of users would just accept that the address was correct and approve the transaction.
Another issue is that for an extended period after the hack was detected EtherDelta.com was completely offline, leaving no easy way to interface with the EtherDelta contract and withdraw the tokens it is holding. There are some guides on how to withdraw funds through other means, but these are even less accessible to less technical users than browser plugins.
The 0x Approach
With 0x, tokens are traded straight out of your wallet. You don’t have to send your tokens to an exchange contract in order to trade them, you just have to approve the 0x Token Transfer Proxy Contract to move those tokens on your behalf. The tokens stay in your wallet, and can only be moved if you submit an order to the 0x Exchange Contract, or someone else submits an order you digitally signed to the 0x Exchange Contract.
Now, this isn’t a silver bullet. Someone who hacks a 0x based relayer or affiliate could trick you into approving transfers to their address instead of the Token Transfer Proxy’s address. However, if you use unlimited allowances, you should never need to approve the same token twice from the same account. If a website is asking you to approve a token you’ve already approved, that’s a sign that something is amiss.
Another problem is that when you sign a 0x order, at present the message you sign is not very informative. A typical signing dialog looks something like this:
So you might think you’re signing a message authorizing the trade of 10 token ABC for 5 token XYZ, but you’re actually signing a message authorizing the trade of 10 ABC for .0005 XYZ redeemable only by the hacker. The 0x Project team has sponsored EIP-712, which would offer a better user interface for message signing, so you could have greater certainty around the message you’re signing.
Finally, if you’re using a 0x relayer for trading tokens and your relayer of choice goes offline for a while, your tokens are still there in your wallet. If you want to find somewhere else to trade them, you can just find a different relayer and find trades through them. All 0x relayers rely on the same 0x Token Transfer Proxy, so you won’t even have to approve the transfers again.
More Advanced Solutions
While EtherDelta is a decentralized exchange, what was compromised last week was DNS, a centralized component of the stack. Some Dapps are going to great lengths to elimiate any centralized components from their stacks.
It would be possible for a Dapp to host its front-end application IPFS or swarm and point to the front-end application using ENS. That reduces the likelihood of compromising centralized services, but at a trade-off of convenience for the user. Very few users today are using browsers that support IPFS / Swarm and ENS Domain resolution, so it’s not very feasible to build an application with a substantial user base without some centralized components.
Even if an exchange were completely decentralized, someone has to hold the keys to update ENS records, and if those keys get compromised the ENS record can end up pointing to the wrong content just as a DNS record can. This might be mitigated by using multisig contracts or even more complex community governance systems to manage ENS records, but increased management complexity adds to the likelihood that the management contracts have bugs of their own.