Blockchain-Specific Programming Vulnerabilities
Smart contracts are computer programs. However, they run in a very different environment than traditional computer programs.
Smart contracts run on top of the distributed ledger maintained by a blockchain network. This different ecosystem introduces unique vulnerabilities.
Access Control Vulnerabilities
Many smart contracts are designed to provide privileged functionality to specific users. For example, it is possible to implement a cryptocurrency wallet within a smart contract, allowing it to accept, store, and send value. For a smart contract wallet, the owner of the wallet may wish to allow anyone to make a deposit but would want to restrict the ability to make withdrawals.
Typically, this access control is implemented based upon blockchain account addresses. The smart contract will be designed to store the address of the owner in a variable. Any time that it receives a transaction that calls privileged functionality, it will verify that the transaction originated from and was digitally signed by the “owner’s” address.
In many cases, this functionality is implemented in a function called initContract or something similar. This function is designed to assign ownership of the function to the person that calls it. This makes it possible for a smart contract owner to deploy it on the blockchain, then claim ownership before using it.
However, in some cases, this function is not implemented properly. The code sample above shows an example of a vulnerable function. While this function assigns ownership correctly when called by the smart contract creator, it does not restrict the function to only being called once. Instead of assigning ownership to the first person to call the function, the owner of the smart contract is whomever called it last.
This vulnerability existed in the code of the Parity smart contract wallet and led to two different hacks against them. The first exploited the flaw in the individual contracts deployed by Parity wallet users, allowing the attacker to claim the wallets and extract the funds within. In the second, an attacker targeted a library contract shared between all Parity wallets and caused it to self-destruct. This rendered all Parity wallets unusable and caused the Ether that they contained to be lost forever.
Many smart contracts need access to random numbers. However, many of the common methods for implementing pseudorandom number generation do not work for blockchain:
- Seeded PRNGs: Many traditional applications use a pseudorandom number generator (PRNG) seeded with a random value to generate pseudorandom values. On the blockchain, everything is public, allowing anyone to see the seed and PRNG code.
- Extraction of System Entropy: Some traditional applications extract entropy from the system, using sources like mouse movement. On the blockchain, all data sources accessible to a smart contract are publicly visible and under a miner’s control, making it possible to cheat the system.
As a result, many smart contracts rely upon poor sources of randomness. Instead, these contracts should use an external oracle for random number generation.
Denial of Service (DoS) Attacks
Smart contracts on the blockchain are run by transactions that call their code. If transactions cannot be added to the distributed ledger, then the smart contract can’t run. This can be accomplished in a number of different ways:
- Block Creator DoS: Blockchain consensus algorithms are designed to select a single node to create the next block. If this block creator cannot do so or cannot publish the block (due to a DoS attack), then the block is not created.
- Malicious Block Creator: A block creator has full control over the transactions included in their blocks. A block creator can choose to simply ignore certain transactions.
- Network-Level Attacks: Transactions and blocks can only be added to the ledger if all nodes in the network have access to them. A network-level attack can prevent transactions from being added to blocks or blocks being transmitted to the rest of the network.
For some smart contracts, the order in which transactions are submitted to them impact their result. One example of this is a smart contract that implements a cryptocurrency exchange. Due to the laws of supply and demand, the purchase or sale price of a particular token depends on the contract’s current supply of it. As a result, an attacker with knowledge of an upcoming transaction can make a guaranteed profit by submitting their own transaction first.
With smart contract platforms, gaining knowledge of upcoming transactions is easy. Blockchain transactions are not immediately added to the ledger. Instead, they are publicly broadcast to the network and added as part of blocks.
This means that an attacker monitoring the network has a window between a transaction becoming public and being added to the ledger. By submitting their own transaction with a higher transaction fee, they have a high probability that an honest block creator will add their transaction to the next block first, enabling them to frontrun the original transaction.
Some smart contracts are designed to run after a certain time. For example, a contest may award a prize to the first submission after midnight or a vendor’s service level agreements (SLAs) may specify delivery of something by a certain time.
Smart contracts use block timestamps as their source of the current time; however, these timestamps are flexible. In many cases, any block timestamp within two hours of the real time will be accepted by the network. This enables a malicious block creator to cheat the system by submitting a block with a falsified timestamp and winning the contest before anyone else begins playing.
Designing Smart Contracts Securely
The unique nature of the blockchain means that programs written to run on top of it (i.e. smart contracts) can have vulnerabilities that don’t exist in traditional computers. Smart contracts must be carefully designed so that their unique deployment platform does not make them vulnerable to attack.