The final competitions web challenges contains XSS exploitations inside a file content, XSS in past Laravel CVE, and RCE from pandas unsafe input handling
🧾 Challenges
Hackyesterday
🤔Difficulity: Easy
🕸️Vulnerability: Cross Site Scripting (XSS), Mass Assignment
Description
We were given a CTFd like web, where we able to create register, login, solve problems, and create challenges.
Approach
First thing i do is to find out where the flag is placed at, and it seems like they put it in an admin privilege user password.
So it seems our target is to leak the user password. Traversing on how can we get the user password, there’s a bot report functionality that we can use to make an admin bot (assume the user with flag password) to visit the challenge page.
deflogin_and_view_challenges(): """Simulates an admin user that logs in and views the challenges page""" logging.info("Starting bot...") driver = setup_driver() driver.get(BASE_URL + "/login")
login_button = driver.find_element(By.ID, "submit") login_button.click() logging.info("Logged in as '%s' with password '%s'.", username, password)
time.sleep(3) driver.quit() .....Snippet.....
Then how do we attempt to create an XSS payload in the main challenge page? Because we need to be an admin to submit a challenge, the composition are as below:
ifnot current_user.is_admin: raise HTTPException(status_code=403, detail="You are not authorized to create challenges.")
if challenge.score < 0: raise HTTPException(status_code=400, detail="Score must be positive.")
iflen(challenge.title) < 3orlen(challenge.description) < 3orlen(challenge.flag) < 3: raise HTTPException(status_code=400, detail="Title, description and flag must be at least 3 characters long.")
Yey… Now how do we get the real admin with flag in the password creds with XSS? First, we need to found out what protection exists. The CSP Configuration is as follows:
Using CSP evaluator, we have a little warning in this script-src 'self' part
‘self’ can be problematic if you host JSONP, AngularJS or user uploaded files.
In short, this settings might be an issue if we can submit file that contains XSS payload. But how? In Challenge component, we can see that a script loaded dynamically, below is the script
The script will dynamically loaded based on javascript source inside the description part, which means, if we able to submit a file with XSS script inside, then we can refer that file as script source. But… how?
The only way we can create stored files, is in the create challenge endpoint, we can add attachment as part of the challenge set. Yet, we can only submit file with below extensions and mime type:
Of course XSS in the pdf using jspdf or something won’t help, since the context will be in the pdf context, not document, so we can’t extract the target cookies or localStorage. But here’s the trick, below is how the file Mime checking is done:
magic.from_buffer is not a common way to check the file mime, it just check if a spesific magic byte is exists in a buffer, not validate if the format is in a right way, in short, it works like
1 2
ifb"PDF"in buffer: return"application/pdf"
We can make pdf file like gedagedi.pdf with content as below:
and it will counted as a valid pdf, and a valid js content because we commented verything behind the valid js payload.
Create challenge with XSS payload in the PDF as attachment
Create challenge again with the PDF as script source inside the description.
Access the page, the XSS will be triggered
POC
Create payload (must be base64 encoded)
Submit as pdf
Take the document as our payload source
Make another challenge with the script html tag with pdf file as the script source to trigger script dynamic load.
Visit the main page again will trigger the XSS
Now with the same flow, we do it again but now we use the report endpoint to trigger the bot visitting the main page Now we can set the token to our local storage, and we become the target user We get the flag in the password field
CSV
🤔Difficulity: Easy
🕸️Vulnerability: RCE in Pandas query
Description
We’re given a web where we able to submit a CSV and it will do analysis in the files using df.query.
Approach
Looking through the website, yes a pandas query can become and RCE if not handled properly. From this WriteUp, we can do easily getting RCE. The vulnerable part lies here:
🕸️Vulnerability: XSS in Laravel error page when debug mode is active (CVE-2024-13919)
Description
We’re given a web where we can reflect sanitized html input we gave to the server.
Approach
First, the flag is inside the admin cookies, so it must be an XSS, but the sanitizer is pretty lit and i thought it was a zero day challenge, yet i thing it’s too hard for such a short time CTF. Then i realize something, if we visit the /reflect page with get method, it will shows error page which tell us it’s on debug mode: we can also verify this on the .env file:
then… i found out the version has a CVE record, which was CVE-2024-13919. we can supplied anything in the query param with xss payload, and it will be triggered.
Now we can use this payload to get the admin cookies