Wacon2023
Mosaic
Recon
First thing you see are a login and register button
After you register and login you see 3 menus
Upload
: Can Upload .jpg, .zip, .tiff, .png files. After uploading it shows the path to the uploaded fileMosaic
: Able to see an uploaded file mosaicked
The files are as followed (excluding asdasd.png)
The weird this is that the password.txt
file was given. In most CTFs the password is within the source code.
Objective
The flag is placed as followed
- At the root directory the image file is saved and the path is saved in the
FLAG
variable
- The flag image will be copied by the
copyfile
function, to a possibly accessible directory only if the session is username is admin(== admin session) and it is called locally (127.0.0.1)
- Lastly, by using
/check_upload@<username>/<file>
, you are able to see an image but to see an image in admin, you must have a session with username “admin”
Step 1. Admin Password
Of course you need the admin password to login as admin. The password for admin is saved in password.txt
- FYI the password.txt is saved at
/app/password.txt
To read the password you can use the code below.
The image file you want to read depends on the username
name you input and you cannot use ../
in the file
path
But, you can read the password.txt
by placing ..
in the username
and it will form /app/uploads/../password.txt
Step 2. Copy Flag Image
The next step is accessing the root URL locally (127.0.0.1) with the admin session.
As you can see in the code, depending on the image_url
value it is used differently. If we were to use requests.get
to call 127.0.0.1 we are able to copy the flag image.
But image_url
filters values that start with https://
and http://
You can bypass this by using capital letters or using a python vuln like below.
The value goes straight through with the space in front of http
It might seem that the logic will work by putting 127.0.0.1 in the image_url
parameter but you will get 500 error
Like you can see the error above an error occurs in the split
function because there is no value for the mimetype.
The guess_type
function in mimetype
tries to guess the mimetype of a uri depending on the extension(after the ‘.
’)
To bypass this you can do it as below
Again you can see a 500 error
But this time it occurs in the imageio.imread
function and if you look at the log, the request locally worked
Thus you can get the flag image by accessing /check_upload/@admin/flag.png
Warmup-Revenge
Recon
When access the web page you get to see a page like below
After you register and login you will see as below
- in the board menu, you can see peoples titles, writers and date of writings and you can write one yourself
In the Myinfo page, you can look at infos of yourself and edit it.
Note is a function to send and receive DMs
The environment is as follows
Objective
The main goal is to achieve the admin’s cookie which is the “flag” which means there is a 95% chance that it will be an XSS challenge
bot.js
The only endpoint where the “User” and “Admin” interact is /report.php
The user can send the path
and idx
of an article to the admin
- FYI, everything you write in text will be filtered.
Step 1. XSS Entry Point
While looking around where I might be able to enter by XSS script, I found a download logic which looked strange.
The content-disposition
header is setted differently depending on the user-agent
, but since you cannot change the admin bot’s UA I didn’t think too big about this.
I thought if I were to delete the header or possibly change(inject) it, I might be able to make a URL that won’t popup a download screen.
Trying to figure out how, I did a bit of fuzzing and I was able to remove the content-disposition
header in my response. (The reason in the link below)
When I put in a “hex” value of \r
in filename
parameter, it will delete the content-disposition
response header due to an error
Step 2. Bypass CSP
As you can see in the image above, there is a CSP so I cannot not use script right off the bat.
1
Content-Security-Policy: default-src 'self'; style-src 'self' https://stackpath.bootstrapcdn.com 'unsafe-inline'; script-src 'self'; img-src data:
To bypass it, I thought “why not just upload a js
file and make script src
call it?”
Thus I was able to make the bot send me his cookie by crafting a payload like below.