Howard Poston

View Original

Introduction to Blockchain: Smart Contracts

In the beginning, blockchain was designed to replace the financial system.  The distributed, decentralized ledger maintained by the blockchain network is used to record the transactions performed using the blockchain financial system.  As a result, cryptocurrencies like Bitcoin can implement complete, trustworthy financial systems without a central authority (like a bank).

The distributed, decentralized ledger offered by blockchain technology is useful for more than just recording financial transactions.  Smart contract platforms are designed to run a Turing-complete computer on top of the blockchain, allowing smart contracts to fulfill a variety of different functions.

Introduction to Smart Contracts

Smart contract platforms use the underlying blockchain technology but modifies it to use it to run arbitrary, third-party programs on top of it.  Instead of transactions including actual financial transactions, they include computer instructions designed to be run by the blockchain’s virtual machine.

Since the blockchain network is distributed and decentralized, there is no central computing platform that runs the code and updates the state of the smart contract platform with the result.  Instead, each node in the network runs its own copy of the virtual machine and executes the code contained in the transactions in each block of the blockchain. Since code is designed to be deterministic and is organized into a block before execution, the network is able to remain synchronized at all times.

Smart Contract Security

The blockchain landscape is fragmented, and so is the landscape of smart contract blockchains.  The basic blockchain solution has been adopted and adapted in many different ways, making it difficult to create a definitive list of smart contract vulnerabilities.

Since Ethereum is the best-established smart contract platform, many lists of smart contract vulnerabilities focus on this.  The Decentralized Application Security Project has compiled a list of the most common smart contract vulnerabilities on the Ethereum platform, which are explored here.

Reentrancy

Reentrancy is probably the most famous of the Ethereum smart contract vulnerabilities.  Exploitation of this vulnerability in The DAO smart contract caused Ethereum to break its blockchain’s immutability and rewrite history to erase the attack.  This controversial decision caused a split in the Ethereum network that created the Ethereum Classic cryptocurrency.

Reentrancy is possible in Ethereum due to the existence of payable fallback functions.  These functions are designed to run when value is sent to the smart contract, allowing it to update its internal ledger, perform some functions, etc.

The issue with this setup is when a vulnerable smart contract function that the attacker can control (like a refund function) can be forced to call a malicious fallback function.  Vulnerable functions use the following control flow:

  1. Check transaction validity

  2. Perform send

  3. Update internal ledger

With this control flow, the malicious fallback function is run as a part of step 2, before the vulnerable function updates state.  If it calls the vulnerable function again, the transaction will still be considered valid (since the state isn’t updated) and run again, allowing the attacker to withdraw twice as much value as approved.

Access Control

Some smart contracts are designed to have protected functionality.  For example, you can implement wallets as smart contracts where anyone can send value to it but only the owner can extract value from it.

Some of these smart contracts have a function for claiming ownership, where the owner of the smart contract (and the one permitted to call protected functionality) is set to the person who called the function.  The issue with these functions is that sometimes people forget to set the function to check that this is the first time the function is called. If they fail to do so, the owner is whoever called the function last, not first.

Arithmetic

Arithmetic vulnerabilities like integer overflows and underflows are nothing new with blockchain.  They’ve existed in software programming for some time and have only become less common due to the existence of programming languages that make them impossible (like Python).  Unfortunately, some smart contract programming languages are now vulnerable.

Arithmetic vulnerabilities occur when certain variable types are misused.  Integer overflow vulnerabilities occur when a programmer uses too small of a variable to store a value.  Underflow vulnerabilities occur during switches between signed variables (where a one in the most significant bit means negative) and unsigned variables (where a one in the most significant bit means a large, positive number).  Performing subtraction with unsigned values always results in a positive number, which can be problematic since these tests are often performed to check the validity of a transaction.

Unchecked Return Values

An Ethereum-specific feature that can trip up novice smart contract developers is the fact that it does not have a consistent means of indicating when low-level functions fail.  Some low-level functions throw an error if they fail, which terminates execution. Other ones return a value of false and allow the code to continue running. If an programmer assumes the first case for a certain function and doesn’t check function return codes, it’s possible to put their code in an unexpected (and potentially invalid) state.

