Fix to Replicate “Magic Quotes” and “Register Globals” in PHP 5.4+
It pains me to write this post in 2013, but after doing some client work recently, I’ve found that these issues still actually exist in the wild, so these “fixes” may potentially help people.
A little history… Back in the day, PHP had a feature called “Magic Quotes”
(magic_quotes_gpc
). When it was on, all '
(single-quote), "
(double
quote), \
(backslash) and NULL
characters in the $_POST
, $_GET
and
$_COOKIE
arrays would be escaped with a backslash automatically. Like many
things in PHP, it was a bad idea. But it was often turned on by default, so
people became dependent on it. Specifically, they would do things like this:
mysql_query("INSERT INTO records SET name = '{$_POST['name']}'");
That statement has a number of things wrong with it (using a deprecated MySQL
API is among them), but the biggest issue is that it assumes $_POST['name']
has been properly escaped to prevent SQL injection. That assumption is
(dangerously) based on PHP’s “Magic Quotes” being enabled. Unfortunately,
there’s still lots of terrible legacy code like this out there. This type of
thing fell out of practice 8+ years ago, but you’d be surprised how long sites
will stick around, untouched.
“Magic Quotes” was depreciated in PHP 5.3.0 (2009) and was dropped completely in
PHP 5.4.0 (2012). I recently had to move a client’s (very old) PHP site to a new
server running PHP 5.4. The code depended on “Magic Quotes” being enabled. Since
that was now impossible, lots of things broke. Refactoring the code was,
unfortunately, not an option. Instead, I had to implement the quick hack below.
As long as this is placed in a globally included file before any processing is
done (e.g. – the database connection file), it’ll replicate the
magic_quotes_gpc
functionality and add slashes to the $_POST
and $_GET
arrays (you could also do this with $_COOKIE
, if you’d like).
// This replicates magic_quotes_gpc in PHP 5.4+
foreach($_POST as $key => $val){
$_POST[$key] = addslashes($val);
}
foreach($\_GET as $key => $val){
$_GET[$key] = addslashes($val);
}
Believe me, I’m not proud of this solution — or even the fact that I’m dealing with sites this old. But if you run into the same problem, you now have a possible fix.
While I’m at it, if you need to replicate register_globals
(I hope you don’t),
here’s a snippet for doing that. This will take the values in your $_POST
and
$_GET
arrays and make them available as independent global variables (e.g. –
$_POST['name']
will be accessible as $name
).
// This replicates register_globals in PHP 5.4+
foreach (array_merge($_GET, $_POST) as $key => $val) {
global $$key;
$$key = addslashes($val);
}
Disclaimer: I’d strongly suggest refactoring your code over using any of these hacks. Only use them if you must.