Skip to content

Commit

Permalink
Fixed vulnerabilities reported by João Victor #339
Browse files Browse the repository at this point in the history
  • Loading branch information
givanz committed Mar 2, 2024
1 parent af1f29c commit c6422cf
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 30 deletions.
83 changes: 65 additions & 18 deletions save.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,29 @@
*/

define('MAX_FILE_LIMIT', 1024 * 1024 * 2);//2 Megabytes max html file size
define('ALLOW_PHP', false);//check if saved html contains php tag and don't save if not allowed
define('ALLOWED_OEMBED_DOMAINS', [
'https://www.youtube.com/',
'https://www.vimeo.com/',
'https://www.twitter.com/'
]);//load urls only from allowed websites for oembed

function sanitizeFileName($file, $allowedExtension = 'html') {
$basename = basename($file);
$disallow = ['.htaccess', 'passwd'];
if (in_array($basename, $disallow)) {
showError('Filename not allowed!');
return '';
}

//sanitize, remove double dot .. and remove get parameters if any
$file = __DIR__ . '/' . preg_replace('@\?.*$@' , '', preg_replace('@\.{2,}@' , '', preg_replace('@[^\/\\a-zA-Z0-9\-\._]@', '', $file)));
$file = preg_replace('@\?.*$@' , '', preg_replace('@\.{2,}@' , '', preg_replace('@[^\/\\a-zA-Z0-9\-\._]@', '', $file)));

if ($file) {
$file = __DIR__ . DIRECTORY_SEPARATOR . $file;
} else {
return '';
}

//allow only .html extension
if ($allowedExtension) {
Expand All @@ -35,19 +54,38 @@ function showError($error) {
die($error);
}

function validOembedUrl($url) {
foreach (ALLOWED_OEMBED_DOMAINS as $domain) {
if (strpos($url, $domain) === 0) {
return true;
}
}

return false;
}

$html = '';
$file = '';
$action = '';

if (isset($_POST['startTemplateUrl']) && !empty($_POST['startTemplateUrl'])) {
$startTemplateUrl = sanitizeFileName($_POST['startTemplateUrl']);
$html = file_get_contents($startTemplateUrl);
$html = '';
if ($startTemplateUrl) {
$html = file_get_contents($startTemplateUrl);
}
} else if (isset($_POST['html'])){
$html = substr($_POST['html'], 0, MAX_FILE_LIMIT);
if (!ALLOW_PHP) {
//if (strpos($html, '<?php') !== false) {
if (preg_match('@<\?php|<\? |<\?=|<\s*script\s*language\s*=\s*"\s*php\s*"\s*>@', $html)) {
showError('PHP not allowed!');
}
}
}

if (isset($_POST['file'])) {
$file = sanitizeFileName($_POST['file'], false);
$file = sanitizeFileName($_POST['file']);
}

if (isset($_GET['action'])) {
Expand All @@ -58,7 +96,7 @@ function showError($error) {
//file manager actions, delete and rename
switch ($action) {
case 'rename':
$newfile = sanitizeFileName($_POST['newfile'], false);
$newfile = sanitizeFileName($_POST['newfile']);
if ($file && $newfile) {
if (rename($file, $newfile)) {
echo "File '$file' renamed to '$newfile'";
Expand All @@ -85,28 +123,37 @@ function showError($error) {
if ($type && $name && $html) {

$file = sanitizeFileName("$type/$name");
$dir = dirname($file);
if (!is_dir($dir)) {
echo "$dir folder does not exist\n";
if (mkdir($dir, 0777, true)) {
echo "$dir folder was created\n";
if ($file) {
$dir = dirname($file);
if (!is_dir($dir)) {
echo "$dir folder does not exist\n";
if (mkdir($dir, 0777, true)) {
echo "$dir folder was created\n";
} else {
showError("Error creating folder '$dir'\n");
}
}

if (file_put_contents($file, $html)) {
echo "File saved '$file'";
} else {
showError("Error creating folder '$dir'\n");
}
}

if (file_put_contents($file, $html)) {
echo "File saved '$file'";
showError("Error saving file '$file'\nPossible causes are missing write permission or incorrect file path!");
}
} else {
showError("Error saving file '$file'\nPossible causes are missing write permission or incorrect file path!");
showError('Invalid filename!');
}
} else {
showError("Missing reusable element data!\n");
}
break;
case 'oembedProxy':
header('Content-Type: application/json');
echo file_get_contents($_GET['url']);
$url = $_GET['url'] ?? '';
if (validOembedUrl($url)) {
header('Content-Type: application/json');
echo file_get_contents($url);
} else {
showError('Invalid url!');
}
break;
default:
showError("Invalid action '$action'!");
Expand Down
12 changes: 9 additions & 3 deletions scan.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,19 @@

//scan media folder for all files to display in media modal

if (isset($_POST['mediaPath'])) {
define('UPLOAD_PATH', $_POST['mediaPath']);
function sanitizePath($path) {
//sanitize, remove double dot .. and remove get parameters if any
$path = preg_replace('@/+@' , DIRECTORY_SEPARATOR, preg_replace('@\?.*$@' , '', preg_replace('@\.{2,}@' , '', preg_replace('@[^\/\\a-zA-Z0-9\-\._]@', '', $path))));
return $path;
}

if (isset($_POST['mediaPath']) && ($path = sanitizePath(substr($_POST['mediaPath'], 0, 256)))) {
define('UPLOAD_PATH', $path);
} else {
define('UPLOAD_PATH', 'media');
}

$scandir = __DIR__ . '/' . UPLOAD_PATH;
$scandir = __DIR__ . DIRECTORY_SEPARATOR. UPLOAD_PATH;

// Run the recursive function
// This function scans the files folder recursively, and builds a large array
Expand Down
23 changes: 14 additions & 9 deletions upload.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
*/

$uploadDenyExtensions = ['php'];
$uploadAllowExtensions = ['ico','jpg','jpeg','png','gif','webp'];
$uploadAllowExtensions = ['ico','jpg','jpeg','png','gif','webp','svg'];

function showError($error) {
header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error', true, 500);
Expand All @@ -31,36 +31,41 @@ function showError($error) {

function sanitizeFileName($file)
{
$disallow = ['.htaccess', 'passwd'];
$file = str_replace($disallow, '', $file);

//sanitize, remove double dot .. and remove get parameters if any
$file = preg_replace('@\?.*$@' , '', preg_replace('@\.{2,}@' , '', preg_replace('@[^\/\\a-zA-Z0-9\-\._]@', '', $file)));

return $file;
}


define('UPLOAD_FOLDER', __DIR__ . '/');
define('UPLOAD_FOLDER', __DIR__ . DIRECTORY_SEPARATOR);
if (isset($_POST['mediaPath'])) {
define('UPLOAD_PATH', sanitizeFileName($_POST['mediaPath']) .'/');
define('UPLOAD_PATH', sanitizeFileName($_POST['mediaPath']) . DIRECTORY_SEPARATOR);
} else {
define('UPLOAD_PATH', '/');
define('UPLOAD_PATH', DIRECTORY_SEPARATOR);
}

$fileName = sanitizeFileName($_FILES['file']['name']);
if (!$fileName) {
showError('Invalid filename!');
}

$fileName = $_FILES['file']['name'];
$extension = strtolower(substr($fileName, strrpos($fileName, '.') + 1));

//check if extension is on deny list
if (in_array($extension, $uploadDenyExtensions)) {
showError("File type $extension not allowed!");
}

/*
//comment deny code above and uncomment this code to change to a more restrictive allowed list
// check if extension is on allow list
if (!in_array($extension, $uploadAllowExtensions)) {
showError("File type $extension not allowed!");
}
*/

$destination = UPLOAD_FOLDER . UPLOAD_PATH . '/' . $fileName;
$destination = UPLOAD_FOLDER . UPLOAD_PATH . DIRECTORY_SEPARATOR . $fileName;
move_uploaded_file($_FILES['file']['tmp_name'], $destination);

if (isset($_POST['onlyFilename'])) {
Expand Down

0 comments on commit c6422cf

Please sign in to comment.