WordPress Newsletter Plugin Multisite Vulnerability

WordPress Newsletter Plugin Vulnerability

I have had the opportunity to work with the WordPress Newsletter Plugin from Tribulant, a plugin that rivals the free MailPress plugin, but with its own twist (and its own pricetag of $54.99 single license, $274.95 unlimited).

The WordPress Newsletter Plugin copy starts out by shouting:

A WordPress newsletter plugin which will, without a doubt, blow your mind away with its feature set…

And it does, after you take a look at one of its core features that they’re proud of:

Both PHP, HTML, CSS and WordPress shortcodes can be put into themes.

Newsletters: Themes Documentation

See anything wrong with that?

How about this in the Theme Editor screen:

You may use PHP code inside themes and any of the shortcodes/variables.

Exactly! PHP!?

The problem

You mean to say that any user with the right permissions, i.e. accesslevel: 10 (User Levels have been deprecated in WordPress 3.0), which stands for Administrator. Well that’s not a problem, right? You may be the only Administrator on your site.

Problems arise when you are NOT the only Administrator. This is especially true in Multisite environments, where you can have an infinite amount of Administrators. Sure, they all have separate tables in the database, and wouldn’t normally see one another’s blogs, they have their own WordPress security contexts. But, what they share is a common PHP user with all its access rights and privileges. Ouch!

So my Multisite users, with the help of WordPress Newsletter Plugin can in fact do this:

Wordpress Newsletter Plugin Problem

…and viola, with compliments:

Wordpress Newsletter Plugin Problem

This means that everything the current PHP user has access to is compromised, including the database.

Additionally, with the latest 3.3.8 version updates, Tribulant was kind enough to let Administrators give out power to any other user roles:

Full integration with the WordPress roles has been done. You can tick/check the roles which are allowed to have access to each individual section of the Newsletter plugin. Additionally, any custom roles added with a WordPress roles plugin like the WordPress Members plugin will show up here as well, dynamically.

So one wrong tick… tock… and boom!

Also, if an attacker (hacker) gains access to any of the admin accounts in WordPress (via privilege escalation, cookie hijacking, etc.), then with the help of WordPress Newsletter Plugin he/she can drop the database, read server files (exec( 'cat /etc/htpasswd' );), in short, run any PHP code and potentially compromise the whole system. Of course if any of your plugin and theme files are writable by the PHP user then they’ll go for your Plugins or Theme Editor, which also supports PHP, which is why you always need to set the right permissions and make sure your PHP user is not almighty. Maybe it’s time for WordPress to remove the Theme and Plugin Editor (at least disable it by default via a CONSTANT), too.

The solution

A closer inspection of course reveals that the WordPress Newsletter Plugin uses eval() in its code. TLDR:

The eval() language construct is very dangerous because it allows execution of arbitrary PHP code. Its use thus is discouraged…

wp-mailinglist-ajax.php:208:	echo eval('?>' . $content . '<?php ');
wp-mailinglist.php:315:		echo eval('?>' . $theme -> content . '<?php ');
wp-mailinglist.php:1052:	echo eval('?>' . $content . '<?php ');
wp-mailinglist-plugin.php:2863:	echo eval('?>' . stripslashes($theme -> content) . '<?');

This is version 3.8.7, line numbers may not match later or previous versions, just search for the evil “eval”. If you’re realizing that your Multisite or even Singlesite (not pointing fingers at the public backend Demo at Tribulant) is at risk right now, replace all those lines with:

wp-mailinglist-ajax.php:208:	echo '?>' . $content . '<?php ';
wp-mailinglist.php:315:		echo '?>' . $theme -> content . '<?php ';
wp-mailinglist.php:1052:	echo '?>' . $content . '<?php ';
wp-mailinglist-plugin.php:2863:	echo '?>' . stripslashes($theme -> content) . '<?';

You’ll end up with unevaluated PHP tags in your theme, those have to be replaced with HTML or shortcodes instead. And then wait with hope until these insecurities are removed at the source, and we can get back to enjoying the great plugin in a Multisite environment. Until then, I remain disappointed and strongly discourage irresponsible use of WordPress Newsletter with its powerful but dangerous features.

A long-term solution

I think that there is absolutely no point or advantage of giving front-end PHP capabilities. Things are bound to go horribly wrong, PHP is unforgiving and has no place in-mid HTML-based e-mail themes. In my opinion, shortcodes only are the proper way to go. If users are tech-savvy and confident enough to use PHP in WordPress Newsletter mail themes, they will have no problem wrapping their PHP into shortcode callbacks inside functions.php, and value the much-needed layer of security.

The conclusion

The Newsletter: PHP Variables documentation (if you ever get to read that before buying) does not warn you if you’re planning on running this on Multisite. In fact, nowhere in their front-facing pitch does it say that this script is in any way dangerous for Multisite. And I would have never realized in time if not for some other problems (hardcoded header images in the default templates) which I was to solve, making me look into these themes in the first place and seeing <?php tags… and then I fell off my chair.

Tribulant

I’ve written to Tribulant’s support 72 hours ago, warning them of my forthcoming vulnerability disclosure, which would have affected their public Demo (it’s been patched now). Tribulant’s CEO Antonie Potgieter has approached and handled the matter with utmost responsibility, acknowledged the flaw of the PHP feature and was ready to discuss potential solutions. A new version of WordPress Newsletter Plugin will be rolling out which does away (at least by default) with the evil evals. Antonie stated that the company will make it a point to release a patch by the end of this week.

Update February 18th, 2012

An update has been published, getting rid of the dangerous functionality. I haven’t checked it out yet, will do so in a couple of days.