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.
There are two very important things you must do to avoid serious security problems.
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.
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 <
.
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
Call mysql_real_escape_string
on the string before inserting it into your SQL query (but not when you echo
it).
Call htmlspecialchars
on the string before displaying it to the user (but not when you put it in the database).
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<two" before inserting it into the database. (Obviously, you shouldn't be storing plaintext passwords, but the generic example stands.)
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
You can also do this:
$way = preg_replace('#[^a-z0-9]#i', '',
strip_tags(htmlentities(htmlspecialchars(mysqli_escape_string($db_conx, $_GET['way'])))));