CTF Nights: a first attempt
Hack a cool one with the team!
I love taking on the challenge of a good CTF (Capture The Flag). And I tend to have a preference for co-op games. So what happens when you’re stuck in a corner of northern England that doesn’t offer much entertainment? You hack a cool one with the team.
First I’d like to clarify what I mean by a CTF Night (DuckDuckGo gives me some hits that are kinda on-spot but I’m not 100% sure it’s “a thing”): the idea would be a lightweight version of a CTF competition, in a chilled and collaborative environment, where the competitive element is replaced by a learning and sharing ideas. The learning element is of primary importance given the perspective of our teams: we are developers, not security experts so our goal is to understand more in order bake security in rather than becoming expert breakers.
A few attempts happened by now, mostly set up at the last minute and with only 2 partecipants but I’d really like to try to figure out what’s a viable format, a reasonable focus and drive more involvement. This is a brief experience report of it, and some thoughs on moving forward.
The first, mostly accidental attempt was a few (8?) months ago with Christoph, Dev on the team and good friend of mine. We took a stroll to Brewdog, in Glasgow’s west end and the conversation was about my plans to organize a CTF event with the OWASP Security Shepherd. So when we realized that we had laptops with us (went for a pint straight after work), we just fired them on and took a challenge, right in the middle of the pub on some standing tables. We decided to go for a beginner chellenge and picked OverTheWire’s Bandit.
I completed Bandit already, so we ended up going for a pairing/coaching format. To be honest it’s really hard to refrain from spoilers, but it also makes you realize that one can never stress enough the importance of manpages. We did a few levels but everything ended up when some drunk locals took an interest in our shell-fu and started a conversation. Key learning: It’s super cool when you can amaze people in the middle of a pub, but you need more than a pair to keep hacking on while someone showcases the coolness. Also, the loudness level can make a huge impact, that night was ok but it was an outlier.
Fast forward to early June: we’re with a team in Darlington and in need for ideas to entertain ourselves. I just came back from AppSecEU in Belfast and my first thought is “hey, what about a CTF?”. We struggle to organize it for a while due to availability of a suitable location until me and Sam, our QA expert, decide to give it a try no matter what, at the very least to get the ball rolling. We both played some levels of OverTheWire’s Natas years ago so we decide to go for that with a twist: we’ll automate the solution of all levels with a script. Me and Sam tend to do a lot of automate-everything-with-everything work in our team, so given that we already cleared some Natas before taking the chance to better our pick-up-anything-to-get-the-job-done-fu sounded smart. So one evening we met in the hotel lounge armed with our respective laptops and the wifi password and started hacking.
We cleared the first 10 levels in a 3 hour-ish sitting. It’s the boring part of the challenge (although very informative about accidental disclosure of secrets), and we mostly spent a lot of time scripting things up. I think it’s mostly worthwhile, except that it also involve a lot of repetition: copy some boilerplate from the previous challenge, replace a bunch of tokens, tweak the script. Knowing what happens in the 6 next levels I can say that it’s good prep but given the low complexity of the first 10 levels the boilerplate-stirring excercise was excessive. In hindsight, it would have been a better choice to set for a language and take the time to make a small library/framework after a few levels, to make the reusability effort cheaper. Our approach was fragmented: we paired on the problem-solving part but scripted separately and then compared results. It’s interesting to compare the approaches but that can also not yield much value when you end up comparing apples with giraffes: Sam went for a liberal mix of
ruby while I decided to stubbornly stick with
bash (and guess what happened when null-bytes appeared).
I think that the scripting factor makes sense, later levels and other challenges are less “you just need to figure it out” and require whipping up some tooling. Not having a definite approach for the scripting just adds to the confusion. Sticking for a single language helps in building some boilerplate mitigation and makes comparing approaches easier. On the pairig element, I think it worked on the problem solving, and I think that on the scripting either pairing or splitting would work equally well, as long as the results are easily comparable to make feedback easier. Being just the two of us we didn’t feel too much constrained by the hardware we had but just two laptops with no external mice nor keyboards nor bigger screen is as good as it goes.
It happened mostly by chance that just the week after that I set up one more session with Angelo, a friend from uni days who is now doing a PhD in security of industrial control sytems. We meet at my place, when I have enough hardware to provide a pairing workstation with 2 monitors, mice and keyboards… but not a second chair. We make do with a stool, crack open a cold one and a bag of Doritos and start hacking. We have the whole day and some decent understanding of low-level stuff so we decide to pick OverTheWire’s Behemoth, with some Bandit first as a warm-up to figure out how we want to do it and ease the transition to pairing mode.
All good until Bandit14: we decide that scripting it up is not that valuable for a warm-up and just whip up a small wrapper to save some typing when jumping on the next level. But for some reason we are very slow at it so around dinnertime we call it quits and start on Behemoth. Behemoth0 was fairly easy and yielded the flag after a few minutes of throwing unix debugging tools at it, so we got our morale high. But then we stuck our face on the wall of Behemoth1: we both know the theory of a buffer overflow and I solved some easy buffer overflow CTF challenges before (the type in which there’s a
printFlag() function already there waiting for you) but when it came to injecting shellcode properly we got stranded. We got ourself more familiar with
gdb, grabbed some shellcode from The Interwebz and just got a segfault after another. We were convinced that the process was alright (and actually looked like working in
gdb!) but something was missing. Still, we didn’t DuckDuckWent for “how to shellcode properly” and called it quits late in the night. I tried tinkering for a little longer, then decided that I couldn’t possibly get to sleep without some spoilers and figured out that yes, we were very very close, but also didn’t know about some details and would have probably never made it without searching, despite being just a few bytes off.
It was a good session. The idea of a warm-up is not bad but it probably needs to be timeboxed. Facing a problem that you’re not familiar with is an awkward one for pairing though: people tend to have different thinking processes and would search for different keyworks, pick different documents. This is the kind of moment that probably calls for a timeboxed split for some research, then merging the results afterwards. Or parking the challenge and beginning a different stream, leaving it for the next time.
I think this gives some insight. I think organizing it as an impromptu thing is ok, but would probably try to lay down some guidelines at the beginning to increase the focus. I’d like to see how it plays out with more people. There is nothing scheduled as of now but I’ll keep organizing and see how it goes.