Private GIT

Skip to content
Snippets Groups Projects
Commit f2624d10 authored by loiclau's avatar loiclau Committed by Kevin Duret
Browse files

fix(security) Secure upload images (#5863)

* add function uploadImg

* secure upload image

* rename uploader to manager

* secure update

* fix style

* move image

* clean dead code

* fix upload

* fix error msg

* fix license

* update license
parent 053c9e9d
No related branches found
No related tags found
No related merge requests found
<?php
/*
* Copyright 2005-2017 Centreon
* Centreon is developped by : Julien Mathis and Romain Le Merlus under
* GPL Licence 2.0.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation ; either version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, see <http://www.gnu.org/licenses>.
*
* Linking this program statically or dynamically with other modules is making a
* combined work based on this program. Thus, the terms and conditions of the GNU
* General Public License cover the whole combination.
*
* As a special exception, the copyright holders of this program give Centreon
* permission to link this program with independent modules to produce an executable,
* regardless of the license terms of these independent modules, and to copy and
* distribute the resulting executable under terms of Centreon choice, provided that
* Centreon also meet, for each linked independent module, the terms and conditions
* of the license of that module. An independent module is a module which is not
* derived from this program. If you modify this program, you may extend this
* exception to your version of the program, but you are not obliged to do so. If you
* do not wish to do so, delete this exception statement from your version.
*
* For more information : contact@centreon.com
*
*/
/**
* Created by PhpStorm.
* User: loic
* Date: 31/10/17
* Time: 11:55
*/
class CentreonFileManager implements iFileManager
{
protected $rawFile;
protected $comment;
protected $tmpFile;
protected $mediaPath;
protected $destinationPath;
protected $destinationDir;
protected $originalFile;
protected $fileName;
protected $size;
protected $extension;
protected $newFile;
protected $completePath;
protected $legalExtensions;
protected $legalSize;
/**
* centreonFileManager constructor.
* @param \Pimple\Container $dependencyInjector
* @param $rawFile
* @param $mediaPath
* @param $destinationDir
* @param string $comment
*/
public function __construct(
$rawFile,
$mediaPath,
$destinationDir,
$comment = ''
) {
$this->mediaPath = $mediaPath;
$this->comment = $comment;
$this->rawFile = $rawFile["filename"];
$this->destinationDir = $this->secureName($destinationDir);
$this->destinationPath = $this->mediaPath . $this->destinationDir;
$this->dirExist($this->destinationPath);
$this->originalFile = $this->rawFile['name'];
$this->tmpFile = $this->rawFile['tmp_name'];
$this->size = $this->rawFile['size'];
$this->extension = pathinfo($this->originalFile, PATHINFO_EXTENSION);
$this->fileName = $this->secureName(basename($this->originalFile, '.' . $this->extension));
$this->newFile = $this->fileName . '.' . $this->extension;
$this->completePath = $this->destinationPath . '/' . $this->newFile;
$this->legalExtensions = array();
$this->legalSize = 500000;
}
/**
* @return mixed
*/
public function upload()
{
if ($this->securityCheck()) {
$this->moveFile();
return true;
} else {
return false;
};
}
/**
* @return bool
*/
protected function securityCheck()
{
if (!$this->validFile() ||
!$this->validSize() ||
!$this->secureExtension() ||
$this->fileExist()
) {
return false;
} else {
return true;
}
}
/**
* @param $text
* @return mixed
*/
protected function secureName($text)
{
$utf8 = array(
'/[áàâãªä]/u' => 'a',
'/[ÁÀÂÃÄ]/u' => 'A',
'/[ÍÌÎÏ]/u' => 'I',
'/[íìîï]/u' => 'i',
'/[éèêë]/u' => 'e',
'/[ÉÈÊË]/u' => 'E',
'/[óòôõºö]/u' => 'o',
'/[ÓÒÔÕÖ]/u' => 'O',
'/[úùûü]/u' => 'u',
'/[ÚÙÛÜ]/u' => 'U',
'/ç/' => 'c',
'/Ç/' => 'C',
'/ñ/' => 'n',
'/Ñ/' => 'N',
'/–/' => '-',
'/[“”«»„"’‘‹›‚]/u' => '',
'/ /' => '',
'/\//' => '',
'/\'/' => '',
);
return preg_replace(array_keys($utf8), array_values($utf8), $text);
}
/**
* @return bool
*/
protected function secureExtension()
{
if (in_array(strtolower($this->extension), $this->legalExtensions)) {
return true;
} else {
return false;
}
}
/**
* @return bool
*/
protected function validFile()
{
if (empty($this->tmpFile) || $this->size == 0) {
return false;
} else {
return true;
}
}
/**
* @return bool
*/
protected function validSize()
{
if ($this->size < $this->legalSize) {
return true;
} else {
return false;
}
}
/**
* @return bool
*/
protected function fileExist()
{
if (file_exists($this->completePath)) {
return true;
} else {
return false;
}
}
/**
* @param $dir
*/
protected function dirExist($dir)
{
if (!is_dir($dir)) {
@mkdir($dir);
}
}
/**
* @return mixed
*/
protected function moveFile()
{
move_uploaded_file($this->tmpFile, $this->completePath);
}
}
<?php
/*
* Copyright 2005-2017 Centreon
* Centreon is developped by : Julien Mathis and Romain Le Merlus under
* GPL Licence 2.0.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation ; either version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, see <http://www.gnu.org/licenses>.
*
* Linking this program statically or dynamically with other modules is making a
* combined work based on this program. Thus, the terms and conditions of the GNU
* General Public License cover the whole combination.
*
* As a special exception, the copyright holders of this program give Centreon
* permission to link this program with independent modules to produce an executable,
* regardless of the license terms of these independent modules, and to copy and
* distribute the resulting executable under terms of Centreon choice, provided that
* Centreon also meet, for each linked independent module, the terms and conditions
* of the license of that module. An independent module is a module which is not
* derived from this program. If you modify this program, you may extend this
* exception to your version of the program, but you are not obliged to do so. If you
* do not wish to do so, delete this exception statement from your version.
*
* For more information : contact@centreon.com
*
*/
/**
* Created by PhpStorm.
* User: loic
* Date: 31/10/17
* Time: 11:55
*/
class CentreonImageManager extends centreonFileManager
{
protected $legalExtensions;
protected $legalSize;
/**
* centreonImageUploader constructor.
* @param $rawFile
* @param $basePath
* @param string $destinationDir
* @param string $comment
*/
public function __construct($rawFile, $basePath, $destinationDir, $comment = '')
{
parent::__construct($rawFile, $basePath, $destinationDir, $comment);
$this->legalExtensions = array("jpg", "jpeg", "png", "gif");
$this->legalSize = 2000000;
}
/**
* @param bool $insert
* @return array
*/
public function upload($insert = true)
{
$parentUpload = parent::upload();
if ($parentUpload) {
if ($insert) {
$img_ids[] = $this->insertImg(
$this->destinationPath,
$this->destinationDir,
$this->newFile,
$this->comment
);
return $img_ids;
}
} else {
return false;
}
}
/**
* @param $imgId
* @param $imgName
* @return bool
*/
public function update($imgId, $imgName)
{
if (!$imgId || empty($imgName)) {
return false;
}
global $pearDB;
$query = "SELECT dir_id, dir_alias, img_path, img_comment FROM view_img, view_img_dir, view_img_dir_relation " .
"WHERE img_id = '" . $imgId . "' AND img_id = img_img_id AND dir_dir_parent_id = dir_id";
$dbResult = $pearDB->query($query);
if (!$dbResult) {
return false;
}
$img_info = $dbResult->fetchRow();
// update if new file
if (!empty($this->originalFile) && !empty($this->tmpFile)) {
$this->deleteImg($this->mediaPath . $img_info["dir_alias"] . '/' . $img_info["img_path"]);
$this->upload(false);
$query = "UPDATE view_img SET img_path = '" . $this->newFile . "' WHERE img_id = '" . $imgId . "'";
$pearDB->query($query);
}
// update image info
$query = "UPDATE view_img SET img_name = '" . $this->secureName($imgName) .
"', img_comment = '" . $this->comment . "' WHERE img_id = '" . $imgId . "'";
$pearDB->query($query);
//check directory
if (!($dirId = $this->checkDirectoryExistence())) {
$dirId = $this->insertDirectory();
} elseif ($img_info['dir_alias'] != $this->destinationDir) {
$old = $this->mediaPath . $img_info['dir_alias'] . '/' . $img_info["img_path"];
$new = $this->mediaPath . $this->destinationDir . '/' . $img_info["img_path"];
$this->moveImage($old, $new);
}
//update relation
$query = "UPDATE view_img_dir_relation SET dir_dir_parent_id = '" . $dirId .
"' WHERE img_img_id = '" . $imgId . "'";
$pearDB->query($query);
return true;
}
/**
* @param $fullPath
*/
protected function deleteImg($fullPath)
{
unlink($fullPath);
}
/**
* @return int
*/
protected function checkDirectoryExistence()
{
global $pearDB;
$dirId = 0;
$dbResult = $pearDB->query(
"SELECT dir_name, dir_id FROM view_img_dir WHERE dir_name = '" . $this->destinationDir . "'"
);
if ($dbResult->numRows() >= 1) {
$dir = $dbResult->fetchRow();
$dirId = $dir["dir_id"];
}
return $dirId;
}
/**
* @return mixed
*/
protected function insertDirectory()
{
global $pearDB;
touch($this->destinationPath . "/index.html");
$query = "INSERT INTO view_img_dir " .
"(dir_name, dir_alias) " .
"VALUES " .
"('" . $this->destinationDir . "', '" . $this->destinationDir . "')";
$pearDB->query($query);
$dbResult = $pearDB->query("SELECT MAX(dir_id) FROM view_img_dir");
$dirId = $dbResult->fetchRow();
$dbResult->free();
return ($dirId["MAX(dir_id)"]);
}
/**
* @param $dirId
*/
protected function updateDirectory($dirId)
{
global $pearDB;
$query = "UPDATE view_img_dir SET dir_name = '" . $this->destinationDir .
"', dir_alias = '" . $this->destinationDir . "' WHERE dir_id = " . $dirId;
$pearDB->query($query);
}
/**
* @return mixed
*/
protected function insertImg()
{
global $pearDB;
if (!($dirId = $this->checkDirectoryExistence())) {
$dirId = $this->insertDirectory();
}
$query = "INSERT INTO view_img " .
"(img_name, img_path, img_comment) " .
"VALUES " .
"('" . $this->fileName . "', '" . $this->newFile . "', '" . $pearDB->escape($this->comment) . "')";
$pearDB->query($query);
$res = $pearDB->query("SELECT MAX(img_id) FROM view_img");
$imgId = $res->fetchRow();
$imgId = $imgId["MAX(img_id)"];
$pearDB->query(
"INSERT INTO view_img_dir_relation (dir_dir_parent_id, img_img_id) " .
"VALUES ('" . $dirId . "', '" . $imgId . "')"
);
$res->free();
return ($imgId);
}
/**
* @param $old
* @param $new
*/
protected function moveImage($old, $new)
{
copy($old, $new);
$this->deleteImg($old);
}
}
<?php
/*
* Copyright 2005-2017 Centreon
* Centreon is developped by : Julien Mathis and Romain Le Merlus under
* GPL Licence 2.0.
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free Software
* Foundation ; either version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, see <http://www.gnu.org/licenses>.
*
* Linking this program statically or dynamically with other modules is making a
* combined work based on this program. Thus, the terms and conditions of the GNU
* General Public License cover the whole combination.
*
* As a special exception, the copyright holders of this program give Centreon
* permission to link this program with independent modules to produce an executable,
* regardless of the license terms of these independent modules, and to copy and
* distribute the resulting executable under terms of Centreon choice, provided that
* Centreon also meet, for each linked independent module, the terms and conditions
* of the license of that module. An independent module is a module which is not
* derived from this program. If you modify this program, you may extend this
* exception to your version of the program, but you are not obliged to do so. If you
* do not wish to do so, delete this exception statement from your version.
*
* For more information : contact@centreon.com
*
*/
/**
* Created by PhpStorm.
* User: loic
* Date: 31/10/17
* Time: 11:53
*/
interface iFileManager
{
/**
* @return mixed
*/
public function upload();
}
...@@ -107,7 +107,6 @@ function is_gd2($filename) ...@@ -107,7 +107,6 @@ function is_gd2($filename)
return false; return false;
} }
function handleUpload($HTMLfile, $dir_alias, $img_comment = "") function handleUpload($HTMLfile, $dir_alias, $img_comment = "")
{ {
if (!$HTMLfile || !$dir_alias) { if (!$HTMLfile || !$dir_alias) {
......
...@@ -36,6 +36,9 @@ ...@@ -36,6 +36,9 @@
* *
*/ */
require_once _CENTREON_PATH_ . "www/class/centreonImageManager.php";
if (!isset($centreon)) { if (!isset($centreon)) {
exit(); exit();
} }
...@@ -97,7 +100,7 @@ if ($o == "a") { ...@@ -97,7 +100,7 @@ if ($o == "a") {
$dir_list_sel, $dir_list_sel,
array('onchange' => 'document.getElementById("directories").value = this.options[this.selectedIndex].text;') array('onchange' => 'document.getElementById("directories").value = this.options[this.selectedIndex].text;')
); );
$file = $form->addElement('file', 'filename', _("Image or archive")); $form->addElement('file', 'filename', _("Image or archive"));
$subA = $form->addElement('submit', 'submitA', _("Save"), array("class" => "btc bt_success")); $subA = $form->addElement('submit', 'submitA', _("Save"), array("class" => "btc bt_success"));
} elseif ($o == "ci") { } elseif ($o == "ci") {
$form->addElement('header', 'title', _("Modify Image")); $form->addElement('header', 'title', _("Modify Image"));
...@@ -117,7 +120,7 @@ if ($o == "a") { ...@@ -117,7 +120,7 @@ if ($o == "a") {
array('onchange' => 'document.getElementById("directories").value = this.options[this.selectedIndex].text;') array('onchange' => 'document.getElementById("directories").value = this.options[this.selectedIndex].text;')
); );
$list_dir->setSelected($dir['dir_id']); $list_dir->setSelected($dir['dir_id']);
$file = $form->addElement('file', 'filename', _("Image")); $form->addElement('file', 'filename', _("Image"));
$subC = $form->addElement('submit', 'submitC', _("Save"), array("class" => "btc bt_success")); $subC = $form->addElement('submit', 'submitC', _("Save"), array("class" => "btc bt_success"));
$form->setDefaults($img); $form->setDefaults($img);
$form->addRule('img_name', _("Compulsory image name"), 'required'); $form->addRule('img_name', _("Compulsory image name"), 'required');
...@@ -126,7 +129,7 @@ if ($o == "a") { ...@@ -126,7 +129,7 @@ if ($o == "a") {
$form->addElement('text', 'img_name', _("Image Name"), $attrsText); $form->addElement('text', 'img_name', _("Image Name"), $attrsText);
$form->addElement('text', 'img_path', $img_path, null); $form->addElement('text', 'img_path', $img_path, null);
$form->addElement('autocomplete', 'directories', _("Directory"), $dir_ids, array('id', 'directories')); $form->addElement('autocomplete', 'directories', _("Directory"), $dir_ids, array('id', 'directories'));
$file = $form->addElement('file', 'filename', _("Image")); $form->addElement('file', 'filename', _("Image"));
$form->addElement( $form->addElement(
"button", "button",
"change", "change",
...@@ -200,14 +203,15 @@ $tpl->assign("helptext", $helptext); ...@@ -200,14 +203,15 @@ $tpl->assign("helptext", $helptext);
$valid = false; $valid = false;
if ($form->validate()) { if ($form->validate()) {
$imgID = $form->getElement('img_id'); $imgId = $form->getElement('img_id')->getValue();
$imgPath = $form->getElement('directories')->getValue(); $imgPath = $form->getElement('directories')->getValue();
$imgComment = $form->getElement('img_comment')->getValue(); $imgComment = $form->getElement('img_comment')->getValue();
$oImageUploader = new CentreonImageManager($_FILES, './img/media/', $imgPath, $imgComment);
if ($form->getSubmitValue("submitA")) { if ($form->getSubmitValue("submitA")) {
$valid = handleUpload($file, $imgPath, $imgComment); $valid = $oImageUploader->upload();
} elseif ($form->getSubmitValue("submitC")) { } elseif ($form->getSubmitValue("submitC")) {
$imgName = $form->getElement('img_name')->getValue(); $imgName = $form->getElement('img_name')->getValue();
$valid = updateImg($imgID->getValue(), $file, $imgPath, $imgName, $imgComment); $valid = $oImageUploader->update($imgId, $imgName);
} }
$form->freeze(); $form->freeze();
if (false === $valid) { if (false === $valid) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment