This is a discussion on Security in PHP within the PHP Programming forums, part of the Web Development category; In this example, each form that is submitted is expected to have a form variable named form that uniquely identifies ...
| |||||||
| Register | FAQ | Members List | Calendar | Mark Forums Read |
| |||
| In this example, each form that is submitted is expected to have a form variable named form that uniquely identifies it, and security.inc has a separate case to handle the data filtering for that particular form. An example of an HTML form that fulfills this requirement is as follows: HTML Code: <form action="/receive.php" method="POST"> <input type="hidden" name="form" value="login" /> <p>Username: <input type="text" name="username" /></p> <p>Password: <input type="password" name="password" /></p> <input type="submit" /> </form>
__________________ With, J. Jeyaseelan Everything Possible Last edited by Jeyaseelansarc : 04-11-2008 at 10:55 PM. |
| Sponsored Links |
| |||
| An array named $allowed is used to identify exactly which form variables are allowed, and this list must be identical in order for the form to be processed. Control flow is determined elsewhere, and process.inc is where the actual data filtering takes place.
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| A good way to ensure that security.inc is always included at the top of every PHP script is to use the auto_prepend_file directive.
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| It is important to take a whitelist approach to your data filtering, and while it is impossible to give examples for every type of form data you may encounter, a few examples can help to illustrate a sound approach.
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| To validate the email we can use as PHP Code:
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| The following example ensures that $num is an integer: PHP Code:
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| Each of the previous examples make use of an array named $clean. This illustrates a good practice that can help developers identify whether data is potentially tainted. You should never make a practice of validating data and leaving it in $_POST or $_GET, because it is important for developers to always be suspicious of data within these superglobal arrays. In addition, a more liberal use of $clean can allow you to consider everything else to be tainted, and this more closely resembles a whitelist approach and therefore offers an increased level of security. If you only store data in $clean after it has been validated, the only risk in a failure to validate something is that you might reference an array element that doesn't exist rather than potentially tainted data.
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| Once a PHP script begins processing, the entire HTTP request has been received. This means that the user does not have another opportunity to send data, and therefore no data can be injected into your script (even if register_globals is enabled). This is why initializing your variables is such a good practice.
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| error_reporting This directive sets the level of error reporting desired. It is strongly suggested that you set this to E_ALL for both development and production.
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| display_errors This directive determines whether errors should be displayed on the screen (included in the output). You should develop with this set to On, so that you can be alerted to errors during development, and you should set this to Off for production, so that errors are hidden from the users (and potential attackers).
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| log_errors This directive determines whether errors should be written to a log. While this may raise performance concerns, it is desirable that errors are rare. If logging errors presents a strain on the disk due to the heavy I/O, you probably have larger concerns than the performance of your application. You should set this directive to On in production.
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| error_log This directive indicates the location of the log file to which errors are written. Make sure that the web server has write privileges for the specified file. Having error_reporting set to E_ALL will help to enforce the initialization of variables, because a reference to an undefined variable generates a notice.
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| Each of these directives can be set with ini_set(), in case you do not have access to php.ini or another method of setting these directives.
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| A good reference on all error handling and reporting functions is in the PHP manual: PHP: Errors and Logging - Manual
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| PHP 5 includes exception handling. For more information, see: PHP: Exceptions - Manual
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| In order to appreciate the necessity of data filtering, consider the following form located (hypothetically speaking) at http://example.org/form.html: HTML Code: <form action="/process.php" method="POST"> <select name="color"> <option value="red">red</option> <option value="green">green</option> <option value="blue">blue</option> </select> <input type="submit" /> </form>
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| Imagine a potential attacker who saves this HTML and modifies it as follows: HTML Code: <form action="http://example.org/process.php" method="POST"> <input type="text" name="color" /> <input type="submit" /> </form> This makes it very easy to eliminate any client-side restrictions, whether HTML form restrictions or client-side scripts intended to perform some rudimentary data filtering. In this particular example, $_POST['color'] is not necessarily red, green, or blue. With a very simple procedure, any user can create a convenient form that can be used to submit any data to the URL that processes the form.
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| Hi, You can write your own client instead of manually entering requests with telnet. The following example shows how to perform the HTTP request using PHP: PHP Code:
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| The following best practices can mitigate the risk of XSS (cross-site scripting): Filter all external data. As mentioned earlier, data filtering is the most important practice you can adopt. By validating all external data as it enters and exits your application, you will mitigate a majority of XSS concerns. Use existing functions Let PHP help with your filtering logic. Functions like htmlentities(), trip_tags(), and utf8_decode() can be useful. Try to avoid reproducing something that a PHP function already does. Not only is the PHP function much faster, but it is also more tested and less likely to contain errors that yield vulnerabilities. Use a whitelist approach. Assume data is invalid until it can be proven valid. This involves verifying the length and also ensuring that only valid characters are allowed. For example, if the user is supplying a last name, you might begin by only allowing alphabetic characters and spaces. Err on the side of caution. While the names O'Reilly and Berners-Lee will be considered invalid, this is easily fixed by adding two more characters to the whitelist. It is better to deny valid data than to accept malicious data. Use a strict naming convention. As mentioned earlier, a naming convention can help developers easily distinguish between filtered and unfiltered data. It is important to make things as easy and clear for developers as possible. A lack of clarity yields confusion, and this breeds vulnerabilities.
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| There are a few things you can do to protect your applications against CSRF: Use POST rather than GET in forms. Specify POST in the method attribute of your forms. Of course, this isn't appropriate for all of your forms, but it is appropriate when a form is performing an action, such as buying stocks. In fact, the HTTP specification requires that GET be considered safe. Use $_POST rather than rely on register_globals. Using the POST method for form submissions is useless if you rely on register_globals and reference form variables like $symbol and $quantity. It is also useless if you use $_REQUEST. Do not focus on convenience. While it seems desirable to make a user's experience as convenient as possible, too much convenience can have serious consequences. While "one-click" approaches can be made very secure, a simple implementation is likely to be vulnerable to CSRF. Force the use of your own forms. The biggest problem with CSRF is having requests that look like form submissions but aren't. If a user has not requested the page with the form, should you assume a request that looks like a submission of that form to be legitimate and intended?
__________________ With, J. Jeyaseelan Everything Possible |