Reentrancy

Introduction

Re-entrancy happens in single-thread computing environments, when the execution stack jumps or calls subroutines, before returning to the original execution.

This type of attack can occur when a contract sends ether to an unknown address. An attacker can carefully construct a contract at an external address that contains malicious code in the fallback function. Thus, when a contract sends ether to this address, it will invoke the malicious code. Typically the malicious code executes a function on the vulnerable contract,

• Fallback functions can be called by anyone & execute malicious code • Malicious external contracts can abuse withdrawals

Example

1. A smart contract tracks the balance of a number of external addresses and allows users to retrieve funds with its public withdraw() function. 2. A malicious smart contract uses the withdraw() function to retrieve its entire balance. 3. The victim contract executes the call.value(amount)() low level function to send the ether to the malicious contract before updating the balance of the malicious contract. 4. The malicious contract has a payable fallback() function that accepts the funds and then calls back into the victim contract's withdraw() function. 5. This second execution triggers a transfer of funds: remember, the balance of the malicious contract still hasn't been updated from the first withdrawal. As a result, the malicious contract successfully withdraws its entire balance a second time.

Code Example

The following function contains a function vulnerable to a reentrancy attack. When the low level call() function sends ether to the msg.sender address, it becomes vulnerable; if the address is a smart contract, the payment will trigger its fallback function with what's left of the transaction gas:

function withdraw(uint _amount) {
 require(balances[msg.sender] >= _amount);
 msg.sender.call.value(_amount)();
 balances[msg.sender] -= _amount;
}

transferFrom() Reentrancy Attack on ERC-777

incomplete compatibility between the lending protocol and the ERC-777 token standard

The condition required to enable this attack is simple to describe: • The token makes an external call in the transferFrom function to an attacker-controlled address.

What types of tokens enable this attack?

External calls inside transfer/transferFrom function can be called either before or after the token balances were changed. This is important, depending on the mentioned condition, there can be two different ways to steal funds from the exchange. Let’s look at some scenarios where reentrancy can be done: If the external call is made in transfer function to the recipient (or any other account controlled by the attacker) before the balances were updated. If the external call is made in transferFrom function to the token spender (or any other account controlled by the attacker) before or after the balances were updated. It’s important to notice that all transferFrom functions are always called with the exchange as the recipient, so callback to the recipient which is common in different ERC20 extensions is not dangerous. The first example is quite rare, but the second one can be observed in multiple places: Every ERC-777 token should have a callback to the spender before the balances are changed and to the recipient after. That allows everyone to make malicious reentrancy to an exchange contract with ERC-777 token. Regulated/controlled tokens typically have an external call to the controller to perform additional validation checks before (or rarely after) every transaction. This is done for KYC or other regulatory requirements. A malicious controller contract could be used in such an attack. Although the owner of a security token contract is usually a public entity who is not interested in stealing tokens, this also provides an additional incentive for a hacker to gain access to the owner’s private keys. Additionally, in some regulated tokens, controllers already have the power to transfer any amount of tokens from any address.

Remediation

We recommend adding a mutex to all trading functions in order to prevent reentrancy. That would slightly increase the gas cost of transactions but will make the system more secure toward tokens with more complex structure. ConsenSys Diligence ConsenSys Diligence has the mission of solving Ethereum…

Resources

The DAO

Reentrancy

address global functions

Securing Smart Contracts

Ethernaut

Last updated