I had a client recently who had unfortunately been attacked by one of those fun PHP insertion hacks, often associated with outdated installations of WordPress (fixed in later versions). Regardless it left the client with around 800 files with an identical block of code at the very beginning of the file.
I won’t get into treating the problem (the security weakness) here, instead I am just talking about how I treated the symptom, the malicious code that was inserted. I did a quick Google search and came up with a recursive directory/file listing function that suited my needs perfectly. Credit for this code is given in the below code.
NOTES:
It is very important to note that this code may not work for you perfectly out of the box as I created it for a specific task, for instance this script will ONLY search *.php and *.html files unless you add other extensions or remove that routine all together.
FUNCTION CODE:
/*
--------------------------------------------------------------------------------
PHP SCRIPT
---
For: Amyst Design Company
By: Doug Linsmeyer, Amyst Design Company
Date: 2009-09-24
Revised:
Version: 0
--------------------------------------------------------------------------------
Purpose:
Recusively search all files and sub-folders for a regex pattern and
replace it with another strong and resave the file.
Some original code by mallsop.com on 05/2001.
Updated by mallsop.com on 04/2009.
PHP 5 or better. Tested ok on unix hosting box.
GPL License.
Some snippets from other php code posted online.
--------------------------------------------------------------------------------
*/
function scanDirectory($needle, $replacement, $dirid, $dirname, $path, $spaces)
{
while ( ($file = readdir($dirid)) != false )
{
if ( ($file != '.') && ($file != '..') )
{
$dirname_full = $dirname.'/'.$file;
if ( is_dir($dirname_full) && ($file != 'cgi-bin') )
{
$return .= $spaces . '<b>' . $file . '</b><br />' . "\n";
$dirid_next = opendir($dirname_full); // was just $file
$newpath = $path.'/'.$file;
$nextspaces = $spaces.' ';
$return .= scanDirectory($needle, $replacement, $dirid_next, $dirname_full, $newpath, $nextspaces);
$nextspaces = '';
closedir($dirid_next);
$dirname_here = '';
}
else
{
$break = explode('.', $file);
$file_ext = $break[1];
$file_ext_lowercase = strtolower($file_ext);
if ( ($file_ext_lowercase == 'php') OR ($file_ext_lowercase == 'html') )
{
$code = file_get_contents($dirname . '/' . $file);
if ( preg_match($needle, $code) )
{
$matchtext = '<span style="color:#cc0000;">...Found.</span>';
$newcode = preg_replace($needle, $replacement, $code);
file_put_contents($dirname . '/' . $file, $newcode);
$matchtext .= '...Fixed.';
}
else
{
$matchtext = '<span style="color:#00cc00;">...Not Found</span>';
}
$return .= $spaces . $file . $matchtext . '<br />' . "\n";
}
}
}
}
return ($return);
}
IMPLEMENTATION:
$needle = '/\<\? [\/\*]{4}eval\(base64_decode\(\'[A-Za-z0-9]+\'\)\); \?\>/';
$replacement = '';
$dirname_start = '/home/wildchi2/public_html/';
$dirid_start = opendir($dirname_start);
$dirname_here = basename($dirname_start);
$spaces = ' ';
$output = scanDirectory($needle, $replacement, $dirid_start, $dirname_start, $dirname_here, $spaces);
?>
<html>
<head>
<title>Recursive File Search and Replace Utility by Amyst Design, 2009</title>
</head>
<body>
<h1>Recursive Search and Replace Utility.</h1>
<h2>By Amyst Design Co.</h2>
<h3>Searching all files in the <?=$dirname_start?> folder.</h3>
<?=$output?>
<h3>Finished.</h3>
</body>
</html>