Denial of Service

Just like the underlying blockchain can be vulnerable to Denial of Service attacks, smart contracts can also be rendered non-operational by a malicious (or benign) user.  Denial of Service attacks on smart can be accomplished in a variety of different ways.

One way to attack a smart contract is to exploit an access control vulnerability.  Well-designed smart contracts include a self-destruct function that would render the contract unusable if an attacker gains access to and executes this function.

Bad Randomness

Smart contracts often need access to random numbers.  In fact, many smart contract are designed to implement gambling games, so they need the ability to generate secret random numbers.

There are several means of generating random numbers in code, and many of these are considered “best practice” in traditional applications.  However, the blockchain environment is different, making the following means of generating randomness insecure:

  • “Secret” Values: Like seeding a pseudo-random number generator, some smart contracts use “secret” values to create randomness.  However, everything is public on the blockchain, so an attacker can observe this value and predict the “random” values

  • “Secret Code”: Using a proprietary algorithm for generating random numbers is not a great idea but it often works.  However, it fails on blockchain for the same reason as the “secret” values.

  • External Input: Using external sources of entropy is a common method of generating randomness in traditional applications.  However, any source of entropy visible to one smart contract is visible to any other, making it easy to observe and exploit.

In the end, the best way to generate random numbers on the blockchain is to use an external source of randomness that the smart contract can query.  However, this has to be done carefully to ensure that malicious smart contracts can’t see it as well.

Race Conditions

In traditional programming, race conditions are when two or more threads are competing for resources, and the behavior of the program is dependent on which one gets there first.  In the blockchain, multiple transactions may be competing for recognition by a smart contract and the result depends on whichever transaction is processed first.

For example, a contest may exist where the first person to solve a puzzle wins some prize.  A benign user solves the puzzle and submits their solution to the smart contract as a transaction.  However, transactions are not instantly processed, are publicly visible before processing, and are organized for processing based upon transaction fees.  If an attacker sees the user’s solution, copies it, and submits a transaction with a higher transaction fee, the attacker is likely to win the contest without doing any work to solve the puzzle.

Timestamp Dependence

Another way that these contests can go wrong is if they depend on the current time on the blockchain as a condition for the contest.  For example, a smart contract may run a contest where the first submission after midnight on a certain day is the winner.

On the blockchain, the current time is the time of the most recent block, and this is set by the block creator.  Further, there is some wiggle room (often up to two hours) in timestamps to deal with propagation delay, non-synchronized clocks, etc. (in fact block timestamps don’t even have to be in order).  An attacker who manages to create a valid block with a timestamp of midnight before midnight but within the acceptable window can win this contest before anyone else tries to play.

Short Addresses

Short address vulnerabilities in Ethereum are caused by variable sizes, how arguments to a function are stored in memory, and how Ethereum pads arguments that are too short.

In this attack, the attacker calls a vulnerable smart contract function designed to send value to a certain address (like the refund function from the reentrancy vulnerability).  In this call, the attacker deliberately sends a destination address that is one byte too short and a value of the correct size. The function checks the value and, if the transaction is valid, calls a function to transfer the value.

This transfer function specifies the size of its arguments and expects a destination address of a given size.  As a result, it fills the address variable with the provided address and the first byte of the provided value. Now, the value is too small, so Ethereum zero-pads it on the right, effectively multiplying it by 256.  As a result, if the new destination address is controlled by the attacker (which they can assure before they perform the attack), they receive 256 times more value than the vulnerable function authorized.

Unknown Unknowns

The final smart contract vulnerability included in the DASP list was unknown unknowns.  Blockchains in general, and smart contract platforms in particular, are a relatively new technologies.  It is extremely likely that new vulnerabilities will be discovered and take the top slots for smart contract vulnerabilities in future years.

The Final Chapter: Blockchain Extensions

The articles to date have covered the topics used by most blockchain and smart contract platforms.  However, some extensions and second-level protocols have been developed to fix the deficiencies of the blockchain.  The final article in this series will discuss some of the security considerations for these technologies.