Blockchain vulnerabilities

Smart contracts are programs that run on top of a blockchain network

The underlying blockchain infrastructure creates unique vulnerabilities:

  • Access control

  • Bad randomness

  • Denial of Service

  • Frontrunning

  • Timestamp dependence

Access control

function initContract() public {
    owner = msg.sender
}

Smart contracts commonly have functions that transfer "ownership" of the contract to a particular address, this gives the owner access to protected functionality

If these functions are poorly implemented, an unauthorized user can gain contract ownership

Bad randomness

function play() public payable {
    require(msg.value >= 1 ether);
    if (block.blockhash(blockNumber) % 2 == 0){
        msg.sender.transfer(this.balance)
    }
}

Smart contracts commonly require access to a strong source of randomness:

  • Gambling

  • Contests

  • etc

There are many "wrong" ways to generate random numbers in a smart contract:

  • Based on embedded "secret" values

  • Using embedded "secret" code

  • Based on mining activity

Denial of Service

Blockchain users are dependent upon blockchain nodes to add their transactions to blocks

A smart contract can be the target of a DoS attack if:

  • Transactions to the contract are ignored by a block creator

  • Blockchain nodes do not propagate a transaction through the network

  • The node creating a transaction or the block containing it is the target of a DoS attack

Frontrunnning

Frontrunning attacks take advantage of the block creation process. Transactions with higher fees are more likely to be added to a block first.

Smart contracts that rely upon a "first come, first served" model are vulnerable to attack

If an attacker sees a transaction and rapidly sends out a similar or conflicting transaction with a higher transaction fee, it is likely to be processed first

contract King is Ownable {
    address public king;
    uint public prize;
    
    function King() public payable {
        king = msg.sender;
        prize = msg.value;
    }
    
    function() external payable {
        require(msg.value >= value || msg.value == owner);
        king.transfer(msg.value);
        king = msg.sender;
        prize = msg.value;        
    }
}

King of the Ether code from Ethereum is applicable to other smart contracts

Lines 10-15 are an example of a fallback function

Order of operations is very important in this example

The order dependency of the program creates the vulnerability

Timestamp dependence

function play() public {
    require(now > 1521763200 && neverPlayed == true);
    neverPlayed = false;
    msg.sender.transfer(1500 ether);
}

Smart contracts may be designed to execute after a certain time:

  • Contests

  • Contracts

  • etc

These timestamps are typically based upon the timestamp of a given block

Block timestamps are flexible and under the control of the block creator

Last updated