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.

  • James Byrne

    I got a call from a client yesterday with this same issue and after reading your article was able to produce a simple fix. Thanks for article.

    • http://justinklemm.com/ Justin Klemm

      James, great! Glad the article was useful for you.

  • guest

    Yes, Bluehost just forcibly “upgraded” my site to php 5.4 and it broke all of my code. I was using magic_quotes_gpc = ON in the php.ini and now I’ve got to go re-do everything in emergency mode. Thank you, NOT, PHP and Bluehost.

  • Magicquotes are magical

    Our inhouse production website (in theory not exposed to the outside world) utilizes this “bad idea of magicquotes” and for someone like myself it was invaluable as I’m not a programmer. Not a fan of it being deprecated but I understand given the vulnerabilities in the public. I don’t understand the fix presented here and am having to addslashes and stripslashes to hundreds of lines of code. By the way, Justin, you are the most attractive web geek I’ve ever seen on the internet.