I've never programmed in an environment with magic quotes turned on before. Now I'm working on a project where it is. This is how I've been setting up user accepted data situations:
$first_name = $_POST['first_name']
if(!get_magic_quotes_gpc()) {
$first_name = mysql_real_escape_string($first_name);
}
With that filtering, am I still open for SQL injection attacks when magic quotes is enabled?
I'm really only concerned about any kind of SQL injection that will break my queries... Other whitelisting, htmlspecialchar() -ing etc. is in place for other areas.
Looking at some similar SO questions it seems that it's being advised to instead check for magic quotes, run 'stripslashes' on the data if it IS turned on, and then always run the escape function. I'm a little apprehensive to do it this way though because all of the existing code in the site assumes it's on.
Thanks!
Working with a legacy system can be a real PITA - especially with something like PHP which let some pretty egregious insecure code be written in the bad old days.
I think you've actually already answered part of your question:
Looking at some similar SO questions it seems that it's being advised to instead check for magic quotes, run 'stripslashes' on the data if it IS turned on, and then always run the escape function. I'm a little apprehensive to do it this way though because all of the existing code in the site assumes it's on.
I would also try and initiate a code review - find all places where use data is being written or used in database queries, and then replace with the more secure escaping. Eventually, you'll replace all of those squirrelly queries, and be able to turn magic quotes off for good.
If you use mysql_real_escape_string (correctly) there is no risk of SQL injection. That doesn't mean the input will be ok. If your magic quotes settings or any other stuff is set incorrectly, your variable may contain an incorrect value. It is still safe however.
Related
What are the technical reasons that Magic Quotes has been removed from PHP 5.4 ?
From PHP docs
Performance
Performance Because not every piece of escaped data is inserted into a database, there is a performance loss for escaping all this data. Simply calling on the escaping functions (like addslashes()) at runtime is more efficient. Although php.ini-development enables these directives by default, php.ini-production disables it. This recommendation is mainly due to performance reasons.
Is there any other reason why Magic Quotes has been removed from PHP?
this is very well explained why the deprecated in manual by chao
Quoting comment of chao
The very reason magic quotes are deprecated is that a one-size-fits-all approach to escaping/quoting is wrongheaded and downright dangerous. Different types of content have different special chars and different ways of escaping them, and what works in one tends to have side effects elsewhere. Any sample code, here or anywhere else, that pretends to work like magic quotes --or does a similar conversion for HTML, SQL, or anything else for that matter -- is similarly wrongheaded and similarly dangerous.
Magic quotes are not for security. They never have been. It's a convenience thing -- they exist so a PHP noob can fumble along and eventually write some mysql queries that kinda work, without having to learn about escaping/quoting data properly. They prevent a few accidental syntax errors, as is their job. But they won't stop a malicious and semi-knowledgeable attacker from trashing the PHP noob's database. And that poor noob may never even know how or why his database is now gone, because magic quotes (or his spiffy "i'm gonna escape everything" function) gave him a false sense of security. He never had to learn how to really handle untrusted input.
also good read Wikipedia : Magic quotes Criticism
If I turn off magic_quotes in an environment where I did not wrote the code, how can I check if any problems may occur? For what do I have to check? Which functions may not work any more?
When magic_quotes turned on, Magic Quotes automatically performs an addslashes() on all form data submitted. It means that a [\] is placed before every ['], ["], [], or null in the data, so That's nice will be converted to That\'s nice automatically. This all happens before your coding even sees that data, so if you're just passing a string to the next page (not to database) it will print with slashes even though you may not want them at all.
Unfortunately, I don't think there's an easy answer. You'll want to check for any place where you're working directly with user input. If the code is simple enough, you can search for uses of $_GET and $_POST, but without at least a scanning code review, you're unlikely to find everything that way.
One thing I've had break a lot when I turn it off is sql insert/update queries someone had written that contained request parameters they had not properly escaped.
Magic quotes affects incoming data strings. Any place you use $_GET or $_POST or variables of that nature can be affected.
Basically, any place you accept data from the user.
Note: More importantly, you should look through all of your SQL queries and make sure that any input strings are escaped! Otherwise your code will be vulnerable to SQL injection.
magic_quotes_gpc
We all hate it and many servers still use this setting and knowingly enough some provides will argue it's safer but I must disagree.
The question I have is, what would a backslash be needed for?
I want to remove them completely which I can do but I am not sure if they are needed?
EDIT
Other then SQL injection.
magic_quotes_gpc() was provided based on the misguided notion that ALL data submitted to PHP from any external source would be immediately inserted into a database. If you wanted to send that data somewhere OTHER than a database, you had to remove the slashes that PHP just inserted, doubling the work required.
As well, not all databases use slashes for escaping metacharacters. \' is fine in MySQL, but in MS Access, escaping a single quote is actually '' - so not only was PHP doing unecessary work, in many situations, it was doing the work WRONG to begin with.
And then, on top of all that, addslashes (which is basically what magic_quotes_gpc() was calling internally) can't handle all forms of SQL injection attacks, particularly where Unicode is used. addslashes is a glorified form of str_replace("'", "\\'", $string), which works at the ASCII level - plenty of Unicode sequences can look like regular ascii, but get turned into SQL metacharacters after a simplistic addslashes() has wreaked its havoc.
They are for preventing SQL injection exploits, a very serious issue you should read up on if you're going to be coding for the web.
You should look into prepared queries, which is a much better way of avoiding SQL injection.
There is no good reason to have this feature in PHP.
That's why it's officially deprecated and will not exist in future versions.
If there were good reasons to keep it, the developer community would have done so.
They are designed to make us do extra work to remove them. For example, some code in Dokuwiki.
Don't forget about magic_quotes_runtime too.
I made a simple news system with comments using PHP and MySQL, and it worked great on my local Apache server, both on my Fedora 10 machine, and my Windows 7 one. Now I have a problem though, I uploaded it to a web host and it keeps returning all the ' and " as \' and \".
I believe this is either the web host who by automatic adds them for security reasons or that the MySQL is the wrong collation, but I have not been able to resolve it yet, testing multiple MySQL collations.
Here is a example of a query:
mysql_query("INSERT INTO news (title, poster, text, time) VALUES ('$newstitle', '1', '$newstext', '$time')") or die(mysql_error());
$time is time();
$newstitle and $newstext are parsed from $_POST and both are ran through mysql_real_escape_string() before I run the query (I guess this might be the problem, but since it is a part of the security I just don't want to remove it, and since it did not cause problems on my local servers)
As a final note: On my local apache servers I had latin1_swedish_ci which did not work on the web hosts server.
EDIT:
They look like this in the database:
\'\'\'\"\"\"
While on my local ones they didn't have the extra backslash, so it must be the PHP adding it. Is there any way to solve this except adding a function that removes extra backslashes?
These additional backslashes are probably Magic Quotes. Try to disable them or remove them before processing the data.
No, you don't want to run stripslashes(). Rather, set up your server properly.
First, turn off magic_quotes. This means that any data going into your script will have nothing escaped.
Then run mysql_real_escape_string() on the data, that'll add the slashes for the query only, and will store the data in the database without the slashes.
When you load the data again, you'll be good to go and there won't be any backslashes around the quotes.
Edit: As mentioned several times below, and in comments, the correct way to go about this is to disable magic quotes. Had I fully read and comprehended the question before replying, then that would probably have been better ;)
mysql_real_escape_string() will be doing what it says, and escaping the relevant characters within the string. Escaping quotes is done by prefixing them with the escape character (a back-slash in PHP, and many other languages). When you pull the data back from the database, do something like run stripslashes() (see the PHP doc) on the content, to remove the slashes from things like quotes.
Edit: As Gumbo mentioned, it could also be due to Magic Quotes being enabled on the server. You should disable these as per his answer.
Take a look at your magic_quotes settings, and compare them on your servers. Your home servers probably have magic_quotes disabled (as they should be, since Magic Quotes is deprecated in current versions of PHP), and your web host likely has them enabled (which is sadly common). You can use:
<?php echo phpinfo(); ?>
for a quick comparison.
If magic_quotes is new to you, you may want to look into PHP security a bit more before you deploy anything you care about.
Questions containing "magic_quotes"
Your host might have Magic Quotes enabled.
Look at magic_quotes_gpc. You can turn this off via .htaccess and use mysql_real_escape_string().
The real solution is to use prepared statements in your insert queries.
Here's a site with an insert example right at the top.
Prepared Statements in PHP
The benefit is that it's a best practice, and the side-effect is that you no longer have to worry about cleansing the input against SQL injection attacks.
When I send ");-- from an input field to my localhost PHP server, it AUTOMATICALLY converts it to
\");--
It seems great, except that I don't know how trustworthy this behavior is.
Although it seems to avoid SQL injections, my development environment is not the same as the production environment and I'm afraid that the production environment may not have this sort of protection automatically activated...
Why does PHP does this(convert the input without having to use mysql_real_escape_string)? Does it always do it or only with certain extensions? Is it safe to rely on this behavior to prevent SQL injections?
It seems that you have Magic Quotes enabled. But you better disable this option or revert them. mysql_real_escape_string is more secure.
This "feature" of PHP is known as "magic quotes". As 'magic' as they may be, it is extremely bad practice to use them, as they do little more than give a false sense of security. Thankfully they have been removed from PHP 6 (in development).
A more detailed list of criticisms can be found in this Wikipedia article.
The PHP manual describes various ways to disable magic quotes.
You might want to get into talking to the database using an abstraction layer like Zend_Db. For example, if you create a select statement by instantiating a Zend_Db_Select, it would look like this:
//$_GET['thing'] is automatically escaped
$select = $zdb->select()->from('things')->where('name = ?',$_GET['thing']);
$result = $zdb->fetchRow($select->__toString());//__toString generates a really pretty, vendor independent query
//a plain vanilla query would look like this:
$result = $zdb->fetchRow('select * from things where name = ?', $zdb->quote($_GET['thing']);
You have Magic Quotes turned on. The PHP group officially deprecated this function strongly, and strongly discourages relying on it. Ways to disable magic quotes at runtime don't always work, weather you use .htaccess or ini_set() in the script. Calling stripslashes all the time can also become pretty messy.
More details: http://ca3.php.net/magic_quotes