8000 Use sandbox for all included files by jarebear6expepjozn6rakjq5iczi3irqwphcvb · Pull Request #3478 · YOURLS/YOURLS · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Use sandbox for all included files #3478

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
29 changes: 22 additions & 7 deletions includes/Config/Init.php
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,20 @@ public function redirect_ssl_if_needed() {
* @return void
*/
public function include_db_files() {
// Allow drop-in replacement for the DB engine
if (file_exists(YOURLS_USERDIR.'/db.php')) {
require_once YOURLS_USERDIR.'/db.php';
} else {
require_once YOURLS_INC.'/class-mysql.php';
// Attempt to open drop-in replacement for the DB engine else default to core engine
$file = YOURLS_USERDIR . '/db.php';
$attempt = false;
if(file_exists($file)) {
$attempt = yourls_include_file_sandbox( $file );
// Check if we have an error to display
if ( is_string( $attempt ) ) {
yourls_add_notice( $attempt );
}
}

// Fallback to core DB engine
if ( $attempt !== true ) {
require_once YOURLS_INC . '/class-mysql.php';
yourls_db_connect();
}
}
Expand All @@ -159,8 +168,14 @@ public function include_db_files() {
* @return void
*/
public function include_cache_files() {
if (file_exists(YOURLS_USERDIR.'/cache.php')) {
require_once YOURLS_USERDIR.'/cache.php';
$file = YOURLS_USERDIR . '/cache.php';
$attempt = false;
if(file_exists($file)) {
$attempt = yourls_include_file_sandbox($file);
// Check if we have an error to display
if (is_string($attempt)) {
yourls_add_notice($attempt);
}
}
}

Expand Down
10 changes: 6 additions & 4 deletions includes/Database/YDB.php
Original file line number Diff line number Diff line change
Expand Up @@ -157,16 +157,18 @@ public function connect_to_DB() {
*/
public function dead_or_error(\Exception $exception) {
// Use any /user/db_error.php file
if( file_exists( YOURLS_USERDIR . '/db_error.php' ) ) {
include_once( YOURLS_USERDIR . '/db_error.php' );
die();
$file = YOURLS_USERDIR . '/db_error.php';
if(file_exists($file)) {
if(yourls_include_file_sandbox( $file ) === true) {
die();
}
}

$message = yourls__( 'Incorrect DB config, or could not connect to DB' );
$message .= '<br/>' . get_class($exception) .': ' . $exception->getMessage();

yourls_die( yourls__( $message ), yourls__( 'Fatal error' ), 503 );
die();

}

/**
Expand Down
7 changes: 5 additions & 2 deletions includes/functions-debug.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* Add a message to the debug log
*
* When in debug mode ( YOURLS_DEBUG == true ) the debug log is echoed in yourls_html_footer()
* Log messages are appended to $ydb->debug_log array, which is instanciated within class ezSQLcore_YOURLS
* Log messages are appended to $ydb->debug_log array, which is instanciated within class Database\YDB
*
* @since 1.7
* @param string $msg Message to add to the debug log
Expand All @@ -17,7 +17,10 @@ function yourls_debug_log( $msg ) {
yourls_do_action( 'debug_log', $msg );
// Get the DB object ($ydb), get its profiler (\Aura\Sql\Profiler\Profiler), its logger (\Aura\Sql\Profiler\MemoryLogger) and
// pass it a unused argument (loglevel) and the message
yourls_get_db()->getProfiler()->getLogger()->log( 'debug', $msg);
// Check if function exists to allow usage of the function in very early stages
if(function_exists('yourls_debug_log')) {
yourls_get_db()->getProfiler()->getLogger()->log( 'debug', $msg);
}
return $msg;
}

Expand Down
13 changes: 13 additions & 0 deletions includes/functions-deprecated.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,19 @@

// @codeCoverageIgnoreStart

/**
* Plugin activation sandbox
*
* @since 1.8.3
* @deprecated 1.9.2
* @param string $pluginfile Plugin filename (full path)
* @return string|true string if error or true if success
*/
function yourls_activate_plugin_sandbox( $pluginfile ) {
yourls_deprecated_function( __FUNCTION__, '1.9.1', 'yourls_include_file_sandbox');
return yourls_include_file_sandbox($pluginfile);
}

/**
* Return current admin page, or null if not an admin page. Was not used anywhere.
*
8000 Expand Down
5 changes: 4 additions & 1 deletion includes/functions-html.php
Original file line number Diff line number Diff line change
Expand Up @@ -906,7 +906,10 @@ function yourls_page( $page ) {
}

yourls_do_action( 'pre_page', $page );
include_once( YOURLS_PAGEDIR . "/$page.php" );
$load = yourls_include_file_sandbox(YOURLS_PAGEDIR . "/$page.php");
if (is_string($load)) {
yourls_die( $load, yourls__('Not found'), 404 );
}
yourls_do_action( 'post_page', $page );
}

Expand Down
34 changes: 11 additions & 23 deletions includes/functions-plugins.php
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ function yourls_load_plugins() {
$plugins = [];
foreach ( $active_plugins as $key => $plugin ) {
$file = YOURLS_PLUGINDIR . '/' . $plugin;
if ( yourls_is_a_plugin_file($file) && yourls_activate_plugin_sandbox( $file ) === true ) {
if ( yourls_is_a_plugin_file($file) && yourls_include_file_sandbox( $file ) === true ) {
$plugins[] = $plugin;
unset( $active_plugins[ $key ] );
}
Expand Down Expand Up @@ -659,7 +659,7 @@ function yourls_activate_plugin( $plugin ) {
}

// attempt activation.
$attempt = yourls_activate_plugin_sandbox( $plugindir.'/'.$plugin );
$attempt = yourls_include_file_sandbox( $plugindir.'/'.$plugin );
if( $attempt !== true ) {
return yourls_s( 'Plugin generated unexpected output. Error was: <br/><pre>%s</pre>', $attempt );
}
Expand All @@ -673,22 +673,6 @@ function yourls_activate_plugin( $plugin ) {
return true;
}

/**
* Plugin activation sandbox
*
* @since 1.8.3
* @param string $pluginfile Plugin filename (full path)
* @return string|true string if error or true if success
*/
function yourls_activate_plugin_sandbox( $pluginfile ) {
try {
include_once $pluginfile;
return true;
} catch ( \Throwable $e ) {
return $e->getMessage();
}
}

/**
* Deactivate a plugin
*
Expand All @@ -706,12 +690,16 @@ function yourls_deactivate_plugin( $plugin ) {

// Check if we have an uninstall file - load if so
$uninst_file = YOURLS_PLUGINDIR . '/' . dirname($plugin) . '/uninstall.php';
if ( file_exists($uninst_file) ) {
$attempt = yourls_include_file_sandbox( $uninst_file );

// Check if we have an error to display
if ( is_string( $attempt ) ) {
$message = yourls_s( 'Loading %s generated unexpected output. Error was: <br/><pre>%s</pre>', $uninst_file, $attempt );
return( $message );
}

if ( $attempt === true ) {
define('YOURLS_UNINSTALL_PLUGIN', true);
$attempt = yourls_activate_plugin_sandbox( $uninst_file );
if( $attempt !== true ) {
return yourls_s( 'Plugin generated unexpected output. Error was: <br/><pre>%s</pre>', $attempt );
}
}

// Deactivate the plugin
Expand Down
47 changes: 36 additions & 11 deletions includes/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -1065,30 +1065,32 @@ function yourls_fix_request_uri() {
* @return void
*/
function yourls_check_maintenance_mode() {
$file = YOURLS_ABSPATH . '/.maintenance' ;
$dot_file = YOURLS_ABSPATH . '/.maintenance' ;

if ( !file_exists( $file ) || yourls_is_upgrading() || yourls_is_installing() ) {
if ( !file_exists( $dot_file ) || yourls_is_upgrading() || yourls_is_installing() ) {
return;
}

global $maintenance_start;
include_once( $file );
yourls_include_file_sandbox( $dot_file );
// If the $maintenance_start timestamp is older than 10 minutes, don't die.
if ( ( time() - $maintenance_start ) >= 600 ) {
return;
}

// Use any /user/maintenance.php file
if( file_exists( YOURLS_USERDIR.'/maintenance.php' ) ) {
include_once( YOURLS_USERDIR.'/maintenance.php' );
die();
}
$file = YOURLS_USERDIR . '/maintenance.php';
if(file_exists($file)) {
if(yourls_include_file_sandbox( $file ) == true) {
die();
}
}

// Or use the default messages
$title = yourls__( 'Service temporarily unavailable' );
$message = yourls__( 'Our service is currently undergoing scheduled maintenance.' ) . "</p>\n<p>" .
yourls__( 'Things should not last very long, thank you for your patience and please excuse the inconvenience' );
yourls_die( $message, $title , 503 );
$title = yourls__('Service temporarily unavailable');
$message = yourls__('Our service is currently undergoing scheduled maintenance.') . "</p>\n<p>" .
yourls__('Things should not last very long, thank you for your patience and please excuse the inconvenience');
yourls_die( $message, $title, 503 );
}

/**
Expand Down Expand Up @@ -1271,3 +1273,26 @@ function yourls_tell_if_new_version() {
yourls_debug_log( 'Check for new version: '.( yourls_maybe_check_core_version() ? 'yes' : 'no' ) );
yourls_new_core_version_notice(YOURLS_VERSION);
}

/**
* File include sandbox
*
* Attempt to include a PHP file, fail with an error message if the file isn't valid PHP code.
* This function does not check first if the file exists : depending on use case, you may check first.
*
* @since 1.9.2
* @param string $file filename (full path)
* @return string|bool string if error, true if success
*/
function yourls_include_file_sandbox($file) {
try {
if (is_readable( $file )) {
include_once $file;
yourls_debug_log("loaded $file");
return true;
}
} catch ( \Throwable $e ) {
yourls_debug_log("could not load $file");
return sprintf("%s (%s : %s)", $e->getMessage() , $e->getFile() , $e->getLine() );
}
}
2 changes: 1 addition & 1 deletion tests/data/config/yourls-tests-config-sample.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php
/**
* YOURLS Config for local unit tests. Copy this file to yourls-test-config.php
* YOURLS Config for local unit tests. Copy this file to yourls-tests-config.php
*/

/*** YOURLS code base you want to test */
Expand Down
2 changes: 1 addition & 1 deletion tests/tests/plugins/files.php
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ public function test_invalid_plugin_deactivate() {
* @dataProvider get_invalid_code_plugins
*/
public function test_invalid_plugin_does_not_activate($plugin) {
$this->assertNotTrue( yourls_activate_plugin_sandbox( $plugin ) );
$this->assertNotTrue( yourls_include_file_sandbox( $plugin ) );
$this->assertNotTrue( yourls_activate_plugin( $plugin ) );
$this->assertNotTrue( yourls_is_active_plugin( $plugin ) );
}
Expand Down
36 changes: 36 additions & 0 deletions tests/tests/utilities/include_file_sandbox.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

/**
* Test sandboxed file loader
*
* @group functions
* @since 1.9.1
*/

class FileLoader_Test extends PHPUnit\Framework\TestCase {

/**
* Load valid file = true
*/
public function test_load_file_exists() {
$file = YOURLS_TESTDATA_DIR . "/" . rand_str() . ".php";
if( touch("$file") ) {
$this->assertTrue( yourls_include_file_sandbox( $file ) );
unlink("$file");
} else {
$this->markTestSkipped( "Cannot create test '$file");
}
}

/**
* Load missing file = string
*/
public function test_load_file_not_exists() {
$this->assertIsString( yourls_include_file_sandbox( YOURLS_TESTDATA_DIR . "/" . rand_str() . ".php" ) );
}

/**
* For tests to load valid and broken PHP code: see in tests/plugins/files.php
*/

}
0