Register Globals - Just Don't Do It

Posted: 20/01/13

Turn on PHP's register_globals? Jog on, son.

A site I do some occasional maintenance on went off line last week. Upon futher investigation, there was some rather nasty looking PHP code lurking in various files, including the database connector. It was easy to spot because it was causing a parse error which was all over the error log like a rash.

This code comprised an eval statement, wrapped up with various base64 and assocated code. When decoded, it added some javascript tags to the page. Nasty.

Needless to say I ripped the code out and things were back to normal. For about 1/2 an hour. Clearly there's a vulnerability somewhere. My suspicions were that a very old version of PHP 5.3.0 hosted on Windoze XP Home was the culprit, but it was much worse than that.

Scrutinising the Apache logs, I noticed entries like this:


Looking in the common/db.php file, the alarm bells started ringing: the $commonpath variable was getting overwritten by the GET string, with disastrous consequences!

But, but, but, when I checked, PHP's register_globals was set to off. For the benefit of those that don't know, register_globals is a deprecated feature that takes ALL values in your cookies, get, post and session and very nicely translates them into variables of the same name ready for you to do what you like with in your PHP. Handy? yes, Dangerous? You betcha. It's just so easy to have anyone inject values into your code doing this, which is exactly what happened here. The confusing thing was, that this feature was off, and so it should have been having no effect. Then I found this little gem, buried in the config.php:

 // Load EGPCS vars into globals (emulates register_globals = On in php.ini)
!if (!empty($HTTP_ENV_VARS)) while(list($name, $value) = each($HTTP_ENV_VARS)) $$name = $value;
if (!empty($HTTP_GET_VARS)) while(list($name, $value) = each($HTTP_GET_VARS)) $$name = $value;
!if (!empty($HTTP_POST_VARS)) while(list($name, $value) = each($HTTP_POST_VARS)) $$name = $value;
if (!empty($HTTP_COOKIE_VARS)) while(list($name, $value) = each($HTTP_COOKIE_VARS)) $$name = $value;
if (!empty($HTTP_SERVER_VARS)) while(list($name, $value) = each($HTTP_SERVER_VARS)) $$name = $value;

That's right, folks, the "programmer" decided that he/she/it would work round a security restriction by implementing his/her/its own ticking time bomb.

This code was of course ripped out faster than you can say "hack me".