Coding Horrors: PHP - Magic Quotes
September 28, 2010 by
Christoff Truter
PHP
Coding Horrors
Ah, magic quotes, one of those terrible not thought through PHP anti-features, not to
mention overly blogged about (but hey, hopefully this post can provide some additional
insights on this evil, this abomination to the Lord) - but at least its deprecated as
of PHP 5.3 and will apparently be removed with the fabled coming of PHP 6 (and there
will be no pain and suffering no illness...)
For those of you who came in late - Magic Quotes (like Anakin Skywalker), was initially
intended for good and on a lot of websites it still provides some protection (unknowingly
to some) against the mediocre "SQL Injection" issue - basically it escapes all values
within the GET/POST & COOKIE globals, which automatically makes these strings safer
(not completely safe) to use.
But what is so evil about all of this?
-
Its unnecessary to escape everything, which means an unnecessary performance
sacrifice - its not like everything will always be inserted into/selected from a database.
-
It also becomes rather annoying since we won't even (on the values that actually require
escaping) always do a direct insert into the database either, chances are that we will
display or do some validation on values before inserting it, which means we need to unescape
values an re-escape values - defeating the whole purpose.
The biggest issue, which makes it truly evil
(in my opinion), is the fact that it potentially
screws with portability of scripts, since we can turn the feature on/off.
Let me explain this issue using three scenarios.
Scenario 1:
You're in the process of "building" or rather
(in your case) downloading pieces of code/scripts
that will eventually be your website/ web application.
You download the source code for forum A
(which requires magic quotes), and the sources for
blog B
(which doesn't use magic quotes).
Disabling magic quotes will leave forum A vulnerable, enabling magic quotes will potentially
screw the input/output to blog B.
In this scenario you might at least have the choice to simply download other scripts that don't
require magic quotes, or vice-versa.
Scenario 2:
You start at a new company and inherit the most horrible source code ever conceived and
constructed by mankind.
The developer
(s) that developed
(more like mangled) the code either firmly believed in magic
quotes or didn't know any better.
Forcing you to either continue the downwards spiral
(dev using the same style), or do things
following certain/better standards - forcing you to code around the "cest pool" they like to
call code.
In this scenario you are forced to work with what you've got.
Scenario 3:
You become senior developer at a web dev company with 1000's of custom built sites, 90% of these
sites require magic quotes - you warn the managers and tell them that with the coming of PHP 6
all scripts that use magic quotes will go to hell.
Unfortunately they pretty much ignore you and the next day some clever system administrator
decides to disable magic quotes on all servers - while he/she neglected to make any backups for the
last 10 months.
All of a sudden the phones start to ring wildly and out of control, customers demanding answers
to why you lost all their data.
In this scenario you're screwed...
How do we solve these scenarios?
All over the web you can find tons of "solutions", like the following dangerous snippet
(and invert versions of the script):
function stripslashes_deep(&$value)
{
$value = is_array($value)
? array_map('stripslashes_deep', $value)
: stripslashes($value);
return $value;
}
if((function_exists("get_magic_quotes_gpc") && get_magic_quotes_gpc()) ||
(ini_get('magic_quotes_sybase') && (strtolower(ini_get('magic_quotes_sybase'))!="off")) )
{
stripslashes_deep($_GET);
stripslashes_deep($_POST);
stripslashes_deep($_COOKIE);
}
The preceding snippet basically unescapes values, returning values in a "magic quotes off"
manner - I believe
(hope) that the true reason the author wrote this script is for scenarios
where you can't for some dodgy reason disable magic quotes.
The danger of scripts like this is when you implement them without considering the codebase
you're using - like seen in scenario 1 - 3.
So how
(in my opinion) do we actually solve this issue?
When confronted with legacy code, over which you have no control or have no time to fix
millions of lines of code, the safest bet is to unfortunately keep magic quotes enabled,
data integrity is paramount.
Always write your code to function with & without magic quotes, don't ever rely on magic
quotes but cater for its unfortunate existence, for example:
define('MQ_ENABLED', ((function_exists("get_magic_quotes_gpc") && get_magic_quotes_gpc()) || (ini_get('magic_quotes_sybase') && (strtolower(ini_get('magic_quotes_sybase'))!="off"))));
function value($name)
{
if (isset($_POST[$name]))
{
return (MQ_ENABLED) ? stripslashes($_POST[$name]) : $_POST[$name];
}
return null;
}
Thinking back about the brainwave behind this anti-feature, why stop at Magic Quotes? What
about Magic numbers?
(Prevent our integers from being turned into malicious queries) or all
kinds of "Magic" XSS attack protection - why not just for the hell of it html encode everything
while we think we're being helpful?
The horror!
September 29, 2010 by Christoff Truter
Rasmus Lerdorf on Magic Quotes: "It escapes me"