Best way to defend against mysql injection and cross site scripting

15,109

Solution 1

Just doing a lot of stuff that you don't really understand, is not going to help you. You need to understand what injection attacks are and exactly how and where you should do what.

In bullet points:

  • Disable magic quotes. They are an inadequate solution, and they confuse matters.
  • Never embed strings directly in SQL. Use bound parameters, or escape (using mysql_real_escape_string).
  • Don't unescape (eg. stripslashes) when you retrieve data from the database.
  • When you embed strings in html (Eg. when you echo), you should default to escape the string (Using htmlentities with ENT_QUOTES).
  • If you need to embed html-strings in html, you must consider the source of the string. If it's untrusted, you should pipe it through a filter. strip_tags is in theory what you should use, but it's flawed; Use HtmlPurifier instead.

See also: What's the best method for sanitizing user input with PHP?

Solution 2

The best way against SQL injection is to bind variables, rather then "injecting" them into string. http://www.php.net/manual/en/mysqli-stmt.bind-param.php

Solution 3

Don’t! Using mysql_real_escape_string is enough to protect you against SQL injection and the stropslashes you are doing after makes you vulnerable to SQL injection. If you really want it, put it before as in:

function madSafety($string)
{
    $string = stripslashes($string);
    $string = strip_tags($string);
    $string = mysql_real_escape_string($string);
    return $string;
}

stripslashes is not really useful if you are doing mysql_real_escape_string.

strip_tags protects against HTML/XML injection, not SQL.

The important thing to note is that you should escape your strings differently depending on the imediate use you have for it.

When you are doing MYSQL requests use mysql_real_escape_string. When you are outputing web pages use htmlentities. To build web links use urlencode

As vartec noted, if you can use placeholders by all means do it.

Solution 4

This topic is so wrong!

You should NOT filter the input of the user! It is information that has been entered by him. What are you going to do if I want my password be like: '"'>s3cr3t<script>alert()</script>

Filter the characters and leave me with a changed password, so I cannot even succeed in my first login? This is bad.

The proper solution is to use prepared statements or mysql_real_escape_string() to avoid sql injections and use context-aware escaping of the characters to avoid your html code being messed up.

Let me remind you that the web is only one of the ways you can represent the information entered by the user. Would you accept such stripping if some desktop software do it? I hope your answer is NO and you would understand why this is not the right way.

Note that in different context different characters has to be escaped. For example, if you need to display the user first name as a tooltip, you will use something like:

<span title="{$user->firstName}">{$user->firstName}</span>

However, if the user has set his first name to be like '"><script>window.document.location.href="http://google.com"</script> what are you gonna do? Strip the quotes? This would be so wrong! Instead of doing this non-sense, consider escaping the quotes while rendering the data, not while persisting it!

Another context you should consider is while rendering the value itself. Consider the previously used html code and imagine the user first name be like <textarea>. This would wrap all html code that follows into this textarea element, thus breaking up the whole page.

Yet again - consider escaping the data depending on the context you are using it in!

P.S Not really sure how to react on those negative votes. Are you, people, actually reading my reply?

Share:
15,109
Drew
Author by

Drew

#SOreadytohelp

Updated on June 07, 2022

Comments

  • Drew
    Drew almost 2 years

    At the moment, I apply a 'throw everything at the wall and see what sticks' method of stopping the aforementioned issues. Below is the function I have cobbled together:

    function madSafety($string)
    {
    
    $string = mysql_real_escape_string($string);
    $string = stripslashes($string);
    $string = strip_tags($string);
    return $string;
    
    }
    

    However, I am convinced that there is a better way to do this. I am using FILTER_ SANITIZE_STRING and this doesn't appear to to totally secure.

    I guess I am asking, which methods do you guys employ and how successful are they? Thanks