However, staying secure is not that simple - you need to know all the limits and caveats of your tools, because sometimes they promise you something but do not deliver - as it is in case of magic quotes functionality.
Magic quotes
PHP magic_quotes_gpc are sometimes recommended as a protection from SQL injection .When this ini setting is on, all GET/POST/COOKIE variables are automatically run through addslashes() function, basically escaping all quote characters with "\".All is good
Let's look at an example, where that protection would work:<?php // some admin login functionality $logged_in = mysql_query("SELECT 1 FROM users WHERE login='admin' AND password=sha1('" . $_POST['password'] . "')"); // process $logged_in
When magic_quotes_gpc are ON injecting the PASSWORD variable won't work. A simplest attack vector "' OR 1=1 -- " would transform to
SELECT 1 FROM users WHERE login='admin' AND password=sha1('\' OR 1=1 -- ')That's a perfectly escaped SQL query, nothing can get injected. magic_quotes_gpc escape the dangerous single quote for us. So - goodbye SQL injection? WRONG!
Magic quotes only insert a backslash before a few characters, nothing more. That protects you from SQL injection only in some particular cases like above and only by coincidence. To prove that, let's analyze the following script.
So much for magic...
<?php // display a single post based on id $post_data = mysql_query("SELECT title, content FROM posts WHERE post_id={$_GET['id']}"); // display $postThe same "' OR 1=1 -- " transforms to invalid query:
SELECT title, content FROM posts WHERE post_id= \' OR 1 = 1 --
and if you have display_errors ON, you just made the attacker very happy with your database details outputted right before his eyes. Even if you don't, there still is a possiblity of blind sql injection.
But what if an attacker set id parameter to one of these:
- 1 AND (SELECT COUNT(*) from another table_name) BETWEEN 0 AND 100
- -10000 union select user_password from users where user_login=CHAR(97,100,109,105,110) (admin)
In this case a single mysql query parameter that was left unprotected could lead to your whole database content dumped to the attacker (I'm not kidding - see sqlmap and try for yourself).
Know your context
The fundamental problem with magic_quotes_gpc is that they know nothing about the context. They don't know if you're using the data to insert it into MySQL, Oracle, or if you're writing to a file. Maybe you're sending it through SOAP or displaying it in HTML? Or maybe all of it. They just don't have enough information, only you know it. Escaping values depends on a context in which they are used. You should disable magic quotes now also for the following reasons:- they mangle your data before you get the chance to reach it and can lead to double escaping,
- most frameworks expect them to be off, and if they're enabled, try to undo these changes at bootstrap,
- they're deprecated in PHP 5.3 and will be removed in PHP 6.
- to output to a HTML - use htmlspecialchars()
- to escape a string in MySQL - use mysql_real_escape_string().
- to escape a string in Postgresql - use pg_escape_string()
- When you are expecting an integer in SQL query - simply cast to int
- ALWAYS use prepared statements when querying databases.
Have any comments on the subject to share? Please do so, this is my first security-related post and I'd like to hear your opinion.