Skip to content

Commit

Permalink
Release 4.0.4
Browse files Browse the repository at this point in the history
  • Loading branch information
Brandon Olivares committed Mar 12, 2024
1 parent 242ab74 commit b23d839
Show file tree
Hide file tree
Showing 10 changed files with 133 additions and 97 deletions.
6 changes: 3 additions & 3 deletions backwpup.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* Description: WordPress Backup Plugin
* Author: WP MEDIA SAS
* Author URI: https://wp-media.me/
* Version: 4.0.3
* Version: 4.0.4
* Requires at least: 3.9
* Requires PHP: 7.2
* Text Domain: backwpup
Expand Down Expand Up @@ -243,14 +243,14 @@ public static function get_plugin_data($name = null)
'\\',
'/',
get_temp_dir()
) . 'backwpup-' . self::$plugin_data['hash'] . '/';
) . 'backwpup/' . self::$plugin_data['hash'] . '/';
} else {
$upload_dir = wp_upload_dir();
self::$plugin_data['temp'] = str_replace(
'\\',
'/',
$upload_dir['basedir']
) . '/backwpup-' . self::$plugin_data['hash'] . '-temp/';
) . '/backwpup/' . self::$plugin_data['hash'] . '/temp/';
}
self::$plugin_data['running_file'] = self::$plugin_data['temp'] . 'backwpup-working.php';
self::$plugin_data['url'] = plugins_url('', __FILE__);
Expand Down
5 changes: 5 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
== Changelog ==
= 4.0.4 =
Release date: March 12, 2024

* Fixed: Changed directory structure of BackWPup temporary files to prevent unauthorized access of database backup.

= 4.0.3 =
Release date: February 22, 2024

Expand Down
2 changes: 1 addition & 1 deletion inc/class-destination-folder.php
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ private static function getDefaultBackupsDirectory()
'/',
$upload_dir['basedir']
)
) . 'backwpup-' . BackWPup::get_plugin_data('hash') . '-backups/';
) . 'backwpup/' . BackWPup::get_plugin_data('hash') . '/backups/';
$content_path = trailingslashit(BackWPup_Path_Fixer::slashify((string) WP_CONTENT_DIR));

return str_replace($content_path, '', $backups_dir);
Expand Down
173 changes: 102 additions & 71 deletions inc/class-file.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,15 @@ public static function is_in_open_basedir($file)
}

$open_base_dirs = explode(PATH_SEPARATOR, $ini_open_basedir);
$file = trailingslashit(strtolower(str_replace('\\', '/', $file)));
$file = trailingslashit(strtolower(BackWPup_Path_Fixer::slashify($file)));

