6

I've been working with PHP for some time and I began asking myself if I'm developing good habits.

One of these is what I belive consists of overusing PHP sanitizing methods, for example, one user registers through a form, and I get the following post variables:

$_POST['name'], $_POST['email'] and $_POST['captcha']. Now, what I usually do is obviously sanitize the data I am going to place into MySQL, but when comparing the captcha, I also sanitize it.

Therefore I belive I misunderstood PHP sanitizing, I'm curious, are there any other cases when you need to sanitize data except when using it to place something in MySQL (note I know sanitizing is also needed to prevent XSS attacks). And moreover, is my habit to sanitize almost every variable coming from user-input, a bad one ?

Cristian D
  • 673
  • 5
  • 21
  • 8
    Never trusting user input is one of the best habits to have. Database injection is the obvious reason, but there are a few others. eval() statements, dynamic class creation $x = new $classnamehere(), etc – STLMikey Oct 27 '14 at 21:25
  • 3
    All user input / external input is potentially dangerous, so if -- for example -- you were comparing the captcha value to an internal string, there is some (albeit minuscule) risk that the passed in value could "cheat" and somehow pass the comparison logic. With that said, yes, some input needs sanitizing more than other input, since some data is used in higher-risk scenarios. I would advise sanitizing all user input through some generic function if possible and use MySQLi or PDO to auto-escape any data to fend-off injection risks. – Anthony Oct 27 '14 at 21:29
  • 2
    I believe it's a good habit, infact - I believe that your application should not touch any user inputted data without being sanitized first - I have a class which loops through post/get requests and produces sanitized versions before I can access them – CᴴᵁᴮᴮʸNᴵᴺᴶᴬ Oct 27 '14 at 21:30
  • I'm currently working with MySQLi as I find more closer to what I worked with before (mysql_*). Also, @DannyHearnah, your idea to loop through the entire $_POST data is really good, I'll definitely use it in the future. – Cristian D Oct 27 '14 at 21:32
  • 1
    You should show us the very approach you use for sanitizing those three input variables. The overly generic strip_tags/stripslashes/trim doesn't usually help. (It's often best to think of input filtering as "format constraining" instead). Most PHP web apps suffer from lack of output context escaping. Database string escaping and input normalization are only half the deal. – mario Oct 27 '14 at 21:38
  • If you're using mysqli and prepared statements then I'm not sure sanitisation helps much but I guess it's a good habit – Strawberry Oct 27 '14 at 21:45
  • related: http://stackoverflow.com/a/5863562/731947 – CSᵠ Oct 27 '14 at 21:57

2 Answers2

4

Whenever you store your data someplace, and if that data will be read/available to (unsuspecting) users, then you have to sanitize it. So something that could possibly change the user experience (not necessarily only the database) should be taken care of. Generally, all user input is considered unsafe, but you'll see in the next paragraph that some things might still be ignored, although I don't recommend it whatsoever.

Stuff that happens on the client only is sanitized just for a better UX (user experience, think about JS validation of the form - from the security standpoint it's useless because it's easily avoidable, but it helps non-malicious users to have a better interaction with the website) but basically, it can't do any harm because that data (good or bad) is lost as soon as the session is closed. You can always destroy a webpage for yourself (on your machine), but the problem is when someone can do it for others.

To answer your question more directly - never worry about overdoing it. It's always better to be safe than sorry, and the cost is usually not more than a couple of milliseconds.

Shomz
  • 37,421
  • 4
  • 57
  • 85
4

The term you need to search for is FIEO. Filter Input, Escape Output.

You can easily confound yourself if you do not understand this basic principle.

Imagine PHP is the man in the middle, it receives with the left hand and doles out with the right.

A user uses your form and fills in a date form, so it should only accept digits and maybe, dashes. e.g. nnnnn-nn-nn. if you get something which does not match that, then reject it.

That is an example of filtering.

Next PHP, does something with it, lets say storing it in a Mysql database.

What Mysql needs is to be protected from SQL injection, so you use PDO, or Mysqli's prepared statements to make sure that EVEN IF your filter failed you cannot permit an attack on your database. This is an example of Escaping, in this case escaping for SQL storage.

Later, PHP gets the data from your db and displays it onto a HTML page. So you need to Escape the data for the next medium, HTML (this is where you can permit XSS attacks).

In your head you have to divide each of the PHP 'protective' functions into one or other of these two families, Filtering or Escaping.

Freetext fields are of course more complex than filtering for a date, but never mind, stick to the principles and you will be OK.

Hoping this helps http://phpsec.org/projects/guide/

Cups
  • 6,901
  • 3
  • 26
  • 30
  • Actually you just answered all the questions I had in my head for some time. Now I understood where prepared statements come handy and where escaping is necesarry. Thanks :) – Cristian D Oct 27 '14 at 22:39