Blockchain security

Ethereum vulnerabilities and smart contracts

Howard Poston
October 14, 2020 by
Howard Poston

Introduction to Ethereum-Specific Smart Contract Vulnerabilities

Ethereum is the first and most widely-used smart contract platform.  This means that it has had the most opportunity to undergo security analysis and have vulnerabilities discovered.  As a result, a number of smart contract vulnerabilities have been discovered that are specific to Ethereum’s implementation of smart contract functionality.

Learn Blockchain Security

Learn Blockchain Security

Build your blockchain security skills with five courses covering blockchain structure, blockchain attacks, smart contract security and more.

Denial of Service

Every node in the network consumes resources when maintaining a copy of the distributed ledger.  Every transaction requires storage space and computational cycles to process when a node is updating the state of its copy of the shared virtual machine.

Ethereum compensates nodes for this effort by having all transaction creators pay “gas” (fractions of an Ether) to submit and run a transaction.  This gas is paid to the node creating the block (which should vary from block to block).  The more computationally expensive the operation, the more gas required.

Ethereum also includes a cap on the amount of gas that a particular transaction or block can contain.  This helps to protect the network against spam, but it leaves it open to Denial of Service attacks.

The code sample above shows an example of a function that has a gas-based DoS vulnerability.  Notice that the number of loop iterations depends on a user-provided value and is always increasing.

This means that the contract can be placed in a state where it takes more gas to run the function than can fit in a transaction.  Since running out of gas terminates execution and causes the execution state to be rolled back to where it was before the transaction was processed, this makes the function completely unrunnable.

Reentrancy

Reentrancy is probably the most famous of the vulnerabilities that can exist in an Ethereum smart contract.  This vulnerability was behind the famous DAO hack that resulted in the split of the Ethereum and Ethereum Classic blockchains.

Reentrancy vulnerabilities are possible due to the existence of fallback functions in Ethereum smart contracts.  Smart contracts are able to receive transfers of value, and a fallback function contains code that is executed if a smart contract is sent Ether.  This creates a potential vulnerability since it allows another contract to execute code between two instructions of the contract sending the value.

The code sample above shows an example of a smart contract with a reentrancy vulnerability.  The logic follows a three-step flow:

  1. Validate that the withdrawal is valid
  2. Perform the withdrawal
  3. Update the contract’s internal balance sheet

While this flow makes sense, it also leaves the function vulnerable.  At line three, the function calls the fallback function of the function that called it.  This fallback function could contain another call to withdrawal, which would create the following flow:

  1. Malicious smart contract calls withdrawal
  2. Withdrawal validates request (line 2)
  3. Withdrawal sends value to malicious function (line 2)
  4. Malicious function’s fallback function calls withdrawal
  5. Withdrawal validates request (line 2)
  6. Withdrawal sends value to malicious function (line 2)
  7. Malicious function’s fallback function returns without doing anything
  8. Withdrawal updates internal ledger (line 3)
  9. Withdrawal returns to malicious fallback function (call from step 4)
  10. Malicious fallback function returns to withdrawal
  11. Withdrawal updates internal ledger (line 3)
  12. Withdrawal returns to malicious smart contract (call from line 1)

This flow is problematic because the internal ledger updates (steps 8 and 11) come after the value transfers (steps 3 and 6).  The second time that the malicious function calls withdrawal (step 4), withdrawal has no record of the transfer from step 3.  The test performed at step 5 tests against the original account balance (before step 3), not the value that should be in the account after the step 3 transfer.

This allows an attacker to withdraw more Ether from its account than it contains with the excess coming from other accounts on the smart contract.  Fixing this issue requires updating the internal state (line 4 of the code) before making the transfer (line 3 of the code), then testing afterward to ensure that the transfer was successful.

Short Addresses

Short address vulnerabilities arise from the fact that smart contracts can assume the length of its arguments without checking them.  For example, a function may assume that addresses are 20 bytes long but not check this fact, allowing an attacker to submit a 19-byte address.

If such a function calls a function that does enforce argument lengths, then the called function may take a byte from the next argument to meet the 20-byte target.  Later on, this argument will be right-padded to reach its desired length.

This creates a problem if, for example, the first function validates a transfer and the second performs it.  The value being transferred will be 256 times the value validated.

Unchecked Return Values

Like many other programming languages, Solidity has the concept of functions.  Solidity functions can take arguments and return values based upon the result of their execution.

One of the potential sources of confusion for Solidity programmers is the fact that similar functions handle errors differently.  For example, the low-level function send() in Solidity returns a value of False upon experiencing an error, while transfer(), a similar function, will cause execution to be halted and rolled up so that the transaction containing the error never happened.

This difference between two similar functions creates problems if developers do not know how to identify and properly handle errors when making function calls.  A call to send() that fails will allow execution to continue if the return value is not checked.  In contrast, most other low-level calls do not require a check because they terminate and roll up execution.

Learn Blockchain Security

Learn Blockchain Security

Build your blockchain security skills with five courses covering blockchain structure, blockchain attacks, smart contract security and more.

Securing Ethereum Smart Contracts

Like any computer program, Ethereum smart contracts can contain vulnerabilities.  Before deploying Solidity code for production use, it is important to perform code reviews and testing to ensure that the business logic and implementation do not contain any exploitable flaws.

Sources

  1. https://dasp.co/
  2. https://quantstamp.com/blog/what-is-a-re-entrancy-attack
  3. https://www.coindesk.com/ethereum-classic-explained-blockchain

 

Howard Poston
Howard Poston

Howard Poston is a copywriter, author, and course developer with experience in cybersecurity and blockchain security, cryptography, and malware analysis. He has an MS in Cyber Operations, a decade of experience in cybersecurity, and over five years of experience as a freelance consultant providing training and content creation for cyber and blockchain security. He is also the creator of over a dozen cybersecurity courses, has authored two books, and has spoken at numerous cybersecurity conferences. He can be reached by email at howard@howardposton.com or via his website at https://www.howardposton.com.