Skip to content
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

Fix regression that discloses file path in some errors #1280

Merged
merged 7 commits into from Feb 6, 2018

Conversation

vboctor
Copy link
Member

@vboctor vboctor commented Feb 3, 2018

This was introduced as part of refactoring error handler and it happens with some errors even when show_detailed_errors is set to OFF.

Fixes #23925

@vboctor vboctor self-assigned this Feb 3, 2018
@vboctor vboctor force-pushed the error_handler_path_disclosure branch from 2e3701c to 67e28b5 Compare February 3, 2018 08:08
This was introduced as part of refactoring error handler and it happens
with some errors even when show_detailed_errors is set to OFF.

Fixes #23925
@vboctor vboctor force-pushed the error_handler_path_disclosure branch from 67e28b5 to d5d85f1 Compare February 3, 2018 08:17
@@ -247,11 +247,16 @@ function error_handler( $p_type, $p_error, $p_file, $p_line, array $p_context )

$t_error_description = nl2br( $t_error_description );

# Make sure the file path is not disclosed via exception details
$t_error_description = str_replace( config_get_global( 'absolute_path' ), '.../', $t_error_description );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have

define ('DIRECTORY_SEPARATOR', "/");
$g_absolute_path = dirname( __FILE__ ) . DIRECTORY_SEPARATOR;

Can't check myself at the moment, did you try if it works on Windows?

Should the path be removed if ON == config_get_global( 'show_detailed_errors' )?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I initially had the code to only show the path when show_detailed_errors is ON. But I then removed this code since I think it is not worth having the extra checks. The real value is the relative path.

I don't have a Windows environment setup at the moment.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can test on Windows when I'm in the office on Monday.

@dregad
Copy link
Member

dregad commented Feb 3, 2018

I'm also concerned about the robustness of the proposed str_replace()-based solution. It works for sure on unix-like environments with a standard MantisBT installation, but what about the case where the admin customized the folder locations in config_inc.php ? Regardless of the directory separator, there are bound to be cases where a simple replacement won't do the trick.

I thought about using the file item in the exception's first stack trace entry instead of $g_absolute_path as string to replace, but it this still does not sound very solid.

IMO, PHP errors are not meant to be displayed to end users; I believe it would be preferable and safer to display a generic error, while writing the actual message and stack trace in the system log - at least when $g_show_detailed_errors = OFF.

@vboctor
Copy link
Member Author

vboctor commented Feb 3, 2018

Will look into having our exception displayed, but PHP exceptions or exceptions that didn't originate from Mantis show a generic message (e.g. internal error, while logging the proper error). If show detailed errors is ON, then we will always show exception. Will refine the approach as I look further on the code.

Will remove path replacement.

@dregad
Copy link
Member

dregad commented Feb 3, 2018

Cheers. Please note that I will probably not have the opportunity to review/test your revised fix until tomorrow evening (~22:00 CET) as I won't be at home the whole day. I'll do my best to do it as soon as possible, so you can release 2.11 as planned, but if I can't manage I'd rather postpone the release by a few days.

@vboctor
Copy link
Member Author

vboctor commented Feb 4, 2018

I have implemented an alternative fix which:

  • Logs php errors.
  • Don't display php exception messages in UI or API.

Copy link
Member

@dregad dregad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: I only tested from the GUI, not from SOAP or REST API.

Sorry to insist, but I really think that when $g_show_detailed_errors is ON, we should provide the error message in the GUI as a convenience to administrators and developers, as per patch below.

Other review comments follow.

diff --git a/core/error_api.php b/core/error_api.php
index b0c1517..265fd5a 100644
--- a/core/error_api.php
+++ b/core/error_api.php
@@ -175,6 +175,8 @@ function error_handler( $p_type, $p_error, $p_file, $p_line, array $p_context )
        }
    }
 
+   $t_show_detailed_errors = config_get_global( 'show_detailed_errors' ) == ON;
+
    # Force errors to use HALT method.
    if( $p_type == E_USER_ERROR || $p_type == E_ERROR || $p_type == E_RECOVERABLE_ERROR ) {
        $t_method = DISPLAY_ERROR_HALT;
@@ -203,12 +205,15 @@ function error_handler( $p_type, $p_error, $p_file, $p_line, array $p_context )
        case E_USER_ERROR:
            if( $p_error == ERROR_PHP ) {
                $t_error_type = 'INTERNAL APPLICATION ERROR';
-               $t_error_description = '';
 
                global $g_exception;
-               $t_stack_as_string = error_stack_track_as_string();
-               $t_error_to_log =  $g_exception->getMessage() . "\n" . $t_stack_as_string;
+               $t_error_description = $g_exception->getMessage();
+               $t_error_to_log =  $t_error_description . "\n" . error_stack_track_as_string();
                error_log( $t_error_to_log );
+
+               if( !$t_show_detailed_errors ) {
+                   $t_error_description = '';
+               }
            } else {
                $t_error_type = 'APPLICATION ERROR #' . $p_error;
                $t_error_description = error_string( $p_error );
@@ -259,7 +264,7 @@ function error_handler( $p_type, $p_error, $p_file, $p_line, array $p_context )
        if( DISPLAY_ERROR_NONE != $t_method ) {
            echo $t_error_type . ': ' . $t_error_description . "\n";
 
-           if( ON == config_get_global( 'show_detailed_errors' ) ) {
+           if( $t_show_detailed_errors  ) {
                echo "\n";
                error_print_stack_trace();
            }
@@ -342,7 +347,7 @@ function error_handler( $p_type, $p_error, $p_file, $p_line, array $p_context )
                }
                echo '</div>';
 
-               if( ON == config_get_global( 'show_detailed_errors' ) ) {
+               if( $t_show_detailed_errors ) {
                    echo '<p>';
                    error_print_details( $p_file, $p_line, $p_context );
                    echo '</p>';

$t_error_to_log = $p_exception->getMessage() . "\n" . $t_stack_as_string;
error_log( $t_error_to_log );

return $p_response->withStatus( HTTP_STATUS_INTERNAL_SERVER_ERROR )->withJson( $t_data );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it normal to return ->withJson( $t_data ) which still contains the exception's message ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed code to include it only if show detailed errors is ON.

*/
function error_print_stack_trace() {
$t_stack = error_stack_trace();
function error_stack_track_as_string( $p_exception = null ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be error_stack_trace_as_string, no ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed typo.

$t_stack = error_stack_trace( $p_exception );

if( php_sapi_name() == 'cli' ) {
echo error_stack_track_as_string( $p_exception );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

error_stack_trace_as_string

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed typo.

* @param Exception|null $p_exception The exception to print stack trace for. Null will check last seen exception.
*/
function error_print_stack_trace( $p_exception = null ) {
$t_stack = error_stack_trace( $p_exception );
Copy link
Member

@dregad dregad Feb 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move that assignment after the cli test, just before the foreach loop

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved.

$t_stack = error_stack_trace( $p_exception );

if( php_sapi_name() == 'cli' ) {
echo error_stack_track_as_string( $p_exception );
return;
}

Copy link
Member

@dregad dregad Feb 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment # remove the call to the error handler from the stack trace (a few lines down from here) looks like a leftover from older code which should probably be removed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.

@vboctor
Copy link
Member Author

vboctor commented Feb 6, 2018

@dregad thanks for the review. I applied all your review comments. Let me know if all looks good.

@dregad
Copy link
Member

dregad commented Feb 6, 2018

Looks good, but I didn't test in depth the behavior from the API.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants