All we need is an easy explanation of the problem, so here it is.
This question was originally asked in a comment here.
It seems unnecessary to me, but I’ve always been told to “Filter Input, Escape Output”. So, aside from a database (or another form of storage), is there any need to filter inputted data?
How to solve :
I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.
Well, there are going to be differing opinions.
My take is that you should always use it (or, the
filter extension in general). There are at least 3 reasons for this:
Sanitizing input is something you should always do. Since the function gives you this capability there is really no reason to find other ways of sanitizing input. Since it is an extension the filter will also be much faster and most likely safer than most PHP solutions out there, which certainly does not hurt. The only exception is if you need a more specialized filter. Even then you should grab the value using the
FILTER_UNSAFE_RAWfilter (see #3).
There are a lot of goodies in the
filterextension. It can save you hours from writing sanitizing and validation code. Of course, it does not cover every single case, but there is enough so that you can focus more on specific filtering/validating code.
Using the function is very good for when you are debugging/auditing your code. When the function is used you know exactly what the input will be. For example, if you use the
FILTER_UNSAFE_RAWthen you know that it should be treated carefully, and that it can easily cause security problems.
As Sverri M. Olsen says, there are differing opinions on this.
I agree very much with the philosophy Filter Input, Escape Output.
Is filter_input() still necessary if you’re using parameterized queries and htmlspecialchars() before you print any user-supplied data?
Short answer: IMO, No. It’s not necessary, but can be useful in some cases.
filter_input function has many useful filters, and I do use some of them (i.e. FILTER_VALIDATE_EMAIL). The validate filters are useful for validating input. However, IMO, the ones that transform data should only be used on output.
Some people encourage escaping input. Indeed, the examples given on the filter_input manual page seem to encourage this as well.
$search_html = filter_input(INPUT_GET, 'search', FILTER_SANITIZE_SPECIAL_CHARS); $search_url = filter_input(INPUT_GET, 'search', FILTER_SANITIZE_ENCODED);
The only examples are for escaping. That combined with the name of the function (filter_input) seems to suggest that escaping input is good practice. Escaping is necessary, but, IMO, should be done before output, not on input. At least the return values are being stored in appropriately named variables.
I strongly disagree with escaping input. I’ve already come across real world situations where transforming data too early is a problem.
For example, Google Analytics processes input in such a way that is causing my encoded ampersands (%26) to be decoded prior to query parameters being excluded. The result is that I have stats for query parameters that actually don’t even exist in my URLs. See my question regarding this issue that remains unsolved.
You may also want to read Why escape-on-input is a bad idea. Here are some excerpts that I agree with, just in case the article disappears [emphasis in the original].
[…] escape-on-input is just wrong […] it is a layering violation — it mixes an output formatting concern into input handling. Layering violations make your code much harder to understand and maintain, because you have to take into account other layers instead of letting each component and layer do its own job.
You have corrupted your data by default. The system […] is now lying about what data has come in.
Escaping on input will not only fail to deal with the problems of more than one output, it will actually make your data incorrect for many outputs.
PHP used to have a feature called magic quotes. It was an escape-on-input feature that […] caused all kinds of problems. […] According to Lerdorf, the much newer PHP ‘filter’ extension is “magic_quotes done right”. But it still suffers from almost all the problems described here.
So how is the filter extension better than magic quotes (other than the fact that it has many different filters)? The filters cause many of the same issues that magic quotes did.
Here are the coding conventions I use:
- values in $_POST, $_GET, $_REQUEST, etc. should not be escaped and should always be considered unsafe
- values should be validated1 before being written to database or stored in $_SESSION
- values expected to be numeric or boolean should be sanitized2 before being written to database or stored in $_SESSION
- trust that numeric and boolean values from database and $_SESSION are indeed numeric or boolean
- string values should be SQL-escaped before being used directly in any SQL query (non-string values should be sanitized2) or use prepared statements
- string values should be HTML-escaped before being used in HTML output (non-string values should be sanitized2)
- string values should be percent-encoded before being used in query strings (non-string values should be sanitized2)
- use a variable naming convention (such as *_url, *_html, *_sql) to store transformed data
For my purposes here, this is how I define the terms used above.
- to validate means to confirm any assumptions being made about the data such as having a specific format or required fields having a value
- to sanitize means to confirm values are exactly as expected (i.e. $id_num should contain nothing but digits)
In general (there may be some exceptions), I’d recommend the following:
- use validate filters on input
- use sanitize filters on output
- remember TIMTOWDI – For example, I prefer htmlspecialchars() (which has more options) over FILTER_SANITIZE_FULL_SPECIAL_CHARS or FILTER_SANITIZE_SPECIAL_CHARS (which escapes line breaks)
Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