foreach ($open_base_dirs as $open_base_dir) {
if (empty($open_base_dir) || !realpath($open_base_dir)) {
continue;
}

$open_base_dir = realpath($open_base_dir);
$open_base_dir = strtolower(str_replace('\\', '/', $open_base_dir));
$open_base_dir = strtolower(BackWPup_Path_Fixer::slashify($open_base_dir));
$part = substr($file, 0, strlen($open_base_dir));
if ($part === $open_base_dir) {
return true;
Expand Down Expand Up @@ -100,16 +101,16 @@ public static function get_folder_size($folder)
*/
public static function get_absolute_path($path = '/')
{
$path = str_replace('\\', '/', $path);
$content_path = trailingslashit(str_replace('\\', '/', (string) WP_CONTENT_DIR));
$path = BackWPup_Path_Fixer::slashify($path);
$content_path = trailingslashit(BackWPup_Path_Fixer::slashify((string) WP_CONTENT_DIR));

//use WP_CONTENT_DIR as root folder
if (empty($path) || $path === '/') {
$path = $content_path;
}

//make relative path to absolute
if (substr($path, 0, 1) !== '/' && !preg_match('#^[a-zA-Z]:/#', $path)) {
if (substr($path, 0, 1) !== '/' && !preg_match('#^[a-zA-Z]+:/#', $path)) {
$path = $content_path . $path;
}

Expand All @@ -125,19 +126,18 @@ public static function get_absolute_path($path = '/')
*
* @return string with error message if one
*/
public static function check_folder($folder, $donotbackup = false)
public static function check_folder(string $folder, bool $donotbackup = false): string
{
$folder = self::get_absolute_path($folder);
$folder = untrailingslashit($folder);

//check that is not home of WP
$uploads = self::get_upload_dir();
if ($folder === untrailingslashit(str_replace('\\', '/', (string) ABSPATH))
|| $folder === untrailingslashit(str_replace('\\', '/', dirname((string) ABSPATH)))
|| $folder === untrailingslashit(str_replace('\\', '/', (string) WP_PLUGIN_DIR))
|| $folder === untrailingslashit(str_replace('\\', '/', (string) WP_CONTENT_DIR))
|| $folder === untrailingslashit($uploads)
|| $folder === '/'
if ($folder === untrailingslashit(BackWPup_Path_Fixer::slashify(ABSPATH))
|| $folder === untrailingslashit(BackWPup_Path_Fixer::slashify(dirname(ABSPATH)))
|| $folder === untrailingslashit(BackWPup_Path_Fixer::slashify(WP_PLUGIN_DIR))
|| $folder === untrailingslashit(BackWPup_Path_Fixer::slashify(WP_CONTENT_DIR))
|| $folder === untrailingslashit(BackWPup_Path_Fixer::slashify($uploads))
) {
return sprintf(__('Folder %1$s not allowed, please use another folder.', 'backwpup'), $folder);
}
Expand All @@ -147,63 +147,41 @@ public static function check_folder($folder, $donotbackup = false)
return sprintf(__('Folder %1$s is not in open basedir, please use another folder.', 'backwpup'), $folder);
}

//create folder if it not exists
if (!is_dir($folder)) {
if (!wp_mkdir_p($folder)) {
return sprintf(__('Cannot create folder: %1$s', 'backwpup'), $folder);
}
}
// We always want to at least process `$folder`
$foldersToProcess = [$folder];
$parentFolder = dirname($folder);

//check is writable dir
if (!is_writable($folder)) {
return sprintf(__('Folder "%1$s" is not writable', 'backwpup'), $folder);
while (!file_exists($parentFolder)) {
array_unshift($foldersToProcess, $parentFolder);
$parentFolder = dirname($parentFolder);
}

//create files for securing folder
if (get_site_option('backwpup_cfg_protectfolders')) {
$server_software = strtolower((string) $_SERVER['SERVER_SOFTWARE']);
//IIS
if (strstr($server_software, 'microsoft-iis')) {
if (!file_exists($folder . '/Web.config')) {
file_put_contents(
$folder . '/Web.config',
'<configuration>' . PHP_EOL .
"\t<system.webServer>" . PHP_EOL .
"\t\t<authorization>" . PHP_EOL .
"\t\t\t<deny users=\"*\" />" . PHP_EOL .
"\t\t</authorization>" . PHP_EOL .
"\t</system.webServer>" . PHP_EOL .
'</configuration>'
);
}
} //Nginx
elseif (strstr($server_software, 'nginx')) {
if (!file_exists($folder . '/index.php')) {
file_put_contents($folder . '/index.php', '<?php' . PHP_EOL . "header( \$_SERVER['SERVER_PROTOCOL'] . ' 404 Not Found' );" . PHP_EOL . "header( 'Status: 404 Not Found' );" . PHP_EOL);
}
} //Aapche and other
else {
if (!file_exists($folder . '/.htaccess')) {
file_put_contents($folder . '/.htaccess', '<Files "*">' . PHP_EOL . '<IfModule mod_access.c>' . PHP_EOL . 'Deny from all' . PHP_EOL . '</IfModule>' . PHP_EOL . '<IfModule !mod_access_compat>' . PHP_EOL . '<IfModule mod_authz_host.c>' . PHP_EOL . 'Deny from all' . PHP_EOL . '</IfModule>' . PHP_EOL . '</IfModule>' . PHP_EOL . '<IfModule mod_access_compat>' . PHP_EOL . 'Deny from all' . PHP_EOL . '</IfModule>' . PHP_EOL . '</Files>');
}
if (!file_exists($folder . '/index.php')) {
file_put_contents($folder . '/index.php', '<?php' . PHP_EOL . "header( \$_SERVER['SERVER_PROTOCOL'] . ' 404 Not Found' );" . PHP_EOL . "header( 'Status: 404 Not Found' );" . PHP_EOL);
}
// Process each child folder separately
foreach ($foldersToProcess as $childFolder) {
if (!is_dir($childFolder) && !wp_mkdir_p($childFolder)) {
return sprintf(__('Cannot create folder: %1$s', 'backwpup'), $childFolder);
}

if (!is_writable($childFolder)) {
return sprintf(__('Folder "%1$s" is not writable', 'backwpup'), $childFolder);
}

//create files for securing folder
if (get_site_option('backwpup_cfg_protectfolders')) {
self::protect_folder($childFolder);
}
}

//Create do not backup file for this folder
if ($donotbackup && !file_exists($folder . '/.donotbackup')) {
file_put_contents($folder . '/.donotbackup', __('BackWPup will not backup folders and its sub folders when this file is inside.', 'backwpup'));
//Create do not backup file for this folder
if ($donotbackup) {
self::write_do_not_backup_file($childFolder);
}
}

return '';
}

/**
* @throws InvalidArgumentException If path is absolute or attempts to navigate above root
*
* @return string[]
*/
public static function normalize_path(string $path): string
{
Expand Down Expand Up @@ -241,25 +219,78 @@ public static function normalize_path(string $path): string
*
* @return string The resolved path
*/
protected static function resolve_path($path)
protected static function resolve_path($path): string
{
$search = explode('/', $path);
$append = [];
// If last element of $search is blank, this means trailing slash is present.
// realpath() will remove trailing slash, so append to $append to preserve.
if (empty($search[count($search) - 1])) {
array_unshift($append, array_pop($search));
}
$parts = explode('/', $path);
$resolvedParts = [];

while (realpath(implode('/', $search)) === false) {
array_unshift($append, array_pop($search));
foreach ($parts as $part) {
if ($part === '..') {
if (!empty($resolvedParts)) {
array_pop($resolvedParts);
}
} elseif ($part === '.') {
continue;
} else {
$resolvedParts[] = $part;
}
}

$path = realpath(implode('/', $search));
if (!empty($append)) {
$path .= '/' . implode('/', $append);
return implode('/', $resolvedParts);
}

private static function protect_folder(string $folder): void
{
$server_software = strtolower((string) $_SERVER['SERVER_SOFTWARE']);

if (strstr($server_software, 'microsoft-iis')) {
if (!file_exists($folder . '/Web.config')) {
file_put_contents(
$folder . '/Web.config',
'<configuration>' . PHP_EOL .
"\t<system.webServer>" . PHP_EOL .
"\t\t<authorization>" . PHP_EOL .
"\t\t\t<deny users=\"*\" />" . PHP_EOL .
"\t\t</authorization>" . PHP_EOL .
"\t</system.webServer>" . PHP_EOL .
'</configuration>'
);
}
} elseif (strstr($server_software, 'nginx')) {
if (!file_exists($folder . '/index.php')) {
file_put_contents(
$folder . '/index.php',
'<?php' . PHP_EOL . "header( \$_SERVER['SERVER_PROTOCOL'] . ' 404 Not Found' );" . PHP_EOL . "header( 'Status: 404 Not Found' );" . PHP_EOL
);
}
} else {
if (!file_exists($folder . '/.htaccess')) {
file_put_contents(
$folder . '/.htaccess',
'<Files "*">' . PHP_EOL . '<IfModule mod_access.c>' . PHP_EOL . 'Deny from all' . PHP_EOL . '</IfModule>' . PHP_EOL . '<IfModule !mod_access_compat>' . PHP_EOL . '<IfModule mod_authz_host.c>' . PHP_EOL . 'Deny from all' . PHP_EOL . '</IfModule>' . PHP_EOL . '</IfModule>' . PHP_EOL . '<IfModule mod_access_compat>' . PHP_EOL . 'Deny from all' . PHP_EOL . '</IfModule>' . PHP_EOL . '</Files>'
);
}
if (!file_exists($folder . '/index.php')) {
file_put_contents(
$folder . '/index.php',
'<?php' . PHP_EOL . "header( \$_SERVER['SERVER_PROTOCOL'] . ' 404 Not Found' );" . PHP_EOL . "header( 'Status: 404 Not Found' );" . PHP_EOL
);
}
}
}

return $path;
private static function write_do_not_backup_file(string $folder): void
{
$doNotBackupFile = "{$folder}/.donotbackup";

if (!file_exists($doNotBackupFile)) {
file_put_contents(
$doNotBackupFile,
__(
'BackWPup will not backup folders and its sub folders when this file is inside.',
'backwpup'
)
);
}
}
}
2 changes: 1 addition & 1 deletion inc/class-option.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public static function default_site_options()
'\\',
'/',
$upload_dir['basedir']
)) . 'backwpup-' . BackWPup::get_plugin_data('hash') . '-logs/';
)) . 'backwpup/' . BackWPup::get_plugin_data('hash') . '/logs/';
$content_path = trailingslashit(str_replace('\\', '/', (string) WP_CONTENT_DIR));
$logs_dir = str_replace($content_path, '', $logs_dir);
add_site_option('backwpup_cfg_logfolder', $logs_dir);
Expand Down
6 changes: 3 additions & 3 deletions languages/backwpup.pot
Original file line number Diff line number Diff line change
Expand Up @@ -1317,15 +1317,15 @@ msgstr ""
msgid "Folder %1$s is not in open basedir, please use another folder."
msgstr ""

#: inc/class-file.php:153
#: inc/class-file.php:162
msgid "Cannot create folder: %1$s"
msgstr ""

#: inc/class-file.php:159
#: inc/class-file.php:166
msgid "Folder \"%1$s\" is not writable"
msgstr ""

#: inc/class-file.php:197
#: inc/class-file.php:289
msgid "BackWPup will not backup folders and its sub folders when this file is inside."
msgstr ""

Expand Down
2 changes: 1 addition & 1 deletion vendor/autoload.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@

require_once __DIR__ . '/composer/autoload_real.php';

return ComposerAutoloaderInitb81f714672cab81745951e3983f718b7::getLoader();
return ComposerAutoloaderInit302766cabed9741b63e4470141d39506::getLoader();
10 changes: 5 additions & 5 deletions vendor/composer/autoload_real.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

// autoload_real.php @generated by Composer

class ComposerAutoloaderInitb81f714672cab81745951e3983f718b7
class ComposerAutoloaderInit302766cabed9741b63e4470141d39506
{
private static $loader;

Expand All @@ -24,20 +24,20 @@ public static function getLoader()

require __DIR__ . '/platform_check.php';

spl_autoload_register(array('ComposerAutoloaderInitb81f714672cab81745951e3983f718b7', 'loadClassLoader'), true, true);
spl_autoload_register(array('ComposerAutoloaderInit302766cabed9741b63e4470141d39506', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInitb81f714672cab81745951e3983f718b7', 'loadClassLoader'));
spl_autoload_unregister(array('ComposerAutoloaderInit302766cabed9741b63e4470141d39506', 'loadClassLoader'));

$includePaths = require __DIR__ . '/include_paths.php';
$includePaths[] = get_include_path();
set_include_path(implode(PATH_SEPARATOR, $includePaths));

require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInitb81f714672cab81745951e3983f718b7::getInitializer($loader));
call_user_func(\Composer\Autoload\ComposerStaticInit302766cabed9741b63e4470141d39506::getInitializer($loader));

$loader->register(true);

$filesToLoad = \Composer\Autoload\ComposerStaticInitb81f714672cab81745951e3983f718b7::$files;
$filesToLoad = \Composer\Autoload\ComposerStaticInit302766cabed9741b63e4470141d39506::$files;
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
Expand Down
12 changes: 6 additions & 6 deletions vendor/composer/autoload_static.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Composer\Autoload;

class ComposerStaticInitb81f714672cab81745951e3983f718b7
class ComposerStaticInit302766cabed9741b63e4470141d39506
{
public static $files = array (
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
Expand Down Expand Up @@ -3217,11 +3217,11 @@ class ComposerStaticInitb81f714672cab81745951e3983f718b7
public static function getInitializer(ClassLoader $loader)
{
return \Closure::bind(function () use ($loader) {
$loader->prefixLengthsPsr4 = ComposerStaticInitb81f714672cab81745951e3983f718b7::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInitb81f714672cab81745951e3983f718b7::$prefixDirsPsr4;
$loader->prefixesPsr0 = ComposerStaticInitb81f714672cab81745951e3983f718b7::$prefixesPsr0;
$loader->fallbackDirsPsr0 = ComposerStaticInitb81f714672cab81745951e3983f718b7::$fallbackDirsPsr0;
$loader->classMap = ComposerStaticInitb81f714672cab81745951e3983f718b7::$classMap;
$loader->prefixLengthsPsr4 = ComposerStaticInit302766cabed9741b63e4470141d39506::$prefixLengthsPsr4;
$loader->prefixDirsPsr4 = ComposerStaticInit302766cabed9741b63e4470141d39506::$prefixDirsPsr4;
$loader->prefixesPsr0 = ComposerStaticInit302766cabed9741b63e4470141d39506::$prefixesPsr0;
$loader->fallbackDirsPsr0 = ComposerStaticInit302766cabed9741b63e4470141d39506::$fallbackDirsPsr0;
$loader->classMap = ComposerStaticInit302766cabed9741b63e4470141d39506::$classMap;

}, null, ClassLoader::class);
}
Expand Down
Loading

0 comments on commit b23d839

Please sign in to comment.