Attacker Value
Very High
(1 user assessed)
Exploitability
Very High
(1 user assessed)
User Interaction
None
Privileges Required
Low
Attack Vector
Network
2

Bludit 3.9.2 remote code execution

Disclosure Date: September 08, 2019
Add MITRE ATT&CK tactics and techniques that apply to this CVE.

Description

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.

Add Assessment

2
Ratings
  • Attacker Value
    Very High
  • Exploitability
    Very High
Technical Analysis

CVE-2019-16113 Bludit Directory Traversal Vulnerability

Description

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.

Technical Analysis

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.

CVSS V3 Severity and Metrics
Base Score:
8.8 High
Impact Score:
5.9
Exploitability Score:
2.8
Vector:
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Attack Vector (AV):
Network
Attack Complexity (AC):
Low
Privileges Required (PR):
Low
User Interaction (UI):
None
Scope (S):
Unchanged
Confidentiality (C):
High
Integrity (I):
High
Availability (A):
High

General Information

Technical Analysis