(34C3) Junior CTF - Upload

March 3, 2018

The Challenge

  • Category: web
  • Difficulty: easy
  • Points: 60
This is an useful service
We added a flag for your convenience.

You can find an upload-form where you can uploard a zip-file.
After uploadung is, you are redirected to a unique folder (*/) where you can see a list of the uploaded files.

The source code:

$UPLOADS = '/var/www/uploads/';
if(!empty($_FILES['uploaded_file'])) {
   $paths = scandir($UPLOADS);
   $now = time();
   foreach($paths as $path) {
       if ($path == '.') {
       $mtime = filemtime($UPLOADS . $path);
       if ($now - $mtime > 120) {
           shell_exec('rm -rf ' . $UPLOADS . $path);
   $path = $UPLOADS . uniqid('upl') . '/';
   if(!mkdir($path, 0777, true)) {
       die('mkdir failed');
   $zip = $path . uniqid('zip');
   if(move_uploaded_file($_FILES['uploaded_file']['tmp_name'], $zip)) {
       shell_exec('unzip -j -n ' . $zip . ' -d ' . $path);
       header('Location: uploads/'. basename($path) . '/');
   } else {
       echo 'There was an error uploading the file, please try again!';
} else {
<!DOCTYPE html>
   <title>Upload your files</title>
   if (@$_GET['source']) {
   } else {
   <form enctype="multipart/form-data" method="POST">
       <p>Upload your file</p>
       <input type="file" name="uploaded_file"></input><br />
       <input type="submit"></input>
   <a href="?source=1">Show source</a>

The solution

Looking at the source-code, we can see that the shell_exec function is executing the unzip tool, unpacking the archive that we uploaded. So, we can get the flag if we can somehow switch into the root-folder, where the /flag.php is located.

So, we’ll have to get from the upload-folder 2 directories higher (../../).

Reading the documentation for (un)zip we can find this at respect of symlinks:

For UNIX and VMS (V8.3 and later), store symbolic links as such in the zip archive, 
instead of compressing and storing the file referred to by the link. 
This can avoid multiple copies of files being included in the archive as zip recurses 
the directory trees and accesses files directly and by links.

This means, that we can zip a symlink with the option –symlink:

$ ln -s ../../flag.php flag.txt
$ zip --symlink flag.zip flag.txt

Uploading the zip-file brings us to the list with uploaded files where we can see our flag.php in the list. Downloading it shows us the content:

$flag = "34C3_unpack_th3_M1ss1ng_l!nk"