From 5130477e4bbe77522adfccacc72182d4ae417d7d Mon Sep 17 00:00:00 2001 From: Joshua Ramon Enslin Date: Thu, 12 Nov 2020 00:12:11 +0100 Subject: [PATCH] Add static function to propose security settings Close #3, see #4 --- MD_JAIL.php | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 2 deletions(-) diff --git a/MD_JAIL.php b/MD_JAIL.php index 983f871..01470bb 100644 --- a/MD_JAIL.php +++ b/MD_JAIL.php @@ -38,6 +38,93 @@ final class MD_JAIL { */ public string $memory_limit; + /** + * Static function providing an advisory on how to harden the php.ini or + * .user.ini. + * + * @param array{shell_access_whitelist: string[], sys_function_whitelist: string[], file_function_whitelist: string[], file_uploads: bool, allow_url_fopen: bool, max_input_vars: integer, max_input_nesting_level: integer, curl: bool} $requested_resources Requested resources. + * + * @return string + */ + public static function check_server_setup(array $requested_resources):string { + + # ini_set("open_basedir", __DIR__ . "/../../"); + + $disable_functions = [ + "dl", # Loads a PHP extension at runtime + "opcache_get_status", # Gets opcache status + "phpinfo", # For obvious reasons + "parse_ini_file", # For obvious reasons + "show_source", "highlight_file", # Aliases; serve the content of a PHP file + "php_uname", # Returns information about the operating system PHP is running on + "phpcredits", # Credits page of PHP authors + "php_strip_whitespace", # Return PHP source with stripped comments and whitespace + "popen", "pclose", # Similar to fopen, but capable of shell access + "virtual", # Perform an Apache sub-request + ]; + + $disable_aliases = [ + "ini_set" => "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 . "php_value[upload_max_filesize] = 1"; + } + if ($requested_resources['max_input_vars'] != ini_get("max_input_vars")) { + $output .= PHP_EOL . "php_value[max_input_vars] = " . $requested_resources['max_input_vars']; + } + if ($requested_resources['max_input_nesting_level'] != ini_get("max_input_nesting_level")) { + $output .= PHP_EOL . "php_value[max_input_nesting_level] = " . $requested_resources['max_input_nesting_level']; + } + + $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. * @@ -87,6 +174,7 @@ final class MD_JAIL { * Applies basedir restrictions. * * @return void + */ private function _apply_basedir_restriction():void { if (empty($this->_open_basedir)) { @@ -97,7 +185,6 @@ final class MD_JAIL { } } - */ /** * Enforces security options previously set. @@ -124,7 +211,7 @@ final class MD_JAIL { $this->_apply_time_limit(); // Set accessible file paths - // $this->_apply_basedir_restriction(); + $this->_apply_basedir_restriction(); $this->_status = self::STATUS_SPECIFIED; $this->__destruct();