👮
Contract Cops
  • Mastering Ethereum Book
    • What is ethereum?
    • Tokens
    • Oracles
    • Decenralized Applications(DApps)
    • The Ethereum virtual machine
    • Ethereum basics
    • Ethereum clients
    • Cryptography
    • Wallets
    • Transactions
    • Chapter 7 - Smart Contracts & Solidity
    • Side Notes
      • Tokens
      • Smart Contracts and Solidity
  • Cryptography
    • Ethereum Cryptography - Cheatsheet
    • Assymetric vs symmetric cryptography
    • ECDSA vs RSA
    • Elliptic curves and ECDSA
    • Sha-256 Example
    • Sha-256
    • What are the different steps in SHA-256?
  • Ethereum Blocks
    • Block Headers
  • Learning Solidity
    • Storage vs memory
    • Upgradeable contracts
      • Proxy pattern in smart contracts
  • PoS
    • Proof of stake
  • PoW
    • PoW
  • Tokens
    • ERC-1155
    • ERC20
  • Cryptonomics
    • Automated market makers
    • Collateral Tokens
    • Collateralized Stablecoin
    • Fiat currency
    • Liquidity pool
    • Open Position: Meaning and Risk in Trading
    • Slippage
    • Spot price
  • Common Attack Vectors
    • Checking access control
    • Access control issues on critical functions
    • Account Existence Check for low level calls
    • Account Existence Check
    • Common attacks with contract/EOA addresses
    • Arithmetic under/overflow
    • Assert Attack
    • Assert require revert
    • Assert Violation
    • Bad Interface DOS
    • Bad pragma and compiler
    • Block Timestamp Manipulation
    • Bypassing contract check
    • Code With No Effects
    • Code size check vulnerability
    • Constructors with Care
    • Default Visibilities
    • Delegatecall
    • Delegatecall
    • Denial of Service (DoS)
    • DoS with block gas limit
    • Entropy Illusion
    • External contract referencing
    • Flash Loan Attack
    • Floating Point and Precision
    • Function selector abuse
    • Function selector abuse
    • Smart contract gas griefing
    • Hash collision parameters
    • Hash Collisions With Multiple Variable Length Arguments
    • Imprecise arithmetic
    • Improper Array Deletion
    • Incorrect array deletion
    • Incorrect interface
    • Insufficient Gas Griefing
    • Loop through long arrays
    • Message call with hardcoded gas amount
    • Not enough gas for ether transfer
    • Precision Loss in Calculations
    • Oracle Manipulation
    • Public Burn Function
    • Read-only reentrancy
    • Race Conditions/Front Running
    • Reentrancy Attacks
    • Reentrancy
    • Requirement Violation
    • Right-To-Left-Override control character (U+202E)
    • Shadowing State Variables
    • Short Address / Parameter attack
    • Signature Malleability
    • Signature Replay
    • Transaction Order Dependence
    • Tx.Origin Authentication
    • Unchecked CALL Return Values
    • Unexpected ether
    • Uninitialized Storage Pointers
    • Unsafe Ownership Transfer
  • EIP's
    • EIP155
    • EIP55
  • PoW
    • Ethash
    • Scrypt - RFC 7914
  • Questions for self evaluation
    • Questions 23/04/2023 (Nr: 84)
    • Usability guide for questions
  • Frequently asked questions
    • What is the difference between transaction and message?
    • What is the use of a interface or function without implementation?
  • UsefulResources
Powered by GitBook
On this page
  1. Common Attack Vectors

Reentrancy

PreviousReentrancy AttacksNextRequirement Violation

Last updated 2 years ago

Reentrancy is when an attacker is able to achieve race condition and repeat an action (that he's not supposed to) multiple times consequently.

In the context of Ethereum, a reentrancy attack is where an attacker is able to re-enter (repeat) a state modifying function so that an inconsistent state is used to perform malicious state.

The easiest way to spot a contract that's vulnerable to re-entrancy is by looking for important logic that occurs after the following functions are used:

  • call()

  • send()

Reentrancy mainly occurs when a contract sends ether to an unknown contract.

The reason behind why this vulnerability is possible when using the above functions is because of how Solidity and the EVM handle payments from one contract to another.

In Solidity, for a contract to receive ether through the functions above, it must have:

  1. A payable function

  2. A payable fallback function

Lets imagine the following snippet:

We can see that in the Withdraw(uint256) function, the amount to withdraw is first sent to the caller of the contract. Finally, the balance for that msg.sender is decremented.

This is problematic, as an attacker can create a contract with malicious code within a fallback function that re-enters the Withdraw function.

The way this works is because of the state balance of the caller being decremented only after the amount is sent.

The attacker "re-enters" the withdraw function and steals the ether from the contract. His balance never gets decremented.

The following snippet demonstrates how an attack might look like:

We graph the reference of the Bank contract and initialize it in the constructor.

We then have the StartAttack() function which does the following things:

  • Deposit 1 ether

  • Withdraw 1 ether right after

What happens when those two are exectued consequently is that in the Bank contract, the balance of the attacker becomes 1 ether. Right after that, he requests a withdrawal and passes the requirement for him to have that amount.

Ether is then sent to the attack contract throught the payable fallback function, where it checks whether the balance of the contract is bigger than 1 ether. If that condition passes, the attacker is able to withdraw as much ether as there is in the contract by calling Withdraw() once again.

This is possible because of race condition. The Bank contract is never able to decrement the attacker's balance and he drains all of the ether stored.

Preventative techniquesAlways use transfer() in place of call() and send() when possible. It only sends 2300 gas which is enough to send the Ether, but not enough to run more functions subsequentially.The actual sending of ether/transfer logic should always be done after the state variables have been changedAnother way to prevent reentrancy is by using a mutex that locks the function until the transaction is done, preventing an attacker from re-enteringOther resources to look into for re-entrancy fallback functions is:Cross-function reentrancyCross-contract reentrancy

1680339519831
1680340302437