TLDR
- Ethereum is the world’s largest blockchain because it was the first blockchain to support smart contracts, creating opportunities for developers to build and deploy their dapps. Since the blockchain mined the genesis block, over 44 million smart contracts have been deployed on Ethereum. Smart contracts allow multiple parties to conduct transactions without an overseeing third party. A drawback is that developers cannot edit them after deployment.
- Ethereum smart contracts are unique because they power most of the prominent DeFi protocols in existence today holding billions of US dollars total value locked. While this is a welcome development,smart contracts are not as secure as we think. This is evident in the list of previous bold attacks on DeFi protocols.
- These exploits are caused by many reasons, ranging from EVM’s infrastructure to vulnerabilities and bugs in the code. This post explores prevalent vulnerabilities, the current state of smart contract security, We also look at the available vulnerability analysis tools with focus on the latest advancement and research in the past five years. Finally, we break down the various analysis methods and examine the countermeasures of prevalent vulnerabilities.
Citation
[1] Aryal, Binod. Comparison of Ethereum Smart Contract Vulnerability Detection Tools. Diss. Master’s thesis. University of Turku. 2021.
[2] Zhou, Haozhe, Amin Milani Fard, and Adetokunbo Makanju. “The State of Ethereum Smart Contracts Security: Vulnerabilities, Countermeasures, and Tool Support.” Journal of Cybersecurity and Privacy 2.2 (2022): 358-378.
[3] Kushwaha, Satpal & Joshi, Sandeep & Singh, Dilbag & Kaur, Manjit & Lee, Heung-No. (2022). Ethereum Smart Contract Analysis Tools: A Systematic Review. IEEE Access. 1-1. 10.1109/ACCESS.2022.3169902.
Terminologies
- Transaction: Transactions are cryptographically signed instructions from Ethereum accounts that updates the state of the network. The simplest transaction is sending ETH from one account to another which is broadcast to the whole network before. Furthermore, transactions require a fee (gas) to be added to a block.
- EVM: The Ethereum Virtual Machine is the software that executes Ethereum smart contract transactions. In detail, when given a transaction, inputs and a target smart contract, the EVM executes the transaction and updates the state on the blockchain. It hosts all the dapps live on the Ethereum network, distinguishing it from Bitcoin.
- Solidity: Solidity is Ethereum’s programming language inspired by JavaScript and is compatible with EVM for smart contract development.
- The DAO: The DAO was an Ethereum community-led venture capital fund. After raising 12.7M Ether ($150M at the time or $44.4B in today’s valuation), it made history as one of the largest crowdfunding campaigns. Unfortunately, a hacker stole 28% of the funds a month after the token sale.
- Mishandled Exceptions: Solidity uses state-reverting exceptions to handle code/transaction errors. Exception undoes all changes, but Solidity handles exceptions uniquely at different times. In addition, the basis of exception handling is the interaction between contracts which makes the contracts vulnerable to attacks when the compiler doesn’t handle exceptions properly.
- Static Analysis: Static analysis analyzes a computer program or compiled code without it. Static analysis techniques aim to examine execution paths, vulnerable patterns, and flawsthat would otherwise appear during the execution of the program.
- Dynamic Analysis: Dynamic analysis is a method that checks a programming application while it is executing. It can validate the findings from a static code analyzer, as well as explore execution paths that it could have missed (e.g., due to resource contraints or time limits).
- DASP10 vulnerabilities: DASP (Decentralized Application Security Project) is an initiative of the NCC group that identifies the top 10 categories of Ethereum smart contracts vulnerabilities.
Research Questions
- What are the major attacks on Ethereum which caused major losses?
- How many vulnerabilities/bugs are present in smart contracts?
- How do attackers exploit these vulnerabilities?
- What tools and analysis methods are available to identify these vulnerabilities?
- How long do these tools require to identify the vulnerabilities?
- What are the accuracy, efficiency, and limitations of existing security-analysis tools?
Background
Introduction
Findings indicate a lack of a uniform set of smart contract vulnerability definitions. Bugs of the same cause were sometimes labeled differently, making it difficult for researchers to analyze, identify, categorize and mitigate vulnerabilities. This situation was only worsened with time, as,hackers continued to exploit different different protocols manipulationg various and oftentime large sums of money. Famous attacks such as The DAO reentrancy attack, the Parity wallet bug, and the 63 historic exploits on Ethereum best illustrate this problem.
[1] In the case of the DAO exploit, issues involving race conditions, failure to store and protect data, and improper access controls allowed the attack to occur. In essence, the DAO’s smart contract relied on a low level function (.call) to transfer Eth to a target recipient (itself a smart contract). Following Solidity’s semantics, such a call triggers the execution of the fallback function in the target recipient . In this case, the attacker would again invoke the withdraw function, allowing him to make multiple withdrawals invocations as this process repeated.At each withdraw call, the account balance was updated only after each .call invocation, corrupting the internal balance of each recipient (the latter would only be updated after all withdrawals) . Because of this contract loophole, the attacker was able to transfer the available funds repeatedly.
For the Parity Multis-Sig Wallet Attack, a vulnerability found on the Parity Multisig Wallet version 1.5+ allowed an attacker to take ownership of the victim’s wallets with a single transaction. In this hack, the attacker stole about 153,000 Ether (~$30M) at the time, the second-largest hack on the Ethereum network at the time.
To help mitigate some of the attacks such as the DAO and parity hacks, smart contract security researchers have developed analysis tools to identify and help eliminate potential vulnerabilities
Summary
[2] Previous researchers have identified and presented many types of Ethereum-based vulnerabilities. Huashan et al. suggests 40 vulnerabilities; next, we outine some of these vulnerabilities for which severe exploits happened before.
Note: Vulnerabilities have a root cause, possibly due to misunderstanding of the programming language in which a smart contract is written on (in the case of Ethereum, generally Solidity) or issues within the EVM itself. The vulnerabilities directly relating to Solidity are explained below.
Re-entrancy: This is one of the most famous vulnerability attack vectors. While re-entrancy on its own is not a vulnerability, it opens the room for potential hacks to occur (e.g., as in the DAO hack). Re-entrancy is a potential issue whenever the execution flow returnns back to the smart contract in which the transaction started; if state changes only occur after such calls, results can be disastrous… The snippet below captures the case where re-entrancy is indeed a bug:
The snippet shown contains a reentrancy bug in line 3. The caller/attacker could call the code’s function multiple times before his balance account is zeroed (line 4). While in Solidity re-entrancy is an inherit language feature, there are two basic strategies to mitigate it. One option is to not use .call, but rather rely on the transfer function. The latter has a fixed gas stipend of 2300; call does not have a limit. Hence, by relying on .transfer, the triggered fallback function will not have enough gas to re-enter the caller contract. The second solution is to add a “lock,” which is just a state variable that shows the state of external calls and permits the external call only if the state is right. Existing frameworks provide a reusable implementation that developers can directly make use of (e.g., OpenZeppelin, with the nonReentrant modifier).
Freezing Ether: This vulnerability is known as greedy contracts and locked money. Smart contracts are designed to be able to receive and send Ether. A freezing-ether smart contract is a contract that can only receive Ether with no function to send it out. Therefore, any ether sent to such a wallet/address is frozen. To mitigate the issue, developers should avoid designing contracts without functions to withdraw Ether as a countermeasure.
Tx.origin: The tx.origin is a transaction-context variable storing the original caller’s address (i.e., where the transaction originated from). This contrasts with msg.sender, which denotes the last caller with the execution flow. If one relies on tx.origin as a means to control access to a priviledged function (e.g., a function what should only be allowed to be executed by an admin), there is the risk a legit authorized address starts a transaction whose execution flow ends-up calling a function in a malicious contract; the latter, could in turn rely on tx.origin to gain access to the priviledged function back in the contract where the transaction execution started from. TThe mitigation here is clear: never use tx.origin when implementing access controls…
Call to Unknown: The Call to unknown vulnerability occur when a function that doesn’t exist in the target contract is called. Following the EVM semantics, calling an inexistent function in a target contract triggers the fallback function of the latter to execute, automatically posing a re-entrancy attack risk. Other risks also exist: the target fallback function could simply revert, canceling the original transaction. In the latter case, the attacker would cause a Denial-of-Service attack on the original contract. There is no straight way to mitigate this issue; at best, to avoid the issue, one has to know the protocols/contracts they are interfacing with and whether they can be trusted or not.
Gasless Send: The Ethereum blockchain has a maximum gas limit. Gas is paid with every transaction/execution. Sometimes, the provided gas for a given transaction is fully consumed before the transaction ends, causing the latter to revert… This becomes tricky when transfering funds. When someone calls .transfer to move eth to a target contract, the fallback function of the latter executes. Calling .transfer relies on a default and non-adjustable stipend of 2300 gas units given to the fall back function. Hence, if the logic inside a fallback function requires spending more that 2300 gas units, the transfer will fail. There are two approaches to circumvent this: (a) use .call instead, and rely on a different gas stipend, which opposed to .transfer, can be set to any value; or (b) keep the fallback function logic as simple as possible and within the 2300 gas limit - this may require creating new functions to absorb the code taken from the fallback logic and change the way the execution flow was originally designed. While (a) certainly works for all cases, it requires developers to abide by a specific best practice. It also comes with a risk: if a developer is not fully aware of how .call works, using it may open the room for a hack similar to the DAO attack. Hence, (b) is oftentime the best option to take as a mitigation strategy.
Timestamp Dependence: During Ethereum’s PoW consensus phase, blocks are created by miners who have a certain degree of influence on the timestamp of each block. All transactions recorded on the block have the same timestamp. Since miners decide the timestamp of transactions, some transactions are susceptible to malicious miners. The miner/attacker may manipulate the timestamp of a block to trigger certain behaviors from the smart contracts.The countermeasure was to use block.number instead of block.timestamp.
Exception Disorder: Exceptions are errors/deviations in the Solidity code. When an exception happens, one should expect the entire transaction to fail. However, some low-level functions, such as .call, do not propagate exceptions to its callee, but rather, it returns ‘false’ as a return value. Hence, if a developer does not check the return value of such a call, throwing an exception in the case where it returns false, a transaction may be made final whereas in turn it should have failed. The mitigattion is clear: always handle return values.
Default Visibility: Solidity provides different access control modifiers for the functions and variables within a contract, namely :public, private, external, and internal. If a developer writes a function without an access control modifier, it defaults to public. This means that anyone interfacing witht the contract would be able to call that function, which may not be the intended desired. To avoid this, developers must determine the specifiers. Solidity also warns when a function is without a specifier while compiling.
Vulnerabilities due to EVM
The Solidity programming language is not the only cause of smart contract vulnerabilities. Various vulnerabilities are also linked with EVM. Examples include:
- Immutability: Due to the blockchain’s immutable nature, once a smart contract is deployed, its code cannot be changed Unless a contract is behind a configurable proxy contract. attackers can exploit any bugs they detect, like in the case of the DAO hack and other numerous exploits. Making use of configurable proxies fully eliminate this issue though. Conceptually, this works as follows: If one desires a contract C to be upgradable, a proxy can be deployed and parameterized with a contract address (in this case C.address); all functions in C are written in a way that only the proxy can call. If C proves to be buggy, one can deploy a new version of C, say C1, and change the state of the proxy to now use C1.address. C0 is now unusable and the any calls to the proxy are then routed to C1. Full details on how to make use of proxies can be found here.
- Ether lost in transfer: Ethereum addresses are 160-bit sequences associated with either a wallet or contract. Addresses without this feature are called orphan addresses. It is not possible to initiate a transaction from those addresses, but it is possible to send funds to them. An attacker can create orphan addresses and use them to lock received funds forever. Also, a one-digit mistake in the address could send ether to the wrong account.
- Stack-size limit: EVM’s call stack size.) was originally bounded to 1024 frames, For context, a transaction constitutes of an execution flow made of a sequence of function calls (at least one); each time a function calls another, the call stack grows by 1. When the call stack reaches the maximum size of 1024 and another function is called, the EVM raises an exceptionan. Until October 18th, 2016, it was possible for an attacker to exploit this issue, for instance, when developers mishandlled exceptions (see “Exception disorder”) An Ethereum hard fork addressed the issue.
Comparison static and dynamic analysis methods
There are two major analysis methods: static and dynamicStatic analysis can detect gas-related vulnerabilities and other key vulnerable patterns in smart contracts. However, it cannot detect vulnerabilities while the code runs. On the other hand, dynamic analysis is used to identify buggy contracts as they execute. Use cases include checking for unsecured balances, lock-and-leak-contract-fund, destroyable contracts, etc.
It is worth mentioning that within static analysis techniques, there are those that can be used to prove certain properties of a smart contract. This is known as formal verification. Compared to the other analysis methods, formal verification is far-reaching as it checks vulnerabilities with methodologies like separation logic, theorem provers, and translating EVM-byte code to formal languages. It comes with the cost of requiring extra expertise in writing a formal specification of the target contract, as well as scalabity issues of existing techniques.
Smart Contract Analysis Tools
Since the DAO hack made contract vulnerabilities known in 2016, several analysis tools have been invented. The figure below shows the year-wise evolution of analysis tools up to November 2021.
Analysis tools are necessary for checking and analyzing smart contract codes for potential security flaws. They are mainly categorized based on their analysis methods - mentioned in the previous section. Furthermore, the categorization is broken down based on the tools’ input for their analysis. The researchers in paper 3 propose a framework for categorizing the analysis tools based on the type of analysis and type of input to the tool:
Criteria of tools to be used:
Currently, there are about 87 known vulnerability analysis tools. However, using every one of them is cumbersome, so researchers created the following criteria to narrow which tools to consider:
- The tool is open source/publicly available while supporting a command line interface (CLI). The CLI increases the scalability of the analyses.
- The tool can identify vulnerabilities, bugs, and bad practices. This excludes tools that only construct control flow graphs, but do not output anything else.
- And finally, the tools should be able to support SmartBugs, an automated tool simplifying the execution of analysis tools on datasets of smart contracts.
From above criteria and recommendations by various Ethereum smart contract security enthusiasts and developers, the set of tools for analysis narrows to : HoneyBadger, Maian, Manticore, Mythril, Osiris, Oyente, Securify, Slither, SmartCheck, NPChecker, Sereum, Mad Max.
Accuracy, efficiency, and limitations of existing security-analysis tools: A Comparison of recurring tools.
- NPChecker: This tool analyzes non-determinism in smart contracts. After that, it performs systematic modeling to expose various non-deterministic factors. Non-deterministic factors are factors that could impact the results of the code and make them unforeseeable. Additional factors considered by NPChecker are block and transaction state, transaction execution scheduling, and external callees. Research about NPChecker reports high precision (only four false positives in a manual study of 50 contracts). The tool also unveils contracts vulnerable to recently-uncovered attack vectors while identifying variants of common smart contract bugs usually missed by existing research.
- MadMax: This tool is a static analysis tool that uses Gigahose IR to detect contract vulnerabilities. Gigahose IR (intermediate representations) is a lifter that converts low-level Ethereum virtual machine bytecode into high-level IR. MadMax automatically detects gas-focused vulnerabilities and uses a combo of two analysis approaches. The first approach is a control-flow-based decompiler, and the second is declarative program queries. This approach means the tool identifies high-level area-specific vulnerabilities. During a 2018 research, MadMax analyzed the entirety of smart contracts in the Ethereum blockchain in about 10 hours (with decompilation timeouts in 8% of the cases) and flagged contracts with a monetary value of over $2.8B as potentially vulnerable. Additional manual inspection of a sample of the flagged contracts shows that 81% of the sampled warnings contained vulnerabilities.
- Sereum: Sereum’s name is derived from “Secure Ethereum,” which focuses on protecting existing, deployed contracts against re-entrancy attacks in a backward-compatible way based on run-time monitoring and validation. Running Sereum does not require modification or prior semantic knowledge of existing contracts. The tool employs run-time monitoring and validation analysis in a backward-compatible way. Sereum also employs taint tracking to monitor the execution of a smart contract and the data flow from storage variables.
- Mythril: Developed by Consensys, mythril is an open-source analysis tool implemented for detecting integer overflow, reentrancy, and unchecked low-level calls. The tools use three approaches for analyzing smart contracts: symbolic execution, SMT solving, and taint analyses. Because of its analysis method, mythril is ideal for finding values that allow exploiting vulnerabilities in the smart contract. Mythril uses a default time budget that lasts for 11 seconds. to analyze contracts and detect vulnerabilities.
- Osiris: This is a static analysis tool implementedfor detecting arithmetic vulnerabilities. The tool detects arithmetic, reentrancy, and call stack vulnerabilities. Callstack bug detection is novel and not previously detected by Conkas or Mythril. Osiris output is very readable, making it easier for the user to follow and know what to expect. The average time taken is 6 seconds.
- Oyente: Oyente is similar to Osiris as its output is true/false. Oyente detects reentrancy, call stack depth, and integer overflow. Its detection is done by statically analyzing the program code path by path. The tool comprises an explorer, core analyzer, and validator; the explorer and validator use Z3 bit-vector solver to eliminate provably clean contracts during analysis. The average analysis time is 7 seconds.
- Slither: Slither is an analysis tool that accepts Solidity as an input. The tool’s immediate representation is known as SlithIR, and it employs data flow analysis and taints each tracking approach to detect vulnerabilities. Slither can be used for automated vulnerability detection, optimization detection, code understanding, and assisted code review. The open-source version of the tool detects about 20 bugs, an average of is 2.2 seconds.
- Smartcheck: This tool employs a lexical and syntactical analysis approach to analyze each smart contract. Smartcheck detects approximately 20 vulnerabilities, includingimplicit visibility modifier, un-fixed compiler version, style guide violation, etc. While running the test, there was no separate output to the terminal from the tool, but the time consumed was longer than average - 30 minutes.
- Honeybadger: Honeybadger was created to find honeypot smart contracts. Honeypots are code designed to make contracts look vulnerable (they set a bait), so others would send ether hoping to exploit the contract. Honeybadger performs a systematic analysis of honeypots, comprising three types of analysis pipeline: symbolic, cash flow, and honeypot analysis. Each type of analysis mentioned uses a Z3 SMT solver to check the satisfiability of constraints. The average time taken during analysis is six seconds.
- Maian: Similar to Manticore, this tool utilizes symbolic analysis and a concrete validation approach to discover the violation of specific properties in smart contracts. The specific properties in question are safety and liveness properties. Maian specializes in finding suicidal, prodigal, lock vulnerable contracts and processes contracts bytecode while building a trace of transactions to find and confirm the bugs. The time consumed is similar to that of Manticore - six minutes.
- Securify: Securify is an analysis tool with the EVM byte code as input and a set of security patterns for identifying smart contract bugs. Securify’s process involves a two-step analysis. The first step involves the symbolic execution of the contracts dependency graph while extracting specific vulnerability data. The second step is for compliance and violation patterns to prove whether a contract is bugged. As a quick testing tool, Securify would not qualify. That said, it detects reentrancy, delegatecall to insecure contracts, mishandled exceptions, and transaction order dependence. The average time taken during analyses is 8.28 seconds.
The image below also provides more context on the tools, methods used and vulnerabilities detected:
After comparing the output of the tools and analyzing their results, researchers discovered Slither, Osiris, and Mythril better detect more DASP10 vulnerabilities. Furthermore, the top five popular vulnerabilities detected by many tools are re-entrancy, gas-related, arithmetic overflow/underflow, timestamp dependency, and transaction ordering dependency. Finally, most tools employ the most popular top five analysis approaches which are symbolic execution, fuzz testing, constraint solving, code instrumentation, and code transformation.
Research Insights and Future Work
The goal of the papers synthesized in this discussion post was to provide an overview of the current state of analysis tools for Ethereum smart contracts. The researchers tested available vulnerability detection tools with smart contracts during this evaluation while recording their vulnerability detection percentage. They also used the DASP10 category to classify the vulnerabilities. One observation was that the current analysis tools could not detect vulnerabilities from two DASP10 types: Bad Randomness and Short Addresses. This shortcoming implies that researchers must do more work to improve the coverage of the tools.
Furthermore, there are many vulnerable contracts on the Ethereum blockchain. This is because developers sometimes do not properly analyze with automated tools and manual testing before deploying their code. Thus, the vulnerability is not detected beforehand, leading to a loss of funds. To avoid this, security experts recommend using the Ethereum compiler, analysis tools, or formal verification methods to check for errors before deploying their code.
More research is needed to enhance smart contract security further, especially in mitigating attacks while they happen. To achieve this, developers must create better and optimized analysis methods while looking for countermeasures to real-time exploits. A promising solution to the above and continuation of this work will be to investigate vulnerabilities in blockchain systems other than Ethereum - like Hyperledger Fabric, Tezos, Solana, Corda, NEO, and Cardano - with focus on overcoming the limitations.
References
There were many interesting articles that I studied while writing this discussion post. I would highly recommend reading Ethereum’s whitepaper for anyone who hasn’t read it already. To truly understand these vulnerabilities, background knowledge about smart contracts and their infrastructure is a must. You can also check their development documentation.
Below are the links to the other research papers and work I read for more context:
Security Analysis Methods on Ethereum Smart Contract Vulnerabilities — A Survey
Empirical Review of Automated Analysis Tools on 47,587 Ethereum Smart Contracts
TEETHER: Gnawing at Ethereum to Automatically Exploit Smart Contracts
Step by step towards creating a safe smart contract: Lessons and insights from a cryptocurrency lab.
A Survey on Ethereum Systems Security: Vulnerabilities, Attacks, and Defenses