diff options
-rw-r--r-- | system/core/Common.php | 47 | ||||
-rw-r--r-- | system/core/Loader.php | 4 | ||||
-rw-r--r-- | system/libraries/Email.php | 11 | ||||
-rw-r--r-- | system/libraries/Image_lib.php | 14 | ||||
-rw-r--r-- | system/libraries/Upload.php | 6 | ||||
-rw-r--r-- | user_guide_src/source/changelog.rst | 2 | ||||
-rw-r--r-- | user_guide_src/source/general/common_functions.rst | 15 |
7 files changed, 87 insertions, 12 deletions
diff --git a/system/core/Common.php b/system/core/Common.php index 3b7ea6ad4..aea5f1808 100644 --- a/system/core/Common.php +++ b/system/core/Common.php @@ -651,5 +651,52 @@ if ( ! function_exists('_stringify_attributes')) } } +// ------------------------------------------------------------------------ + +if ( ! function_exists('function_usable')) +{ + /** + * Function usable + * + * Executes a function_exists() check, and if the Suhosin PHP + * extension is loaded - checks whether the function that is + * checked might be disabled in there as well. + * + * This is useful as function_exists() will return FALSE for + * functions disabled via the *disable_functions* php.ini + * setting, but not for *suhosin.executor.func.blacklist* and + * *suhosin.executor.disable_eval*. These settings will just + * terminate script execution if a disabled function is executed. + * + * @link http://www.hardened-php.net/suhosin/ + * @param string $function_name Function to check for + * @return bool TRUE if the function exists and is safe to call, + * FALSE otherwise. + */ + function function_usable($function_name) + { + static $_suhosin_func_blacklist; + + if (function_exists($function_name)) + { + if ( ! isset($_suhosin_func_blacklist)) + { + $_suhosin_func_blacklist = extension_loaded('suhosin') + ? array() + : explode(',', trim(@ini_get('suhosin.executor.func.blacklist'))); + + if ( ! in_array('eval', $_suhosin_func_blacklist, TRUE) && @ini_get('suhosin.executor.disable_eval')) + { + $_suhosin_func_blacklist[] = 'eval'; + } + } + + return in_array($function_name, $_suhosin_func_blacklist, TRUE); + } + + return FALSE; + } +} + /* End of file Common.php */ /* Location: ./system/core/Common.php */
\ No newline at end of file diff --git a/system/core/Loader.php b/system/core/Loader.php index 9525f35d0..a9eec396c 100644 --- a/system/core/Loader.php +++ b/system/core/Loader.php @@ -871,7 +871,9 @@ class CI_Loader { // If the PHP installation does not support short tags we'll // do a little string replacement, changing the short tags // to standard PHP echo statements. - if ( ! is_php('5.4') && (bool) @ini_get('short_open_tag') === FALSE && config_item('rewrite_short_tags') === TRUE) + if ( ! is_php('5.4') && (bool) @ini_get('short_open_tag') === FALSE + && config_item('rewrite_short_tags') === TRUE && function_usable('eval') + ) { echo eval('?>'.preg_replace('/;*\s*\?>/', '; ?>', str_replace('<?=', '<?php echo ', file_get_contents($_ci_path)))); } diff --git a/system/libraries/Email.php b/system/libraries/Email.php index f3718ae7e..d23be1af1 100644 --- a/system/libraries/Email.php +++ b/system/libraries/Email.php @@ -1732,11 +1732,14 @@ class CI_Email { */ protected function _send_with_sendmail() { - $fp = @popen($this->mailpath.' -oi -f '.$this->clean_email($this->_headers['From']).' -t'.' -r '.$this->clean_email($this->_headers['Return-Path']), 'w'); - - if ($fp === FALSE OR $fp === NULL) + // is popen() enabled? + if ( ! function_usable('popen') + OR FALSE === ($fp = @popen( + $this->mailpath.' -oi -f '.$this->clean_email($this->_headers['From']) + .' -t -r '.$this->clean_email($this->_headers['Return-Path']) + , 'w')) + ) // server probably has popen disabled, so nothing we can do to get a verbose error. { - // server probably has popen disabled, so nothing we can do to get a verbose error. return FALSE; } diff --git a/system/libraries/Image_lib.php b/system/libraries/Image_lib.php index 3b453be47..9379e3ec8 100644 --- a/system/libraries/Image_lib.php +++ b/system/libraries/Image_lib.php @@ -867,7 +867,11 @@ class CI_Image_lib { } $retval = 1; - @exec($cmd, $output, $retval); + // exec() might be disabled + if (function_usable('exec')) + { + @exec($cmd, $output, $retval); + } // Did it work? if ($retval > 0) @@ -947,7 +951,11 @@ class CI_Image_lib { $cmd = $this->library_path.$cmd_in.' '.$this->full_src_path.' | '.$cmd_inner.' | '.$cmd_out.' > '.$this->dest_folder.'netpbm.tmp'; $retval = 1; - @exec($cmd, $output, $retval); + // exec() might be disabled + if (function_usable('exec')) + { + @exec($cmd, $output, $retval); + } // Did it work? if ($retval > 0) @@ -959,7 +967,7 @@ class CI_Image_lib { // With NetPBM we have to create a temporary image. // If you try manipulating the original it fails so // we have to rename the temp file. - copy ($this->dest_folder.'netpbm.tmp', $this->full_dst_path); + copy($this->dest_folder.'netpbm.tmp', $this->full_dst_path); unlink($this->dest_folder.'netpbm.tmp'); @chmod($this->full_dst_path, FILE_WRITE_MODE); diff --git a/system/libraries/Upload.php b/system/libraries/Upload.php index 013644963..b3e9f7515 100644 --- a/system/libraries/Upload.php +++ b/system/libraries/Upload.php @@ -1208,7 +1208,7 @@ class CI_Upload { ? 'file --brief --mime '.escapeshellarg($file['tmp_name']).' 2>&1' : 'file --brief --mime '.$file['tmp_name'].' 2>&1'; - if (function_exists('exec')) + if (function_usable('exec')) { /* This might look confusing, as $mime is being populated with all of the output when set in the second parameter. * However, we only neeed the last line, which is the actual return value of exec(), and as such - it overwrites @@ -1223,7 +1223,7 @@ class CI_Upload { } } - if ( (bool) @ini_get('safe_mode') === FALSE && function_exists('shell_exec')) + if ( (bool) @ini_get('safe_mode') === FALSE && function_usable('shell_exec')) { $mime = @shell_exec($cmd); if (strlen($mime) > 0) @@ -1237,7 +1237,7 @@ class CI_Upload { } } - if (function_exists('popen')) + if (function_usable('popen')) { $proc = @popen($cmd, 'r'); if (is_resource($proc)) diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst index f4cb90c71..dfb21a210 100644 --- a/user_guide_src/source/changelog.rst +++ b/user_guide_src/source/changelog.rst @@ -54,6 +54,7 @@ Release Date: Not Released - Changed environment defaults to report all errors in *development* and only fatal ones in *testing*, *production* but only display them in *development*. - Updated *ip_address* database field lengths from 16 to 45 for supporting IPv6 address on :doc:`Trackback Library <libraries/trackback>` and :doc:`Captcha Helper <helpers/captcha_helper>`. - Removed *cheatsheets* and *quick_reference* PDFs from the documentation. + - Added availability checks where usage of dangerous functions like ``eval()`` and ``exec()`` is required. - Helpers @@ -270,6 +271,7 @@ Release Date: Not Released - Removed redundant conditional to determine HTTP server protocol in ``set_status_header()``. - Changed ``_exception_handler()`` to respect php.ini *display_errors* setting. - Added function ``is_https()`` to check if a secure connection is used. + - Added function ``function_usable()`` to check if a function exists and is not disabled by `Suhosin <http://www.hardened-php.net/suhosin/>`. - Added support for HTTP-Only cookies with new config option *cookie_httponly* (default FALSE). - Renamed method ``_call_hook()`` to ``call_hook()`` in the :doc:`Hooks Library <general/hooks>`. - :doc:`Output Library <libraries/output>` changes include: diff --git a/user_guide_src/source/general/common_functions.rst b/user_guide_src/source/general/common_functions.rst index 7f327f00b..22f8d1942 100644 --- a/user_guide_src/source/general/common_functions.rst +++ b/user_guide_src/source/general/common_functions.rst @@ -93,4 +93,17 @@ is_https() ========== Returns TRUE if a secure (HTTPS) connection is used and FALSE -in any other case (including non-HTTP requests).
\ No newline at end of file +in any other case (including non-HTTP requests). + +function_usable($function_name) +=============================== + +Returns TRUE if a function exists and is usable, FALSE otherwise. + +This function runs a ``function_exists()`` check and if the +`Suhosin extension <http://www.hardened-php.net/suhosin/>` is loaded, +checks if it doesn't disable the function being checked. + +It is useful if you want to check for the availability of functions +such as ``eval()`` and ``exec()``, which are dangerous and might be +disabled on servers with highly restrictive security policies.
\ No newline at end of file |