Blog

Just like in all the previous walkthroughs I wrote up for Ethernaut, I try to come up with my own solution to the posed security problems and you should try to do the same, it's the only way to learn. However, sometimes it's handy or even necessary to take a look at other solutions to know what to look for. For this level, I ended up reading this solution first but after that I returned to Remix in order to cook up my own solution. That way, you'll have several options to go by and come up with your own unique attack. Let's dive in. Level 16 again uses the somewhat dangerous …

Sometimes you may feel like opening up some ports on your Digital Ocean or Linode VPS in order to access a service like a web dashboard remotely. It's bad security practice to do so because you would open up these ports to anyone out there trying to reach them. A better and easy way to access your remote services is to use local port forwarding via SSH. A practical example where I needed this was while I was setting up an IPFS node . IPFS is a great way to host data in a distributed and decentralized way. The IPFS package comes bundled with a web-based dashboard that allows you to …

To learn more about IPFS — aka the InterPlanetary File System — I set up a virtual host on Linode (love these guys, I use them in all my Linux classes). Nothing fancy here, just create your now VPS on your favourite platform and login as root. From there, we'll install IPFS and get to work. I used snaps to quickly get up and running. Follow the instructions here to install the go-ipfs implementation of ipfs in just a couple of commands. What is IPFS? IPFS stands for InterPlanetary File System and it can be described as a decentralized system for storing, hosting and …

This level requires us to transfer funds out of the contract to another address and we know that our own address has the full INITIAL_SUPPLY.  When looking at the code I initially has two different thoughts of how to approach this. First of all, I took a look at the modifier named lockTokens .  function transfer(address _to, uint256 _value) override public lockTokens returns(bool) { super.transfer(_to, _value); } // Prevent the initial owner from transferring tokens until the timelock has passed modifier lockTokens() { if (msg.sender == player) { …

Level 12 is a bit similar to level 8 where we learned about how state variables are stored on a contract (and also how we can read them, even when they are private). In order to get a good understanding of how storage works in more detail, I decided to create a little drawing based on the documentation and the given contract code. To pass this level, we need to unlock the contract by sending the correct _key . We see that the key is checked like so: require(_key == bytes16(data[2])); The storage variables are kept pretty basic (no dynamic arrays and the likes) and are …

This challenge starts with little help from the introduction. What we know is that there is an interface class named Building with just one method. interface Building { function isLastFloor(uint) external returns (bool); } What I know about interfaces is that they are used to more or less force us to build out our contracts (or classes in OO-based languges) with implementations of the functions listed in the interace. In other words, interfaces force or help us to follow a certain standard we need to follow. This is handy when creating more standardized code like ERC-20 …

One of the first hacks I heard about while learning Solidity was a re-entrancy hack. This type of attack is the reason why Ethereum Classic came into existence, after a hard fork undid the 50 million dollar hack of TheDAO . Looking at this level's contract, we need to focus on the following function. function withdraw(uint _amount) public { if(balances[msg.sender] >= _amount) { (bool result,) = msg.sender.call{value:_amount}(""); if(result) { _amount; } balances[msg.sender] -= _amount; } } The dangerous line here is the …

Level 9 of the Ethernaut game contains a contract that receives Ether and makes the biggest donor the next King. The old king receives the money prize and the new king will wait until somebody tries to become the next king. Classic Ponzi game indeed. This is what King Of The Ether did, before getting hacked . In this level, we are asked to prevent someone from becoming the next king. After looking at the contract, the function we should focus on is receive(). receive() external payable { require(msg.value >= prize || msg.sender == owner); king.transfer(msg.value); …

Unlock the vault to pass the level! That's clear enough. When we look at the code of the given contract we can see that a password is set on creation of the contract via the constructor method. Unlocking the vault can only be done if you know the password. The password variable is defined as private but any blockchain developer knows that private only affects the scope of the variable and has nothing to do with making the contents of that variable private or hidden. Any data in your contract is public and can be read by anyone. // SPDX-License-Identifier: …

Level 7 presents us with an empty contract containing nothing more than some ASCII-art. The only hint we get is that some contracts won't accept our money. contract Force {/* MEOW ? /\_/\ / ____/ o o \ /~____ =ø= / (______)__m_m) */} This level probably let's you search around for ways a contract can receive money. You probably know about payable functions and fallback methods, but the contract doesn't seem to contain any of these. I tried logging the full contract ABI on Ethernaut, but it seems to be empty so that's where …