Skip to content

Latest commit

 

History

History
77 lines (61 loc) · 3.92 KB

DenialOfService.md

File metadata and controls

77 lines (61 loc) · 3.92 KB

Denial-of-service attack

In Cybersecurity a Denial of Service Attack (DoS) consist of disabling, shutting down or disrupting a network, website or service.

In the EVM a denial of service attack can be usually performed when a smart contract has a function that tries to send money to certain addresses and checks whether the transaction is done correctly. With untrusted external contract calls its possible to stop those functions and therefore block the functioning of that contract. Analyzing a contract like this:

pragma solidity ^0.8.0;

contract Auction{
    address public currentLeader;
    uint public highestBid;

    constructor(){
        currentLeader = 0x0000000000000000000000000000000000000000; 
        highestBid = 0;
        // Addresses to initializate the variables
    }

    function bid() public payable{
        require(msg.value > highestBid);
        require(payable(currentLeader).send(highestBid));
        currentLeader = msg.sender;
        highestBid = msg.value;
    }

}

You can see that there is the vulnerability in the contract: if an attacker with a malicious fallback function (that reverts any incoming payment) win an auction with the bin function, therefore it will remain the currentLeader even if transactions with higher highestBid are submitted, this because the line require(payable(currentLeader).send(highestBid)); will always produce a fail in execution. This error is due to the fallback of the malicious address that creates reverts the transaction when someone tries to refund the contract.

Simple implementation of a smart contract that can perform a denial of service with a fallback function non-payable:

contract evilAddress{
    Auction public auct;
    constructor(address _addr) payable{
        auct = Auction(_addr);
        auct.bid{value: msg.value}();
    }

    fallback() external{
        // Void non payable fallback function
    }
}

The same thing could even happen with an array of address, when a contract needs to iterate through an array to pay multiple address and checks in the same way that each address get the funds correctly.

Another problem that may cause a denial of service in a contract that refunds an array of addresses is the gas limit: each block on the EVM has an upper bound on the amount of gas that can use per block, so an attacker could try to make it exceed that limit to cause a fail in each transaction it tries to create.

If a contract needs to send funds to multiple address it should consider splitting it in different transaction, but it will need to keep track of how far it has gone and be able to resume from that point. To implement this:

struct Payee {
    address addr;
    uint256 value;
}

Payee[] payees;
uint256 nextPayeeIndex;

function payOut() {
    uint256 i = nextPayeeIndex;
    while (i < payees.length && msg.gas > 200000) {
      payees[i].addr.send(payees[i].value);
      i++;
    }
    nextPayeeIndex = i;
}

A denial of service caused by gas limit can also happen via Block Stuffing: because every block has a maximum gas limit that can consume, an attacker can create several transactions with a gas price high enough to be sure to be included in the next block, if this succeeds, he can be sure no other transactions are in the block. Block Stuffing attack can become very dangerous for smart contracts performing a function in a certain time period: an attacker could intercept the incoming transactions of a contract and create other transactions with a higher gas price to make them be executed before the one intercepted. One of the problem of the attack is the cost: as with any attack, it is executed only when the expected reward exceeds its cost. The cost of the attack depends on how many blocks should be postponed.

https://consensys.github.io/smart-contract-best-practices/development-recommendations/general/external-calls/ https://fravoll.github.io/solidity-patterns/secure_ether_transfer.html