CVE-2018-11330 (PHP, published 2018-05-21T21:29Z)
Description: value: An issue was discovered in Pluck before 4.7.6. There is authenticated stored XSS because the character set for filenames is not properly restricted.
Severity: LOW (CVSS v3 base score: 4.8)
Weakness: CWE-79 \u2014 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
Repository: https://github.com/pluck-cms/pluck
Files changed:
data/inc/editpage.php
data/inc/files.php
data/inc/functions.all.php
data/inc/images.php
data/modules/.htaccess
data/themes/.htaccess
files/.htaccess
images/.htaccess
Commit message: bugfix for XSS and backdoor file upload found by s7acktrac3 issue #58


Vulnerable code:
			$seoname = save_page($title, $_POST['content'], $_POST['hidden'], $_POST['sub_page'], $_POST['description'], $_POST['keywords'], $module_additional_data, $_GET['page']);
			$seoname = save_page($title, $_POST['content'], $_POST['hidden'], $_POST['sub_page'], $_POST['description'], $_POST['keywords'], $module_additional_data);
		if (!copy($_FILES['filefile']['tmp_name'], 'files/'.$_FILES['filefile']['name']))
			if (strcasecmp(substr($_FILES['filefile']['name'], -3),'php') == 0){
				if (!rename('files/'.$_FILES['filefile']['name'], 'files/'.$_FILES['filefile']['name'].'.txt')){
				chmod('files/'.$_FILES['filefile']['name'].'.txt', 0775);
				chmod('files/'.$_FILES['filefile']['name'], 0775);
					<strong><?php echo $lang['files']['name']; ?></strong> <?php echo $_FILES['filefile']['name']; ?>
					<strong><?php echo $lang['files']['size']; ?></strong> <?php echo $_FILES['filefile']['size'].' '.$lang['images']['bytes']; ?>
					<strong><?php echo $lang['files']['type']; ?></strong> <?php echo $_FILES['filefile']['type']; ?>
		if (!copy($_FILES['imagefile']['tmp_name'], 'images/'.$_FILES['imagefile']['name']))
					<strong><?php echo $lang['images']['name']; ?></strong> <?php echo $_FILES['imagefile']['name']; ?>
					<strong><?php echo $lang['images']['size']; ?></strong> <?php echo $_FILES['imagefile']['size'].' '.$lang['images']['bytes']; ?>
					<strong><?php echo $lang['images']['type']; ?></strong> <?php echo $_FILES['imagefile']['type']; ?>

Fixed code:
			$seoname = latinOnlyInput(save_page($title, $_POST['content'], $_POST['hidden'], $_POST['sub_page'], $_POST['description'], $_POST['keywords'], $module_additional_data, $_GET['page']));
			$seoname = latinOnlyInput(save_page($title, $_POST['content'], $_POST['hidden'], $_POST['sub_page'], $_POST['description'], $_POST['keywords'], $module_additional_data));
		if (!copy($_FILES['filefile']['tmp_name'], 'files/'.latinOnlyInput(latinOnlyInput($_FILES['filefile']['name']))))
			$lastfour = strtolower(substr(latinOnlyInput($_FILES['filefile']['name']), -4));
			$lastfive = strtolower(substr(latinOnlyInput($_FILES['filefile']['name']), -5));
			$blockedExtentions = array('.php','php3','php4','php5','php6','php7','phtml');
			if (in_array($lastfour, $blockedExtentions) or in_array($lastfive, $blockedExtentions) ){
				if (!rename('files/'.latinOnlyInput($_FILES['filefile']['name']), 'files/'.latinOnlyInput($_FILES['filefile']['name']).'.txt')){
				chmod('files/'.latinOnlyInput($_FILES['filefile']['name']).'.txt', 0775);
				chmod('files/'.latinOnlyInput($_FILES['filefile']['name']), 0775);
					<strong><?php echo $lang['files']['name']; ?></strong> <?php echo latinOnlyInput($_FILES['filefile']['name']); ?>
					<strong><?php echo $lang['files']['size']; ?></strong> <?php echo latinOnlyInput($_FILES['filefile']['size']).' '.$lang['images']['bytes']; ?>
					<strong><?php echo $lang['files']['type']; ?></strong> <?php echo latinOnlyInput($_FILES['filefile']['type']); ?>
			if (!($file == '.htaccess')){
			}
	$var = htmlspecialchars($var, ENT_COMPAT, 'UTF-8', false);
/**
 * latinOnlyInput from a URL, to make it ready for saving in a file.
 *
 * @since 4.7.5
 * @package all
 * @param string $var Variable 
 * @return string The sanitized variable.
 * 
 * Added as bugfix for XSS and backdoor file upload found by s7acktrac3
 */
function latinOnlyInput($var) {
	$var = str_replace(chr(0), '', $var);
	$var = preg_replace("/[^a-zA-Z0-9.\ -_]+/", "", $var);;
	return $var;
}


		if (!copy($_FILES['imagefile']['tmp_name'], 'images/'.latinOnlyInput($_FILES['imagefile']['name'])))
					<strong><?php echo $lang['images']['name']; ?></strong> <?php echo latinOnlyInput($_FILES['imagefile']['name']); ?>
					<strong><?php echo $lang['images']['size']; ?></strong> <?php echo latinOnlyInput($_FILES['imagefile']['size']).' '.$lang['images']['bytes']; ?>
					<strong><?php echo $lang['images']['type']; ?></strong> <?php echo latinOnlyInput($_FILES['imagefile']['type']); ?>
			if (!($image == '.htaccess')){
			}
<FilesMatch \.php$>
    SetHandler None
</FilesMatch>

<FilesMatch \.phtml>
    SetHandler None
</FilesMatch>

Options -ExecCGI
<FilesMatch \.php$>
    SetHandler None
</FilesMatch>

<FilesMatch \.phtml>
    SetHandler None
</FilesMatch>

Options -ExecCGI
<FilesMatch \.php$>
    SetHandler None
</FilesMatch>

<FilesMatch \.phtml>
    SetHandler None
</FilesMatch>

Options -ExecCGI
<FilesMatch \.php$>
    SetHandler None
</FilesMatch>

<FilesMatch \.phtml>
    SetHandler None
</FilesMatch>

Options -ExecCGI