"ini_alter", # Alias of ini_set(), ini_set is preferred "disk_free_space" => "diskfreespace", # Alias of disk_free_space() "PHP_SAPI" => "php_sapi_name", # Alias of constant PHP_SAPI "stream_set_write_buffer" => "set_file_buffer", # Alias of stream_set_write_buffer() ]; $shell_access_functions = array_diff(["exec", "passthru", "proc_close", "proc_get_status", "proc_nice", "proc_open", "proc_terminate", "shell_exec", "system"], $requested_resources['shell_access_whitelist']); $sys_functions = array_diff(["get_current_user", "getmyuid", "getmygid", "getmypid", "getmyinode", "getlastmod", "getenv", "putenv"], $requested_resources['sys_function_whitelist']); $file_functions = array_diff(["chgrp", "chgrp", "lchgrp", "lchown", "link", "linkinfo", "symlink"], $requested_resources['file_function_whitelist']); if ($requested_resources['curl'] === false) { $disable_functions[] = "curl_init"; $disable_functions[] = "curl_exec"; $disable_functions[] = "curl_multi_init"; $disable_functions[] = "curl_multi_exec"; } $disabledWOAliases = array_merge($disable_functions, $shell_access_functions, $sys_functions, $file_functions); $output = '## php.ini' . PHP_EOL . PHP_EOL; $output .= PHP_EOL . "php_value[disable_functions] = \"" . implode(", ", array_merge($disabledWOAliases, $disable_aliases)) . "\""; if ($requested_resources['file_uploads'] === false) { $output .= PHP_EOL . "php_value[file_uploads] = 0"; } if ($requested_resources['allow_url_fopen'] === false) { $output .= PHP_EOL . "php_value[allow_url_fopen] = 0"; } $output .= PHP_EOL . PHP_EOL . '## .user.ini' . PHP_EOL; if ($requested_resources['file_uploads'] === false) { $output .= PHP_EOL . "upload_max_filesize = 1"; } if ($requested_resources['max_input_vars'] != ini_get("max_input_vars")) { $output .= PHP_EOL . "max_input_vars = " . $requested_resources['max_input_vars']; } if ($requested_resources['max_input_nesting_level'] != ini_get("max_input_nesting_level")) { $output .= PHP_EOL . "max_input_nesting_level = " . $requested_resources['max_input_nesting_level']; } if ($requested_resources['post_max_size'] != ini_get("post_max_size")) { $output .= PHP_EOL . "post_max_size = " . $requested_resources['post_max_size']; } $output .= PHP_EOL . PHP_EOL . '## PHPStan Directives' . PHP_EOL . PHP_EOL . " disallowedFunctionCalls:" . PHP_EOL; foreach ($disable_aliases as $to_keep => $disabled) { $output .= ' - function: \'' . $disabled . '()\' message: \'use ' . $to_keep . ' instead\''; } foreach ($disabledWOAliases as $disabled) { $output .= ' - function: \'' . $disabled . '()\''; } return $output; } /** * Registers an additional accessible directory for open_basedir. * * @param string $dir Directory to register. * * @return void */ public function register_accessible_dir(string $dir):void { $this->_open_basedir[] = $dir; } /** * Applies the memory limit setting. * * @return void */ private function _apply_memory_limit():void { if (!isset($this->memory_limit)) { throw new MDJailSecurityOptionNotSetException("It has not been specified, which memory limit the script should hold. Set MD_JAIL->memory_limit = string."); } if (ini_set("memory_limit", $this->memory_limit) === false) { throw new Exception('Failed to change memory_limit to ' . $this->memory_limit); } } /** * Applies the maximum execution time setting. * * @return void */ private function _apply_time_limit():void { if (!isset($this->max_execution_time)) { throw new MDJailSecurityOptionNotSetException("It has not been specified, which maximum execution time the script should hold. Set MD_JAIL->max_execution_time = integer."); } if (set_time_limit($this->max_execution_time) === false) { throw new Exception('Failed to change max_execution_time to ' . $this->max_execution_time); } } /** * Applies basedir restrictions. * * @return void */ private function _apply_basedir_restriction():void { if (empty($this->_open_basedir)) { throw new MDJailSecurityOptionNotSetException("It has not been specified, which memory limit the script should hold. Set MD_JAIL->open_basedir = string."); } if (ini_set("open_basedir", implode(':', $this->_open_basedir)) === false) { throw new Exception('Failed to set open_basedir restrictions'); } } /** * Enforces security options previously set. * * @return void */ public function enforce():void { // Special instructions on CLI, so as to not disturb PHPUnit if (PHP_SAPI === 'cli') { if (!isset($this->memory_limit)) { throw new MDJailSecurityOptionNotSetException("It has not been specified, which memory limit the script should hold. Set MD_JAIL->memory_limit = string."); } if (!isset($this->max_execution_time)) { throw new MDJailSecurityOptionNotSetException("It has not been specified, which maximum execution time the script should hold. Set MD_JAIL->max_execution_time = integer."); } $this->_status = self::STATUS_SPECIFIED; $this->__destruct(); } $this->_apply_memory_limit(); $this->_apply_time_limit(); // Set accessible file paths $this->_apply_basedir_restriction(); $this->_status = self::STATUS_SPECIFIED; $this->__destruct(); } /** * Setup function. Registers a shutdown function that throws an error * if the security specifications have not been made. * * @return void */ public function __construct() { $this->_status = self::STATUS_STARTED; } /** * Destructor. Throws an exception if the settings have not been set. */ public function __destruct() { if ($this->_status !== self::STATUS_SPECIFIED) { echo "Security specifications need to be set."; if (!isset($this->memory_limit)) { echo "Set memory limit"; } if (!isset($this->max_execution_time)) { echo "Set max_execution_time"; } if (empty($this->_open_basedir)) { echo "Set open_basedir"; } throw new MDJailSecurityOptionNotSetException("Security specifications need to be set."); } } }