9.16.2008

Error reporting

Error reporting is a good thing, right? It gives you valuable insight into why your application failed. It gives you useful information such as what happened and where it happened. This information is essential in order to fix the bug. However, you might not be the only one who is interested in knowing why your application failed. By giving the user the details from the errors and/or exceptions thrown by PHP you are giving valuable insight into how your application works. Apart from the source itself, this is one of the most valuable intelligence the attacker might gather when looking for vulnerabilities in your application. Therefore, you should never output the error to the screen when your application is running in a production environment (the live setting in which your application runs when it is available for public use). In your development environment (e.g. on your local computer) it is perfectly fine to output the errors because there are nobody but you to see them and it is easier than having to check an error log when something fails unexpectedly.

So what should you do when you have launched your new killer app? Bugs might still appear and you need the before-mentioned information in order to fix them. What you can do, and should do, is write the errors into a log file. Actually, PHP does insert all errors into a log file on the server by default. However, if you are on shared hosting then you will most likely not have access to that file and it will therefore be necessary to write it into your own file. There are a couple of php.ini directives that are relevant to our problem:

* display_errors this directive controls whether PHP errors should be sent to the screen. In a production environment this should always be turned off.
* error_reporting this directive controls which errors that should be reported. You should set this to E_ALL and you should fix all issues that appear by doing this.
* log_errors this controls whether errors should be logged to a file. I would recommend that you always turn this on.
* error_log this is the path of the file errors should be written to. This is only applies if log_errors is turned on obviously.

Here is how I would recommend that you configure the before-mentioned four directives:
Table 2.1: Recommended Configuration Directive name: Production: Development:
display_errors Off On
error_reporting E_ALL E_ALL
log_errors On On
error_log varies varies

How error_log should be configured obviously depends on how your directory structure is setup (more on that later in this tutorial).
2.1. Setting the directives

There are a number of different ways you can set the directives in order to achieve the most secure and efficient error handling as I talked about before. If you already know how to do that then you can skip this section.

First and foremost there is changing the values directly in php.ini. However, this is only possible if you are the administrator of the server so for many people this is not an option.

Apache has some configuration files called .htaccess where you can configure Apache directives for the particular folder (and sub-folders) the file is located in. Some hosts do not allow you to use this, but if you can then the PHP module has a directive called php_flag which allows you to set PHP directives. You simply do it like this:

php_flag directive_name directive_value

Note that you cannot use constants like E_ALL so you will have to use their numeric values. E_ALL's value is currently 8191, but that might change in the future so you should check the new value if you update a major version. You can see the constants regarding error reporting at any time here.

So for our production environment you can do this:

php_flag display_errors off
php_flag error_reporting 8191
php_flag log_errors on
php_flag error_log /home/someone/logs/php_errors.log

A third option is to use to use PHP's ini_set() function. That function takes two arguments: the name of the directive to set and its new value. You can use the constants here. There is a function called error_reporting() which you can use to set the error reporting instead.

No comments: