A smart contract is “a computerized transaction protocol that executes the terms of a contract.”. There are obvious advantages of smart contract system: reduction of expenses and legal collisions, time-saving. Blockchain technology has one enormous stumbling block to be widely adopted. And this is security. Security is a critical issue in the case of smart contracts. Recent hacks of smart contracts raised the issue. These facts help to identify and analyze the vulnerabilities, finding potential solutions.
In this article, we gathered related material on Ethereum vulnerabilities and hacks from different sources. It will be useful both for developers of smart contacts and the researchers. Providing you with the common errors and human mistakes in smart contracts we aim to make a guide of their history and fixes, to promote the verification techniques for a smart contract.
The most mainstream and well-known smart contract was The DAO, which launched with US$250 million in ICO in May 2016, and then was hacked. This attack affected the further destiny of the Ethereum network remaining trust and security behind Blockchain technology achievements. Subsequent events changed the conception of Ethereum and Blockchain in general. Let’s see how:
- On June 17, 2006, the attacker drained approximately 3.5M ETH (~$50M) from the DAO smart contract, collected in an ICO a month earlier. The DAO hack occurred after the token sale had already ended.
- The attack happened due to a recursive calling vulnerability. The attacker withdrew Ether from The DAO smart contract multiple times using the same DAO Tokens. In this exploit, the attacker was able to call the split function recursively inside of the split, before the smart contract could update its own balance. There were two main issues that made this possible:
- When the DAO smart contract was creating the coders did not take into account the possibility of a recursive call.
- The fact that the smart contract first sent the ETH funds and then updated the internal token balance.
- The DAO has 663 lines of code (without empty lines and comments) — for roughly 860 commits by 18 different contributors. Statistics show, that there are up to 15–50 bugs per 1000 lines of code. Although extensive testing and auditing can significantly reduce this number, it is very hard to bring it down to 0.
- Therefore, smart contracts should be kept as simple as possible, doubly so when they are made immutable.
- The experts in the community suggested a soft fork to stop ETH draining.
- Hence, a solution was worked out by Vitalik Buterin the Ethereum Foundation on June 17, where he issued a critical update:
A software fork has been proposed, (with NO ROLLBACK; no transactions or blocks will be “reversed”) which will make any transactions that make any calls/callcodes/delegatecalls that reduce the balance of an account with code hash0x7278d050619a624f84f51987149ddb439cdaadfba5966f7cfaea7ad44340a4ba (ie. the DAO and children) lead to the transaction (not just the call, the transaction) being invalid…
- Another proposal was in the terms of infringement the rules and it was more aggressive: the hard-fork, the function of which would have only withdrawn function. The aim of this hard-fork was to ask miners to return all raised tokens to the DAO, refunding smart contract.
- From this contract, DAO token holders could submit their DAO in order to withdraw ETH at a rate of 1 ETH = 100 DAO.
- Having heard about the software fork proposal, the hackers stopped the attack.
- At the same time, there was a spontaneous formation of a Robin Hood Group, who drained the remaining funds of the DAO in order to prevent further hacks. The intention was also to hand the ETH back to its original owners.
- On July 20, 2016, hard-fork took place. After the hard-fork implementation, Ethereum Classic was born.
King of the Ether Throne, Rubixi and GovernMental smart contracts
To set the scene for the analysis of the security of smart contracts, let’s consider some examples of vulnerabilities, allowing the attackers to steal or tamper the assets. We have found a research paper providing the causes of the Ethereum smart contract vulnerabilities in a taxonomy. It is the work written by Nicola Atzei, Massimo Bartoletti, and Tiziana Cimoli (Universit`a degli Studi di Cagliari, Cagliari, Italy).
Let’s review next three smart contracts with such kinds of vulnerabilities:
- Gasless send: King of the Ether Throne
- Exception disorders: KoET, GovernMental
- Immutable bugs: Rubixi, GovernMental
- Stack size limit: GovernMental
- Unpredictable state: GovernMental
- Time constraints: GovernMental
The whole paperwork you can find here.
King of the Ether Throne
- The “King of the Ether Throne” is a game where players compete for acquiring the title of “King of the Ether”. If someone wishes to be the king, he must pay some ether to the current king, plus a small fee to the contract. Here is a simplified version of the game (with the same vulnerabilities), implemented as the contract KotET:
- Whenever a player sends msg.value ether to the contract, he also triggers the execution of KotET’s fallback. The fallback first checks that the sent ether is enough to buy the title: if not, it throws an exception (reverting the ether transfer); otherwise, the player is accepted as the new king. At this point, a compensation is sent to the dismissing king, and the player is crowned. The difference between msg.value and the compensation is kept by the contract. The owner of KotET can withdraw the ether accumulated in the contract through sweepCommission.
- Apparently, the contract may seem honest: in fact, it is not, because not checking the return code of send may result in stealing ether17. Indeed, since send is equipped with a few gas (see “gasless send” vulnerability), the send at line 17 will fail if the king’s address is that of a contract with an expensive fallback. In this case, since send does not propagate exceptions (see “exception disorder”), the compensation is kept by the contract.
- Now, assume that an honest programmer wants to implement a fair variant of KotET, by replacing send with call at line 6, and by checking its return code:
- This variant is more trustworthy than the previous but vulnerable to a denial of service attack. To see why, consider an attacker Mallory, whose fallback just throws an exception. The adversary calls unseatKing with the right amount of ether, so that Mallory becomes the new king. At this point, nobody else can get her crown, since every time KotET tries to send the compensation to Mallory, her fallback throws an exception, preventing the coronation to succeed.
- Rubixi is a contract which implements a Ponzi scheme, a fraudulent investment operation where the operator generates returns for older investors through revenue paid by new investors. Further, the contract owner can collect some fees, paid to the contract upon investments.
- During the contract elaboration, its primary name Dynamic Pyramid was changed to Rubixi. However, the name of the constructor was not correspondingly changed by the programmers. This function then became invokable by anyone. Due to it, the “immutable bugs” vulnerability was exploited. In such a way, the hack allows an opponent to steal some ether from the contract.
- The Dynamic Pyramid function sets the owner address; the owner can withdraw his profit via collectAllFees.
- After this bug became public, users started to invoke Dynamic Pyramid in order to become the owner, and so to withdraw the fees.
- GovernMental’s 1100 ETH jackpot payout was stuck because it used too much gas.
- GovernMental is another flawed Ponzi scheme. To join the scheme, a participant must send a certain amount of ether to the contract. If no one joins the scheme for 12 hours, the last participant gets all the ether in the contract (except for a fee kept by the owner). The list of participants and their credit are stored in two arrays. When the 12 hours are expired, the last participant can claim the money, and the arrays are cleared as follows:
- The EVM code obtained from this snippet of Solidity code clears one-by-one each location of the arrays. At a certain point, the list of participants of GovernMental grew so long, that clearing the arrays would have required more gas than the maximum allowed for a single transaction. From that point, any attempt to clear the arrays has failed. Let’s review a simplified version of GovernMental, which shares some of the vulnerabilities of the original contract.
- The contract Governmental gathers the investments of players in rounds, and it pays back only a winner per round, i.e. the player which is the last for at least one minute. To join the scheme, a player must invest at least half of the jackpot (line 14), whose amount grows upon each new investment. Anyone can invoke resetInvestment, which pays the jackpot (half of the invested total) to the winner (line 24), and sends the remaining ether to the contract owner. The contract assumes that players are either users or contracts with empty fallback, so not to incur in out-of-gas exceptions during send.
Let’s have a look at 3 different attacks to simplified GovernMental:
Attack #1. This attack exploits the vulnerabilities “exception disorder” and “stack size limit”, and is performed by the contract owner. His goal is not to pay the winner, so that the ether is kept by the contract, and redeemable by the owner at a later time. To fulfil this goal, the owner has to make the send at line 24 fail. His first step is to publish the following contract:
Then, the owner calls Mallory’s attack, which starts invoking herself recursively, making the stack grow. When the call stack reaches the depth of 1022, Mallory invokes Governmental’s resetInvestment, which is then executed at stack size 1023. At this point, the send at line 24 fails, because of the call stack limit (the second send fails as well). Since GovernMental does not check the return code of send, the execution proceeds, resetting the contract state (lines 27-29), and starting another round. The balance of the contract increases every time this attack is run, because the legit winner is not paid. To collect the ether, the owner only needs to wait for another round to terminate correctly.
Attack #2. In this case, the attacker is a miner, who also impersonates a player. Being a miner, she can choose not to include in blocks the transactions directed to GovernMental, except for her own, in order to be the last player in the round.
Furthermore, the attacker can reorder the transactions, such that her one will appear first: indeed, by playing first and by choosing a suitable amount of ether to invest, she can prevent other players to join the scheme (line 14), so resulting the last player in the round. This attack exploits the “unpredictable state” vulnerability, since players cannot be sure that, when they publish a transaction to join the scheme, the invested ether will be enough to make this operation succeed.
Attack #3. Also, in this case, the attacker is a miner impersonating a player. Assume that the attacker manages to join the scheme. To be the last player in the round for a minute, she can play with the block timestamp. More specifically, the attacker sets the timestamp of the new block so that it is at least one minute later the timestamp of the current block. As discussed along with the “time constraints” vulnerability, there is a tolerance on the choice of the timestamp. If the attacker manages to publish the new block with the delayed timestamp, she will be the last player in the round, and will win the jackpot.
- On January 4, 2017, Zack Coburn submitted a vulnerability report on EtherCamp’s implementation of the StandardToken contract.
- StandardToken.sol contract vulnerability was found in the transferFrom() function:
- =+ is a vulnerability. In this case, it should be +=
- The effect is that 0x2ccc5a059a1bda4c3c3c594516e812a0b15799c9’s balance has been reduced from 5,000,000 HKG to 0.001 HKG.
- There was recommended a fix by Zack Coburn:
- Create a new HKG contract that fixes the bug and initializes all balances to what they were before the above transactions.
- Any dapps that keep track of HKG balances internally (i.e., EtherDelta) need to be taken into account so that people who were holding balances inside such smart contracts get their tokens back.
- Exchanges and token users will need to be notified about the transition to a new token contract.
- This kind of bug is commonplace and was made due to a human rather than conceptual mistake. In order to prevent them, the developers should use the right tools for improving and correcting the product.
- A good solution for this problem to be further prevented is the SafeMath library. Any math operations should be checked and safe.
- On June 29, 2017, Bithumb exchange discovered a breach. The hackers managed to stole user data and money from Bithumb.
- The personal information of 31,800 Bithumb website users was grabbed. It included users’ names, mobile phone numbers, and email addresses.
- The attack was committed not directly to the exchange’s internal network and digital currency wallets, but to a personal computer belonging to an employee.
- After the credentials have been stolen the hacker started a process voice phishing, where the scammers call up victims one at a time and pose as representatives of Bithumb.
- The attacker posed as a Bithumb executive and asked the victims to give him an “identification number written on the letter from Bithumb.” The number in question was the victim’s One-Time Password, (OTP) which granted the attacker immediate access to ten million won, worth about US$8,700.
- The exchange posted a notice on their website stating that “compensation for personal information leakage cases has been decided.”
Classic Ether Wallet
- On June 30, 2017, the unknown hackers managed to get access to the domain Classic Ether Wallet. They used social engineering in order to mislead the employees of web host 1and1, pretending to be the real domain owners.
- Having gained control over the domain, the attackers changed the domains’ settings and immediately began to direct users to their server.
- This attack is called phishing scam.
- The team immediately started warning users over Twitter to stop using the service
- The users even offered to arrange a DDoS attack on the domain to take it offline, as they found it the fastest way to stop criminals actions.
- But after a few hours later the Classic Ether Wallet managed to convince Cloudflare to place a phishing warning that will appear to anyone who would try to access the website. The issue was resolved.
- To stay safe the users could use My Ether Wallet and connect it to the ETC node.
- Reddit users shared a number of ETC addresses, where their funds were located. Thus, it was possible to calculate the sum in total stolen by the hackers. It was about $ 300,000.
- In order to reduce the chances to be detected the attackers split these funds among different wallets.
Augur REP Token
- Augur’s smart contracts are written in Serpent language
- On July 13, 2017, Zeppelin Solutions, a technology company focused on improving blockchain technology, security, and infrastructure, contacted the Augur team to privately notify them about 8 critical severity vulnerabilities in Serpent project.
- These critical bugs were found through an audit. The critical vulnerability was in the Serpent compiler’s code, not in Augur’s code.
- According to the Augur REP Token Critical Vulnerability Disclosure a few days later, Zeppelin Solutions found one of those critical vulnerabilities affected the production REP token. In a nutshell, an out-of-bounds write on the token’s reputation array allowed an attacker to modify the creation timestamp, making it believe the crowdsale was still ongoing and disabling all token transfers. This critical severity vulnerability, if exploited, could have halted the whole REP economy, worth over $200 million.
- First, Serpent contracts can overwrite storage locations when accessing arrays out of bounds. This means that if a Serpent contract attempts to access an array at a position greater than the array’s length, Serpent won’t stop it.
- Second, the Serpent language is untyped. It allows any operation to be performed on any data. Every value is a 256-bit sequence which can be used as an address, a contract, an integer, or an array. Moreover, it performs no checks on the data sent by a user on a transaction.
- ZS proposed a mitigation plan to reduce damages to the Augur project, which was accepted by their team. It included:
- Writing a new REP smart contract in Solidity, based on OpenZeppelin’s reusable components.
- Auditing the new REP token contract.
- Disclosing to exchanges and wallet providers on July 24, 2017, 25 hours before public disclosure.
- Deploying the new REP token contract to the Ethereum blockchain.
- Freezing the old REP token on July 25, 2017.
- Migrating the balances of the frozen REP token into the new REP token.
- CoinDash, Israeli blockchain technology startup project, was hijacked by the hackers on July 17, 2017.
- In the middle of its ICO, the attackers withdrew $7 Million worth of Ether tokens. Investors sent 43438.455 Ether to the wrong address under the hackers’ control.
- The attackers hacked CoinDash’s site and changed their ETH for an ICO address to their own fund store.
- An estimated 43,500 ETH were redirected to the perpetrators’ wallet address.
- CoinDash team claimed in a statement on its site that they were responsible to all the contributors and would provide tokens (CDTs) to people who sent ethereum to the fraudulent address.
- On July, 19 2017, there was a security alert on about a vulnerability in Parity Wallet’s variant of the standard multi-signature contract.
- A vulnerability was discovered on the Parity Multisig Wallet using Parity client version 1.5 or later (that was released on the 19th of January 2017)
- The hacker managed to steal over 150,000 ETH (~$ 30M) from three multi-sig contracts. Here is the data.
- The bug was ranked as a critical one in a specific multi-sig contract known as wallet.sol.White Hat hackers rescued funds from vulnerable multisigs.
- Parity urged the users to immediately move their funds to other wallets such as MyEtherWallet, a Geth node, or any single-user wallets created on Parity.
- According to Zeppelin Solutions, the attacker sent two transactions to each of the affected contracts: the first to obtain exclusive ownership of the MultiSig, and the second to move all of its funds.
- Let’s consider the detailed description of the vulnerability analyzed by Open Zeppelin’s team below. The source: The Parity Wallet Hack Explained:
- We can see that the first transaction is a call to initWallet (line 216 of WalletLibrary):
- This function was probably created as a way to extract the wallet’s constructor logic into a separate library. This uses a similar idea to the proxy libraries pattern. The wallet contract forwards all unmatched function calls to the library using delegatecall, in line 424 of Wallet:
- This causes all public functions from the library to be callable by anyone, including initWallet, which can change the contract’s owners. Unfortunately, initWallet has no checks to prevent an attacker from calling it after the contract was initialized. The attacker exploited this and simply changed the contract’s m_owners state variable to a list containing only their address, and requiring just one confirmation to execute any transaction:
- After that, it was just a matter of invoking the execute function to send all funds to an account controlled by the attacker:
- This execution was automatically authorized, since the attacker was then the only owner of the multisig, effectively draining the contract of all its funds.
The solution. The attack could have been prevented either by not extracting the constructor logic into the library contract altogether or better by not using delegatecall as a catch-all forwarding mechanism. The recommended pattern is explicitly defining which library functions can be invoked externally on the wallet contract.
It is important to note that the technique of abstracting logic into a shared library can be quite useful, though. It helps improve code reusability and reduces gas deployment costs. This attack, however, makes clear that a set of best practices and standards is needed in the Ethereum ecosystem to ensure that these coding patterns are implemented effectively and securely. Otherwise, the most innocent-looking bug can have disastrous consequences.
- On July 19, 2017, due to the vulnerability in the Ethereum wallet Parity, about 32.4% of the fund’s assets or about $ 7M were withdrawn by the hackers from Satoshi Pie.
- Most of the funds were withdrawn within an hour. The project team managed to rescue the remaining funds sending them to a new wallet.
- The hack led to not identified accounts. However, it was carried out by the White Hats Group who created new wallets with multipoles with the same characteristics that have affected the vulnerability of wallets.
- The error was found in a separate contract with multipoles known as wallet.sol.
- Here is the history of the vulnerability solutions and recovery strategy (the source of information: https://steemit.com/ethereum/@hipster/updates-satoshi-pie-ethereum-multisig-has-been-hacked ):
- Estimation of vulnerable code based on contract version where White hats are sending values.
8 lines updated
- Parity Blog published a new version of contract in Parity Github PR.
- Future multi-sig wallets created by versions of Parity are secure. Fix in the code is https://github.com/paritytech/parity/pull/6103 and the newly registered code is https://etherscan.io/tx/0x5f0846ccef8946d47f85715b7eea8fb69d3a9b9ef2d2b8abcf83983fb8d94f5f
- Recovery strategy was as follows:
- to provide best in breed blockchain asset management service.
- to change valuation cycle from 24 hours to 1 week for Satoshi Pie product.
- to implement a hard limit on deposits and withdrawals at 10 BTC for one transaction. Fewer transactions should go through the market.
- to move Ethereum holdings (if recovered) to Zeppelin smart contract framework.
- to publish bug bounty program.
- to publish the new version of Satoshi Pie white paper
- The new contract deployed by WHG has been verified
- All values have been returned under SatoshiPie control.
- There is the new contract.
- On July 23, 2017, Veritaseum was attacked by the hacker during an ICO who managed to redirect Veritas (VERI) tokens to an unknown digital wallet.
- Approximately $8.5 million worth of VERI tokens were stolen from the company.
- Veritaseum was under scrutiny by community members who were skeptical of the company’s security protocols that lacked SSL, or cryptographic protocols used to relay information across a computer network.
- In order to foul their trails, the hackers dumped the tokens into two separate wallets, then directed to other accounts.
- The hack is still being investigated, and so far there is limited information out there.
1. The DAO, The Hack, The Soft Fork and The Hard Fork
2. The History of the DAO and Lessons Learned
3. Classic Ether Wallet Falls Victim to a social Engineering Hacker
4. Classic Ether Wallet has been hacked – do not use it to send currency
5. A survey of attacks on Ethereum smart contracts
7. Massive “Hack” Hits Ethereum Parity Clients – More Than $30M Of Ether Still At Large
8. Hackers have stolen $32 million in Ethereum in the second heist this week
9. [Updates] Satoshi•Pie Ethereum multisig has been hacked
10. Veritaseum Hacked
11. Fourth largest Bitcoin exchange. Bithumb, hacked for billions of Won
12. One of the Biggest Ethereum and Bitcoin Exchanges Got Hacked
13. Post-Mortem Investigation
14. Augur REP Token Critical Vulnerability Disclosure
15. HackerGold Bug Analysis
16. Vulnerability in StandardToken.sol’s implementation of transferFrom() #8