Recently, I wrote about Fujitsu’s SASC (a tool to find 6 categories of smart contract vulnerabilities), it’s origin from the OYENTE tool (developed by Luu et al.) and what the findings mean. Nikolic et al. (2018) have developed MAIAN, a tool for trace vulnerabilities which is fundamentally different than the vulnerabilities researched so far.

What is a trace vulnerability?

Unlike SASC, OYENTE or ZEUS (another tool made available by researchers), Nikolic et al. don’t look at vulnerabilities that can be caused by a single invocation of a contract but rather at what can happen when many invocations are triggered over a period of time. A trace is just that, a series of invocations of a contract or how Nikolic et al. put it:

A transaction can run one invocation of the contract and an execution trace is a (possibly infinite) sequence of runs of a contract recorded on the blockchain.

The team focuses on three specific types of trace vulnerabilities: prodigal, suicidal and greedy contracts. The team specifies that they are trying to define the vulnerabilities with the intent and implementation discussion and the special circumstances in which contract should killable (e.g. when under attack or for bounties) in mind. Taking those aspects into consideration they arrive at the following (paraphrased) definitions:

Prodical contracts: Contracts that send Ether to arbitrary addresses that are not the owner of the contract, have never deposited Ether in that contract and have only provided data that is easily fabricated by a third party.

As an example they use a bounty contract that has a payout function without restrictions on the sender that needs two or more invocations.

Suicidal contracts: Contracts that can be killed by any account through invoking the suicide function.

As an example they provide the Parity bug. Here, there were also more than one invocation in play: The first invocation set _owners and _required of the contract’s initMultiowned function to 0. The second invocation called the kill function, which now did not need anyone to agree to its execution anymore.

Greedy contracts: Contracts that remain alive, lock Ether indefinitely and do not allow for the Ether to be released under any circumstances.

Parity serves as an example again, where after the Parity library was killed, contracts that used functions thereof where not able to release it’s Ether anymore. In addition, they name contracts that simply have no function build in to send Ether or contracts that include functions of that nature that are unreachable.

Additionally, Nikolic et al. define posthumous contracts as a subclass vulnerability of greedy contracts. Posthumous contracts are killed contracts that have an Ether balance greater than 0.

How does MAIAN work?

Based on the three vulnerabilities, MAIAN goes on the search for contracts that transgress the following parameters of the defined traces:

(a) of safety properties, asserting that there exists a trace from a specified blockchain state that causes the contract to violate certain conditions; and

(b) of liveness properties, asserting whether some actions cannot be taken in any execution starting from a specified blockchain state.

Simplified, it means that MAIAN is a) checking the contracts for outcomes that do no harm (or as they say “during a final execution nothing bad happens”), and once that has been confirmed, b) checking the contracts for desired outcomes (to quote once again “something good must eventually happen”).

In order to analyze the contracts MAIAN uses symbolic analyses and concrete validation.

Symbolic analysis

The analysis receives input in the form of the contract’s bytecode along with a number of parameters including:

Vulnerability category as defined above

Invocation depth: MAIAN has limits on the depth of it’s search, specifically a max_call_depth (default value = 3), a limit on total number of jumps on a path mac_cfg_nodes (default value = 60), a timeout of 10 seconds per call and a max_analysis_time of 300 seconds per contract.

Execution path search: A specified way of searching through the execution paths to ensure a balance between as many paths as possible and as little false positives as possible.

Data access: First-time accesses of global or blockchain storage on a path are stored into local mappines to enable successive local reads or writes.

Non-deterministic inputs: Non-deterministic inputs are treated as symbolic and their concrete values are not used.

Flagging violations: When a transgression is identified, a contract is marked a vulnerability candidate.

Pruning: Specific configuration that have multiple occurrences are only explored once in order to safe time.

Concrete validation

In order to validate it’s findings, a private Ethereum fork was created. An added new functionality to the go-ethereum package, enabled the researchers to fork the blockchain at a desired block height . A flagged contract is then executed with the values from the symbolic analysis, if the transgression cannot be confirmed MAIAN flags the candidate contract as a false positive otherwise as a true positive.

Prodigal contract candidates are tested for actual Ether leakage through a test account sequentially sending transactions and waiting to receive Ether back. If the contract does not have Ether, Nicolic et al. send Ether in first in order to test the potential exploitation.

Suicidal contracts are tested correspondigly. The bytecode of a killed contract is set to 0x, which is used to achieve a true positive.

For greedy contracts candidates it is already checked in the analysis whether the contract accepts Ether. If it does, the validation only needs to check for missing call, delegatecall or suicide functions in order to achieve a true positive.

Sidenote: I intentionally leave out more technical details which are nonetheless incredibly important and very well thought out. Please read the paper for more information.

What did MAIAN find?

MAIAN analyzed a total of 970,898 contracts (with an avarage of 10 seconds per contracts needed) starting from the very first Ethereum block until the last block of Dezember 26th, 2017 (block 4,799,998 to be precise). Since Ethereum only has contract bytecodes, they used Etherscan to obtain source codes where possible, resulting in source code for 9,825 contracts. The actual validation was performed at block 4,499,451 (where the ParityLibrary contract was still alive) in order to simplify the process and only contracts that were still alive at that block height were validated, the rest were only tested. Fig.1 shows the results of MAIAN:

Fig.1: Results of MAIAN’s analysis of nearly 1 million smart contracts

The team used a random subset for concrete validation, instead of the actually flagged contracts, and used the true positives rates (which use the original amount of contracts) to obtain their numbers.

MAIAN flagged a total of 34,200 (2365 distinct) contracts, representing 3.52% of smart contracts on the Ethereum blockchain. Greedy contracts make up the biggest portion of found contracts with 91.2%, followed by nearly identical findings for prodigal and suicidal contracts with 4.4% each. A total true positives rate of 89% shows the thorough work by Nikolic et al..

Sidenote: The reason for the relatively low true positive rate for greedy contracts lies in the nature of the greedy contracts definition and the strategy taken to invest them. Because Nikolic et al. explain it so well and detailed in their paper, I strongly suggest you read it if you have questions regarding that issue.

Greedy contract behavior is by far the biggest vulnerability, representing roughly 3.2% of contracts on the entire Ethereum blockchain! Very simplified, that means that for roughly every 30 contracts that you interact with there is a possibility that 1 of them has no means to release the Ether you sent to it.

Prodigal and suicidal contracts are far fewer but still represent a big threat to smart contract security. The number of contracts alone does not signify the importance of these findings, one of the contracts found being the ParityWalletLibrary contract that led to the loss of more than 200$ million in Ether. The relatively low numbers are a good indicator but should still be cause for vigilance and attention towards smart contract security.

Lastly, 853 posthumous contracts were found, meaning there are 853 contracts that are dead but still have Ether on them. One of the more interesting fun facts of MAIAN’s findings is that 294 of those received Ether AFTER they were killed.

Conclusion

Smart contracts and therefore smart contract security are one of the fundamental aspects of the Ethereum blockchain and the origin for the fast adoption of Ethereum. Nikolic et al.’s research shows that there is still a lot of room for improving the security of smart contracts, by proving the importance of accounting for trace vulnerabilities. 3.5% of all Ethereum smart contracts showed exploitation potential (including the Parity bug), a number that needs to be reduced to further drive adoption.

Tools like MAIAN provide developers with the mean to test their smart contracts and make the Ethereum blockchain a safer environment. Further research is of course needed (regarding vulnerabilities in general)because as the Ethereum environment is in constant change, so are the requirements for safe smart contracts.