PicoCTF 2024 - Web Exploitation Writeups
This post contains a collection of writeups under the Web Exploitation category for PicoCTF 2024.
Bookmarklet - 50 points
We are given the following javascript code as a bookmark.
Basically for each character in the encryptedFlag
string
- Converted to its integer UTF-16 char code (
à
is224
) - Minus the
key
char code for the current character modulo bykey
length (which ensures we will not be out of index bounds ofkey
). For example char code of key at indexi = 0
is which isp
is112
- Add
256
and modulo it by256
which in this example(112 + 256) % 256
gives us back112
- Convert it back to String using
String.fromCharCode
which gives usp
Alternatively, simply run the code in the function in a javascript console and get the flag.
Flag: picoCTF{p@g3_turn3r_1d1ba7e0}
WebDecode - 50 points
This is a very easy challenge similar to the Bookmarklet
challenge, all we need is to inspect the source. When we navigate to the About
page we see the following hint to inspect the page. If you are not familiar with encoding you might scratch your head wondering where is the flag. It is right there.
cGljb0NURnt3ZWJfc3VjYzNzc2Z1bGx5X2QzYzBkZWRfZGYwZGE3Mjd9
is Base64 encoded. Once decoded, we get the flag. (If you have no idea what something is, try playing with it over at CyberChef which occasionally can magically tell u it is Bas64 encoded as in this example)
Flag: picoCTF{web_succ3ssfully_d3c0ded_df0da727}
IntroToBurp - 100 Points
This is honestly quite a badly named challenge. It is more like intro to sending HTTP Headers. Simply fill the form until u reach the OTP section. Send anything and it will say wrong OTP. Copy that request or intercept with burp or modify with Firefox and modify the Accept
and Content-Type
headers to application/json
and you will get back the flag in the response claiming you "Bypassed the OTP"
let result = await fetch("http://titan.picoctf.net:53880/dashboard", {
"headers": {
"accept": "application/json",
"content-type": "application/json",
},
"body": "otp=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"method": "POST",
"mode": "cors",
"credentials": "include"
});
await result.text()
Flag: picoCTF{#0TP_Bypvss_SuCc3$S_2e80f1fd}
Unminify - 100 Points
Another challenge that was probably not well thought out, inspecting the source in Chrome simply shows the flag as one of the element classes
Flag: picoCTF{pr3tty_c0d3_622b2c88}
No SQL Injection - 200 Points
Looking at the source code, we see that the NoSQL injection lies in the unsanitised input to the find
function in api/login/routes.ts
const users = await User.find({
email: email.startsWith("{") && email.endsWith("}") ? JSON.parse(email) : email,
password: password.startsWith("{") && password.endsWith("}") ? JSON.parse(password) : password
});
For Mongo, finding documents in such ways is vulnerable to SQLi and authentication bypass where we can make use of simple query filters such as not equals $ne
User.find(
{
email: { "$ne": "a"},
password: { "$ne": "a"}
});
The above will return users whose email and password both do not equal a
.
Using { "$ne": "a"}
for both email and password and input fields will return the list of users in the response. The flag is Base64 encoded in the user token field.
Flag: picoCTF{jBhD2y7XoNzPv_1YxS9Ew5qL0uI6pasql_injection_53d90e28}
Trickster - 300 Points
There is no source code available so we can only play with it, uploading a random gif that ends with .png
passes the rudimentary check but we are greated with the following error
Okay now we know its a PHP app and it seems to try and get the file contents after file uploading.
Creating a sample PHP hello world script along with a simple webshell containing the following and adding the .png.php
to the file name and upload it. (Remember to modify the request header for the Content-Type
to image/png
)
Now we get the message
There could be a magic byte check to see if it is a PNG file. PNG files can be identified by starting with 89 50 4E 47 0D 0A 1A 0A
in hex.
After reuploading the file, we see
File uploaded successfully and is a valid PNG file. We shall process it and get back to you... Hopefully
Taking a guess at where our file will be uploaded to, if we visit the /uploads
folder with our file name we see our PHP code getting executed and we see Hello World
If we add in ?cmd=ls ../
in the url, it will get executed by the server and we see the list of files in the main html
folder
Change our cmd to cat ../G*.txt
and we have the flag
Flag: picoCTF{c3rt!fi3d_Xp3rt_tr1ckst3r_48785c0e}
Elements - 500 Points
I managed to bypass the checks to /remotecraft
but could but not get any of the functions to return back the flag for the eval
xss 😦
Here's a completed writeup by Saktoki for the elements challenge https://github.com/satoki/ctf_writeups/tree/master/picoCTF_2024/elements