views:

105

answers:

3

On my website I have a variable called $user_data that contains input from a form. I then show this variable on the user page (via echo).

What is the best method to avoid any security risks with this variable? I use strip_tags(), but it is not enough.

This variable also gets saved to a MySQL database.

+10  A: 

There are two very important things you must do to avoid serious security problems.

  1. You need to escape the user input before putting it in your SQL query. Escaping means escape all the special characters such as '; luckily, there is a function that already does it automatically: mysql_real_escape_string.

    If you don't escape user input nasty things could happen. Imagine that your query is INSERT INTO userdata VALUES ('$user_data'). Now imagine that the user wrote '; DROP DATABASE userdata;.

    If you don't escape it, your query will become: INSERT INTO userdata VALUES (''; DROP DATABASE userdata;'). As you can imagine this is not good: if you have multi statements enabled you can kiss goodbye to your database. This is called an SQL Injection attack.

  2. When you are outputting your variable to the user you also need to properly replace HTML special characters with HTML entities. Luckily, there is a function to do that too: htmlspecialchars(). It will transform the special HTML characters such as < to &lt;.

    This seems to be a problem that is often underestimated, but in reality it's very serious. Imagine if $user_data contains <script>SomeNastyScript()</script>. It could exploit existing vulnerabilities in the browser of your users, or it could send a non-HTTPOnly cookie (that may contain saved passwords) to the attacker, or it could trick the user into writing their password on a form generated through the manipulation of the DOM (possible in javascript), or a lot of other bad things.

    This is called XSS (Cross-site scripting).


Short version

  1. Call mysql_real_escape_string on the string before inserting it into your SQL query (but not when you echo it).

  2. Call htmlspecialchars on the string before displaying it to the user (but not when you put it in the database).

Andreas Bonini
just htmlspecialchars, no more functions?
Happy
Important thing, don't do a `htmlspecialchars()` before inserting data in your database. You need to avoid useless transformations before storing user data.
Colin Hebert
I edited my answer to make it clearer
Andreas Bonini
way more important thing. `'` is not a "special character" but just a delimiter. And escaping is just to distinguish a delimiter from a text. And obviously escaping works with quote delimited strings only and has nothing to do with numbers.
Col. Shrapnel
Thanks man, this is a perfect answer.
Happy
@WorkingHard not that perfect. There are 2 major flaws in it, which will lead you directly to SQL injection. Not just `"user input "` but 1. EVERY string that's going to be quote delimited in the query, no matter i's origin. 2. escape STRINGS only as it would not help with numbers. Numbers need special treatment, as well as identifiers and operators, if any
Col. Shrapnel
+4  A: 

When you're going to output something, strip_tags or htmlspecialchars is fine. I prefer the latter, since you then don't totally destroy <3 and the like that were never meant as HTML tags anyway.

When putting a value directly into a query, mysql_real_escape_string is the appropriate way to escape, or just using PDO and prepared statements.

Of course, it's best to do these escape methods only when you're about to need them, rather than applying both to all variables ever. It's always a pain to have to strip the slashes back out of a MySQL-escaped variable if you want to actually work with it before putting it into the database, and that's no better than PHP4's magic quotes. Similarly, you don't want to turn someone's password of "one<two" into "one&lt;two" before inserting it into the database. (Obviously, you shouldn't be storing plaintext passwords, but the generic example stands.)

Matchu
Good for pointing out `<3`
shamittomar
+2  A: 

There is not a thing called "secureness".
No way to just secure an abstract variable. Everything depends on the scenario.
A condoms commonly used for safety. Would you secure your money with a condom? I suppose - no.
Same here. You'd better distinguish these 2 matters - a database security and displaying security.

Database one is little more complicated than just "Call mysql_real_escape_string". I've described all the rules comprehensively in this answer

Col. Shrapnel