Bludit 3.9.2 allows remote code execution via bl-kernel/ajax/upload-images.php because PHP code can be entered with a .jpg file name, and then this PHP code can write other PHP code to a โฆ/ pathname.
Recent assessments:
wchen-r7 at October 24, 2019 4:38am UTC reported:
Bludit is a web application written in PHP to build your own website or blog, free and open source. It uses files in JSON format to store the content, so it is configuration-free.
A vulnerability was found in the upload-images.php file, where a remote user could upload a fake image file that is actually a malicious PHP payload, and gain remote code execution.
The vulnerable file (upload-images.php) is written as follows:
<?php defined('BLUDIT') or die('Bludit CMS.');
header('Content-Type: application/json');
/*
| Upload an image to a particular page
|
| @_POST['uuid'] string Page uuid
|
| @return array
*/
// $_POST
// ----------------------------------------------------------------------------
$uuid = empty($_POST['uuid']) ? false : $_POST['uuid'];
// ----------------------------------------------------------------------------
// Set upload directory
if ($uuid && IMAGE_RESTRICT) {
$imageDirectory = PATH_UPLOADS_PAGES.$uuid.DS;
$thumbnailDirectory = $imageDirectory.'thumbnails'.DS;
if (!Filesystem::directoryExists($thumbnailDirectory)) {
Filesystem::mkdir($thumbnailDirectory, true);
}
} else {
$imageDirectory = PATH_UPLOADS;
$thumbnailDirectory = PATH_UPLOADS_THUMBNAILS;
}
$images = array();
foreach ($_FILES['images']['name'] as $uuid=>$filename) {
// Check for errors
if ($_FILES['images']['error'][$uuid] != 0) {
$message = $L->g('Maximum load file size allowed:').' '.ini_get('upload_max_filesize');
Log::set($message, LOG_TYPE_ERROR);
ajaxResponse(1, $message);
}
// Convert URL characters such as spaces or quotes to characters
$filename = urldecode($filename);
// Move from PHP tmp file to Bludit tmp directory
Filesystem::mv($_FILES['images']['tmp_name'][$uuid], PATH_TMP.$filename);
// Transform the image and generate the thumbnail
$image = transformImage(PATH_TMP.$filename, $imageDirectory, $thumbnailDirectory);
if ($image) {
$filename = Filesystem::filename($image);
array_push($images, $filename);
} else {
$message = $L->g('File type is not supported. Allowed types:').' '.implode(', ',$GLOBALS['ALLOWED_IMG_EXTENSION']);
Log::set($message, LOG_TYPE_ERROR);
ajaxResponse(1, $message);
}
}
ajaxResponse(0, 'Images uploaded.', array(
'images'=>$images
));
?>
The first thing that happens is that the code retrieves the โuuidโ parameter from a POST request:
$uuid = empty($_POST['uuid']) ? false : $_POST['uuid'];
The uuid is used as part of the image directory path. If the path doesnโt exist, then it will be automatically created:
if ($uuid && IMAGE_RESTRICT) {
$imageDirectory = PATH_UPLOADS_PAGES.$uuid.DS;
$thumbnailDirectory = $imageDirectory.'thumbnails'.DS;
if (!Filesystem::directoryExists($thumbnailDirectory)) {
Filesystem::mkdir($thumbnailDirectory, true);
}
Next, the code starts uploading the file by accessing the $_FILES
variables. In here, the content of the uploaded item isnโt checked, which means even though the file expects an image file, it doesnโt actually have to be. A malicious PHP payload could be uploaded instead:
foreach ($_FILES['images']['name'] as $uuid=>$filename) {
// ... code ...
Finally, the file is moved from PHPโs temp file to a custom tmp directory:
Filesystem::mv($_FILES['images']['tmp_name'][$uuid], PATH_TMP.$filename);
Even though the image upload is uploaded to Blueditโs tmp directory, you can actually also upload a .htaccess file to allow the PHP payload to be accessed remotely, and gain remote code execution.
Assessed Attacker Value: 5
Assessed Attacker Value: 5Assessed Attacker Value: 5
packetstormsecurity.com/files/155295/Bludit-Directory-Traversal-Image-File-Upload.html
packetstormsecurity.com/files/157988/Bludit-3.9.12-Directory-Traversal.html
packetstormsecurity.com/files/158569/Bludit-3.9.2-Directory-Traversal.html
cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-16113
github.com/bludit/bludit/issues/1081