I took part in my university’s Capture The Flag (CTF) tournament today!
If you don’t know what a CTF is…
It’s a competition where you solve challenges (often computer / forensics / hacking related things) to get the highest score.
I originally signed up in a group of four, but two of them sorta went MIA during the day.
So it was just me and my friend.
You can view her writeups and solutions for this CTF here
LES GOO
So we ended up taking 🥳 first place 🥳!
Considering the other leading teams each had 4 people, and that we we started 1.5 hours later after the competition started (Sleep is important guys)…
I think this was a job very well done between my friend and I! 🎉
We’re in that bottom right corner!
I thought to jot down some notes for some of the more interesting challenges.
Web
My First Portal
The website contained a login form that was vulnerable to SQL Injections.
Performing some recon, we can assume the query being executed is something like
SELECT user WHERE username = 'PAYLOAD1' AND password = 'PAYLOAD2'
With a basic ' OR 1=1 --
payload, we were able to bypass the login; finding ourselves authenticated as the user bob
. The profile page revealed the password of the account.
What other users existed in the database?
Taking a guess that the table column names were username
and password
, we could craft a payload to ignore previously discovered users.
For example, something like ' OR username<>'bob' --
, or perhaps ' OR password<>'password123' --
. This gave us access to another user, andy
.
Extending our query, we reveal the five users in the database (including a flag!)
Username | Password |
---|---|
bob | password123 |
andy | i-have-a-better-password-than-bob |
megumin | i_love_kazuma |
flag | FLAG{2_pl81n_t3xt_0ffeNd3rS_T6RjMLt0y20} |
anna | some_generic_p3ssword_not |
As we keep looking, we can see that our HTTP responses contains some sort of JWT/Base64/Flask session cookie.
Decoding such a token like eyJsZXZlbCI6InVzZXIiLCJwYXNzd29yZCI6ImlfbG92ZV9rYXp1bWEiLCJ1c2VybmFtZSI6Im1lZ3VtaW4ifQ
reveals a key called level
, currently assigned to user
{
"level": "user",
"password": "i_love_kazuma",
"username": "megumin"
}
Logging on as all the users, all the values for level
are user
, and as signature verification is enabled, we won’t be able to tamper with the cookie. This does however give us valuable knowledge that the level
key value pair must come from somewhere (the database!).
Since we’ve been performing Blind SQLi, we need to figure out how many values the login query wants.
' UNION SELECT "a" --
' UNION SELECT "a", "b" --
' UNION SELECT "a", "b", "c" --
' UNION SELECT "a", "b", "c", "d" --
Sending each payload, we find that the database wants three values.
We can assume this is the username
, password
and level
(in that order).
We can therefore forge a user result with the payload ' UNION SELECT "username", "password", "admin" --
, giving us access to the admin page, and the flag!
Misc
Shellshook
This challenge involved exfiltrating a shell whilst racing against the clock (time limited). To make things harder, there is a cap on the number of bytes transmitted.
Immediately after entering the shell, we can find a flag in the environment variables, by running the env
command.
The next flag takes some effort.
The flag lives in a dynamically generated nest of subfolders, where red herring flags also exist.
Viewing too many of these red herring flags would cause the connection to disconnect (due to the transfer limit).
So we’ll need to use commands that only output if we have the actual flag.
I opted to use a combination of find
and grep
commands
find /flag2 -type f -exec sh -c "grep 'FLAG{' '{}' | grep -v 'you_got_the' " \;
- For each file in the
/flag2
directory (recursive search)- Print out lines that contain
FLAG{
, but do not containyou_got_the
- Print out lines that contain
This would prevent the red herring flags from appearing, and show us only the real flag!
Recon
dorf
This was a fun one!
The challenge revolves around the story of an employee who had been fired from the company.
He’s not very happy about it, and leaked some sensitive data from the company.
This included an SSH private key, as well as the address of the server.
Time for recon!
- Searching for “Charlie Warner” (the CEO) on GitHub revealed his GitHub acount.
- The CEO had had starred a repository of the ex-employee.
- The ex-employee has a repository called
dorf-site
- Looking at the commit history
Using that SSH private key and the address in the configuration file, we obtain access to the SSH server, and get the flag
Binary Exploitation
My partner REALLY REALLY wanted to do these and wouldn’t let me touch them… That’s okay I guess.
Check out her writeup here!
Crypto
base63
base63
encoding is base-ically (haha…) base64
without the _
character.
That said - because it’s a different encoding scheme we need to modify the base64 algorithm.
Luckily there’s a Java implementation of base63 which we can repurpose!
There are a several changes that needed to be made though in order to get the code working, which can be found here.
Note: I wasn’t actually able to solve this challenge in time - I talked to someone who had completed it, and they kindly sent me their solution :)
That said, I should make a base-n tool for future purposes…
really simple arithmetic
solution code: really-simple-arithmetic.py
I haven’t done RSA for a while haha.. I had a look at my course notes from COMP6441 to refresh myself.
The challenge was basically implementing an RSA cracker, given the value n
and an encoded message c
.
Using an online integer factorising tool we can find the values p
and q
which n
is the product of.
We can then determine Euler’s totient as (p-1) * (q-1)
Assuming the value of the encryption key to be e = 65537
(source), we can calculate the decryption key
d = pow(e, -1, totient)
Finally, with the decryption key, we can decrypt the code c
to get the message m
m = pow(c,d,n)
I originally tried attempting these calculations without pow
But c**d % n
never returned a value (it never finished calculating…)
This pow
function is actually amazing
Reverse Engineering
top secret
Source Code: top-secret.java
This challenge contained a compiled Java program which reads in a key that would be used to decrypt a string inside the program.
I fired up JD-GUI to decompile the byte code to see the program source.
Here we could see that there is an AES/ECB/PKCS5Padding
encryption scheme.
On the internet, there is a ticket regarding a possible vulnerability with this scheme, but it turns out that the challenge is very straightfoward.
All we had to do was use the supposed decryption key notTHEkeyOm766sI7Qv
as the key value.