1

I was searching a bit and I found a line like this, in PHP;

$mots = mysql_real_escape_string(stripslashes(strip_tags(htmlspecialchars($_POST['mots']))));

I was wondering how much of this was really necessary to protect a $_POST entry as good as possible.

Thanks

Yannick Bloem
  • 147
  • 2
  • 4
  • 12
  • 4
    `$_POST` is where the data comes from. What protection you apply depends on *where you put the input*, not where it comes from. – Quentin Sep 15 '13 at 13:32
  • 9
    That particular example code, however, is largely nonsensical. It looks like someone threw together a bunch of functions that are sometimes useful for dealing with escaping user input without understanding what they actually do. – Quentin Sep 15 '13 at 13:33
  • 1
    time to watch Inception :) – Wiggler Jtag Sep 15 '13 at 13:34
  • The `mysql_*` functions are **no longer maintained** and shouldn't be used in any new codebase. It is being phased out in favor of newer APIs. Instead you should use [**prepared statements**](https://www.youtube.com/watch?v=nLinqtCfhKY) with either [PDO](http://php.net/pdo) or [MySQLi](http://php.net/msqli). – tereško Sep 15 '13 at 14:18
  • http://stackoverflow.com/questions/60174/how-can-i-prevent-sql-injection-in-php – Andy Lester Sep 15 '13 at 14:20
  • +! What Quentin said. This line of code is a great big “I Don't Know What I'm Doing” warning sign. – bobince Sep 15 '13 at 15:46

3 Answers3

0

Really only mysql_real_escape_string is necessary, if you are planning to use $mots with sql in any way, as this protects from SQL injection.

Of course this depends on how you plan on using $mots. Remote file inclusion, a method that allows people to give their own php code for your server to execute, is based on manipulating a variable that will force the script to do something you didn't intend it to. This usually happens when code in a variable is included, rather than something being directly included.

E.g. include($mots), instead of include(config.php).

Tiago
  • 1,984
  • 1
  • 21
  • 43
  • Even `include($mots.'.php')` or `include('/my/safe/path/'.$mots.'.php')` won't stop remote file inclusion. Be very careful with this type of include. – TecBrat Sep 15 '13 at 13:40
  • @TecBrat Please elaborate on how you can perform *remote* file inclusion on the second example. – Gumbo Sep 15 '13 at 13:53
  • @Gumbo assume your site allows uploading of pictures. Assume the attacker uploads a PHP script instead, and succeeds. It is now in `/pics/evil.php`. Assume your script is in `/scripts/good.php`. If '$mots' reads '../pics/evil', this will expand to '../pics/evil.php' which will be found and evil is evaluated. – user268396 Sep 15 '13 at 13:59
  • @user268396 That’s still local. – Gumbo Sep 15 '13 at 14:00
  • just feed $mots a URL ending with a question mark,the .php is just added to the included url as an argument. if $mots = "http://example.com/?", the joined url would become: http://example.com/?.php – Tiago Sep 15 '13 at 14:01
  • ?includeme=../../../../../../../../../../../../../proc/self/environ%0 – TecBrat Sep 15 '13 at 14:01
  • @Gumbo. Yes it is, but that doesn't matter as the evil.php script can download code and execute it through include... – user268396 Sep 15 '13 at 14:03
  • @TecBrat that's still local file inclusion – Tiago Sep 15 '13 at 14:03
  • @TecBrat Pretty elegant. – Gumbo Sep 15 '13 at 14:03
  • @Gumbo It does not matter if evil is local or not. Once that file is executed, the hacker can do anything you can do. – TecBrat Sep 15 '13 at 14:04
  • @user268396 for that to work, you would still need to be able to upload or create the evil.php script in the first place. Servers don't have a malicious script by default. To do this, the attacker either needs access to your server, or a remote code execution or remote file inclusion exploit – Tiago Sep 15 '13 at 14:04
  • I learned the hard way about proc/self/envrion. I won't give the details here, because I don't want to help the hackers. Trust me. It will let a hacker execute malicious code. (I tried it myself on my own server to prove that I understood **HOW** I got hacked one time.) – TecBrat Sep 15 '13 at 14:07
  • @TecBrat It does matter if you don’t have a way to exploit it like doing the same on a Windows system. – Gumbo Sep 15 '13 at 14:07
  • 1
    @Gumbo TecBrat is right, you can use proc/self/environ to execute malicious code. But the point is, you shouldn't allow the user to provide a variable used for an inclusion. That's too dynamic, and will end in an exploit. – Tiago Sep 15 '13 at 14:08
0

The title of your question could be the basis of a book. (It probably already is, many times over) But if you are trying to prevent SQL injection, Use PDO with prepared queries (and parameter binding). This eliminates the risk of SQL injection.

user268396
  • 11,576
  • 2
  • 31
  • 26
