Ethernaut: Gatekeeper Two

Ethernaut: Gatekeeper Two

My take on CTFs

CTFs constitute a crucial part in the process of becoming a successful security researcher as they require from you an eye for details, a good understanding of solidity and great technical skills to perform the attack and capture the flag. The most talented security researchers are great at CTFs, at solving them of course and sometimes at designing them. CTFs will not turn you into a great web3 security researcher over night, but it will surely arm you with good enough technical skills to be able to write decent coded PoCs to have your finding validated and maybe get selected for report.

What is Ethernaut?

Ethernaut is a CTF(Capture The Flag) developed by the openzeppelin team that you most propbably already heard of. If you haven't, consider taking a look at this roadmap https://www.0xjarix.com/if-i-had-to-start-again/
This CTF gathers 31 challenges for the moment, this number keeps increasing so check their website every now and then: https://ethernaut.openzeppelin.com/
Maybe you'll design your challenge one day and send it to the openzeppelin team.

Also why you here?

Of all the kinds of articles I publish, CTF writeups are those I wish you read the least. I am a big advocate of giving everything the time it needs, if you cannot solve a challenge that you know for a contains an intentional bug in such a small codebase, do not expect to do really well in the contests. There are 2 reasons why someone can fail at solving a challenge, and when I say 'fail' I mean giving up and looking at the writeups, knowing damn well these CTFs are not time-bounded. So if you failed you either:

  • aren't ready for this challenge yet and that is most probably due to the fact that you skipped some steps in the roadmap
  • are lazy, you read the challenge, read the codebase, maybe not enough times, you had some assumptions maybe, you might have identified some entrypoints or some conditions to bypass or break, but you did not give it enough time, you did not allow yourself to succeed and that's a shame
💡
StErMi provided us with a github repo to solve ethernaut challenges in foundry, you can fork it, remove his solutions and try solving the challenges just like I'm doing
GitHub - 0xjarix/foundry-ethernaut: My solutions to the ethernaut CTF
My solutions to the ethernaut CTF. Contribute to 0xjarix/foundry-ethernaut development by creating an account on GitHub.

Gatekeeper Two

This gatekeeper introduces a few new challenges. Register as an entrant to pass this level.

Things that might help:

  • Remember what you've learned from getting past the first gatekeeper - the first gate is the same.
  • The assembly keyword in the second gate allows a contract to access functionality that is not native to vanilla Solidity. See Solidity Assembly for more information. The extcodesize call in this gate will get the size of a contract's code at a given address - you can learn more about how and when this is set in section 7 of the yellow paper.
  • The ^ character in the third gate is a bitwise operation (XOR), and is used here to apply another common bitwise operation (see Solidity cheatsheet). The Coin Flip level is also a good place to start when approaching this challenge.

Goal

entrant = player

Reasoning

  1. The 1st modifier can be bypassed by applying what we learnt in the Telephone challenge i.e. creating a contract that we'll call so that it calls the GatekeeperOne contract, that way our address will be tx.origin and the contract we create will be msg.sender just like Gatekeeper One
  2. The 2nd modifier requires that the extcodesize of our contract equals 0 (msg.sender is caller() in yul). Until the constructor() is executed successfully, extcodesize(addr) = 0 because it's not deployed yet, we should take advantage of that and call enter() with the correct _gateKey from the constructor()
  3. For the 3rd modifier, if you have a good CS background you must know that for any bit b(0 or 1) b ^ (!b) = 1
    When bits are different, XOR returns 1, when they're the same, it returns 0