TecBrat
  • 3,643
  • 3
  • 28
  • 45
  • @user268396 Thanks for the edit. I thought parameter binding was implied when I said "prepared queries", but it's better to be precise. – TecBrat Sep 15 '13 at 13:54
0

Sanitizing user data

What is necessary when it comes to sanitizing data - specifically, in this case, user input data - depends on a multitude of criteria including (but not limited to) the following:

  1. The type of data expected (e.g. string, integer, binary)
  2. Where the data is to be stored (e.g. database, text file)
  3. How the data is to be used (e.g. displayed back to users, server side calculations)
  4. Well, you get the gist...

Expected data type

The expected data type is highly important when it comes to sanitizing user input as such it can make it very easy or more complicated to sanitize.

Typical expected input types would be:

  1. Text
  2. Integer
  3. Decimal
  4. Binary

In the event that the input is simply an integer or decimal number you can easily sanitize by simply making sure that the input is converted to the expected data type.

In the event of a text expected input you are likely to want to escape or strip certain characters/strings to prevent against things like XSS and SQL injection.

In the event of binary data being input you are going to want to make sure that the data is safe and may wish to run a scan for malicious code and also set correct user permissions for the file to prevent code running on your server. Like with text you may also need to escape certain characters.

Storage location

Storage location also impacts what sanitization is necessary.Taking the example of database vs file:

When entering data into a database you need to escape certain characters to protect your system from people attempting SQL injections conversely, when not using a database you aren't using SQL so protecting specifically against SQL injection is not required.

However, that doesn't mean you can be relaxed when not saving to a database. Saving to files can also lead to malicious code being uploaded and steps should be taken to prevent files that have been uploaded or created to store information from being executable on the server. (This isn't limited to code like where you are specifically allowing upload of a file:

<input type="file" name="uploadFile">

it also applied to for example:

file_put_contents($uploaded_data);

Data use

The purpose of allowing the user to input data is also going to play a role in deciding what protection you need to apply to the user input. While input can be used for many different reasons the main (or most common) reasons are likely to be:

  1. To be displayed back to users (e.g. forum posts, comments, images)
  2. To be used in calculations on site (e.g. calorie counters, insurance quotes)

If the data is to be displayed back to the user you need to think about protection from attacks like XSS as well as stopping from visually defacing your site; both of which can be carried out by injecting tags such as: <script>...</script>

On the other hand if the data is not going to be shown back to users in it's current form then XSS etc. is likely to be somewhat irrelevant.

When to sanitize/format

Sanitization of data should be taken care of before you do anything with it server side that could be affected by dodgy code (e.g. before inserting into a database).

You might chose to sanitize just before you use the data or you may prefer to sanitize code as soon as you start your script. This though is largely down to personal preference and the use case of the system in question.

However, there is often debate on when to run functions like htmlspecialchars (i.e. before uploading to database vs before displaying to the user). This again, is down to personal preference and how you are using the data however there are pros and cons to both methods - which I won't elaborate too much on.

However, if you store the user data to the database as raw (but safe) you are then free to change how you sanitize data across time. Where as if you start storing data after using functions like htmlspecialchars and stip_tags etc. you are removing/altering some data from the input that you might decide at a later date you want to allow/include only to realise that you already lost the data. For example:

strip_tags will by default strip all tags from the input which might seem like a good idea at the moment but further down the line, you might decide that actually want to allow some tags like <b> or <i> - but they are no longer present in any inputs that have already been saved.

Of course, if you are using your own mark up or bb (or similar) for formatting then strip_tags etc before saving to a database would be perfectly reasonable. Similarly if you only want to store plain text then stripping everything that isn't plain would also be reasonable. Again, it depends on your use case...


Your code

See comments for a simple explanation of what each function does.

$mots = mysql_real_escape_string( //Escapes certain characters to 'sanitize' for input to database
        stripslashes( //Removes any escape slashes added by default in $_POST
            strip_tags( //Removes any tags present in the text e.g. <b></b>
                htmlspecialchars( //Coverts some charachters like £ to html codes like &pound;
                    $_POST['mots']
                )
            )
        )
    );

Problems

The most glaring problem with your code is the order in which you are applying the functions. stip_tags should always come before htmlspecialchars (or any other function that will encode characters). The reason for this is simple:

$_POST['userinput'] = "<b>Some user input</b>"; //Input uploaded from form
echo strip_tags($_POST['userinput']);
    //Ouputs: Some user input

echo htmlspecialchars($_POST['userinput'], ENT_QUOTES, 'UTF-8');
    //Output: &lt;b&gt;Some user input&lt;/b&gt;

echo strip_tags(htmlspecialchars());
    //Output: &lt;b&gt;Some user input&lt;/b&gt;

In the above code example you can see that if you run htmlspecialchars before strip_tags the < and > symbols are converted to their respective html codes and are not stripped... So essentially, strip_tags is useless. However, if you run it first then you will strip the tags as required and encode any other miscellaneous special chars.

Steven
  • 6,053
  • 2
  • 16
  • 28