18 Mar

Missed Vulnerabilities in Easy WP SMTP Show Why Checking Over Security Fixes is Important

One of the things that we do to make sure we are providing our customers with the best data on vulnerabilities in WordPress plugins they might be using is that we monitor the changelog for plugins to spot the possibility that vulnerabilities have been fixed and then we try to figure if the changes actually involve a vulnerability. In doing that we have often found that vulnerabilities have only been partially fixed or haven’t been fixed at all. That is the case with the plugin Easy WP SMTP, which has 300,000+ active installations according to wordpress.org, where we reviewed the changes made before the discoverer had put out a post on the vulnerabilities.

The changelog for the latest release of that is:

Fixed potential vulnerability in import\export settings.

When we went to look at the changes made in that version we found that in fact there were multiple exploitable vulnerabilities, so the “potential” part comes off strange. It gets stranger when you consider that, as we later ran across, the discoverer of this NinTechNet reports that one of the vulnerabilities was already being exploited before being fixed:

The vulnerability, found in version v1.3.9, has been exploited by hackers since at least March 15, and was caught by our Web Application Firewall for WordPress, NinjaFirewall (WP Edition).

(Update (3/19/2019): If you need a WordPress website that is hacked through this vulnerability (or some other) we do proper hack cleanups of WordPress websites over at our main business and they include a free lifetime subscription to our Plugin Vulnerabilities service.)

Their post also includes this:

We reported the vulnerability to the authors and the wordpress.org team on March 15 and a new version 1.3.9.1 was released on March 17.

What their post is missing are any details of what the fix was (in fact the post is quite light on details beyond how to exploit one of the vulnerabilities), which turns out to be important since some of the vulnerabilities were due to multiple security failures and a quick look at the changes showed that one of those hasn’t been fixed in multiple places.

As an example of that let’s take a look at PHP object injection vulnerability in the plugin, which we already detailed for our customers.

Details

Based on it its name, not surprisingly, the function admin_init() in the plugin runs during admin_init:

30
add_action( 'admin_init', array( $this, 'admin_init' ) );

That means that anything that runs in that function can be accessed by those not logged in to WordPress.

In the previous version in that function the following code was not restricted in any way:

301
302
303
304
305
306
307
308
309
310
$is_import_settings = filter_input( INPUT_POST, 'swpsmtp_import_settings', FILTER_SANITIZE_NUMBER_INT );
if ( $is_import_settings ) {
	$err_msg = __( 'Error occurred during settings import', 'easy-wp-smtp' );
	if ( empty( $_FILES[ 'swpsmtp_import_settings_file' ] ) ) {
	echo $err_msg;
	wp_die();
	}
	$in_raw = file_get_contents( $_FILES[ 'swpsmtp_import_settings_file' ][ 'tmp_name' ] );
	try {
	$in = unserialize( $in_raw );

If the POST input “swpsmtp_import_settings” is set to “1” the contents of the FILE input “swpsmtp_import_settings_file” will be unserialized, which permits PHP object injection to occur.

In the new version access to that code is restricted to users with the “manage_options” capability, which normally only Administrators have:

252
if ( current_user_can( 'manage_options' ) ) {

What is still missing is protection against cross-site request forgery (CSRF), which is a vulnerability where an attacker can cause someone else to take an action they didn’t intend to. That type of issue was a key part of a vulnerability fixed in the latest version of WordPress. In this case if you can get a logged in Administrator to access a page you control you can cause the PHP object injection to occur.

What also probably should be done is to switch from using serialize()/unserialize() to json_encode()/json_decode() for handling exporting/importing the plugin’s settings.

For us it is hard to understand how no one else noticed that, since CSRF protection should obviously have been in place for that code (if had been then the exploited vulnerability likely wouldn’t have been).

Update (3/19/2019): We should have mentioned yesterday that the code that runs right after the first usage on unserialize() also involves another vulnerability exploitable through CSRF, as it updates the plugin’s settings:

311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
		    if ( empty( $in[ 'data' ] ) ) {
			echo $err_msg;
			wp_die();
		    }
		    if ( empty( $in[ 'checksum' ] ) ) {
			echo $err_msg;
			wp_die();
		    }
		    if ( md5( $in[ 'data' ] ) !== $in[ 'checksum' ] ) {
			echo $err_msg;
			wp_die();
		    }
		    $data = unserialize( $in[ 'data' ] );
		    update_option( 'swpsmtp_options', $data[ 'swpsmtp_options' ] );
		    update_option( 'swpsmtp_pass_encrypted', $data[ 'swpsmtp_pass_encrypted' ] );
		    if ( $data[ 'swpsmtp_pass_encrypted' ] ) {
			update_option( 'swpsmtp_enc_key', $data[ 'swpsmtp_enc_key' ] );
		    }
		    update_option( 'smtp_test_mail', $data[ 'smtp_test_mail' ] );

That could be abused by an attacker to redirect all of the email sent out by the website to them (and say used to gain access to password reset emails).

Not a One Off

The lack of CSRF protection isn’t limited to just that code related to importing settings for the plugin. For example, the plugin has an AJAX accessible function for clearing its log file, which lacks that as well.

Here is the entirety of the code that runs when accessing that function:

364
365
366
367
368
369
370
371
function clear_log() {
if ( $this->log( "Easy WP SMTP debug log file\r\n\r\n", true ) !== false ) {
	echo '1';
} else {
	echo 'Can\'t clear log - log file is not writeable.';
}
die;
}

Checking for CSRF vulnerabilities in admin functionality has been part of security reviews we do as part of our main service (and separately) since the beginning, so the lack of its usage in this plugin is something we would have caught during one of those. (The other causes of the vulnerabilities in this plugin would have also been caught during multiple other checks that we do related to checking code that runs admin_init, checking for PHP object injection vulnerabilities, and option update vulnerabilities.)

Full Disclosure

Due to the moderators of the WordPress Support Forum’s continued inappropriate behavior we are full disclosing vulnerabilities in protest until WordPress gets that situation cleaned up, so we are releasing this post and then only trying to notify the developer through the WordPress Support Forum. You can notify the developer of this issue on the forum as well. Hopefully the moderators will finally see the light and clean up their act soon, so these full disclosures will no longer be needed (we hope they end soon). You would think they would have already done that since a previously full disclosed vulnerability was quickly on hackers’ radar, but it appears those moderators have such disdain for the rest of the WordPress community that their continued ability to act inappropriate is more important that what is best for the rest of the community.

Proof of Concept

With our plugin for testing for PHP object injection installed and activated, the following proof of concept will cause the message “PHP object injection has occurred.” be shown, when logged in as an Administrator.

Make sure to replace “[path to WordPress]” with the location of WordPress and have the contents of the file being included be ‘O:20:”php_object_injection”:0:{}’.

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/admin-post.php" method="POST" enctype="multipart/form-data">
<input type="hidden" name="swpsmtp_import_settings" value="1" />
<input type="file" name="swpsmtp_import_settings_file" />
<input type="submit" value="Submit" />
</form>
</body>
</html>

Concerned About The Security of the Plugins You Use?

When you are a paying customer of our service you can suggest/vote for the plugins you use to receive a security review from us. You can start using the service for free when you sign up now.

7 thoughts on “Missed Vulnerabilities in Easy WP SMTP Show Why Checking Over Security Fixes is Important

  1. Hey, you write “was caught by our Web Application Firewall for WordPress, NinjaFirewall (WP Edition)”.
    It’s possible to use the Plesk Firewall to prevent
    these vulnerabilitys?

    Or NinjaFw only see this error nur doesnt Stop it?

    • That wasn’t something we wrote, that was a quote from the developer of NinjaFirewall, so we would take that with a grain of salt (with a previous vulnerability they discovered, we found that the protection they claimed against to offer was at least incomplete).

      The best approach to protect against these vulnerabilities would be to keep your plugins up to date all times, get warned about known unfixed vulnerabilities using something like our service, and having the security of plugins you used reviewed.

      When it comes to firewalls we wouldn’t recommend using something like that unless there is evidence, preferably from independent testing, that it provides effective protection.

    • @Jens Plesk Firewall (or any other general server firewall) is unlikely to catch this because it is not a Web Application Firewall. For that you should seek to use something like the post author’s Ninja WAF. (I would have previously said to try Sucuri as well, but there is a post on this blog that suggests this may be a poor choice.) You could also try WordFence WAF for WordPress but be aware that in my experience it has been responsible for causing MySQL problems due to corrupting its own database more than a few times.

  2. Thanks guys, that’s a valuable piece of information.
    I’m absolutely blown away by the fact it was published as a 0.0.0.1 version increment, and without a proper CVE even. We couldn’t figure out what the vector of attack was, and somehow skimmed over the Easy SMTP update on the plugins’ list as “probably just a minute tweak to the sources”. Only further analysis of POST data made it clear to us.
    Cheers.

    • While we would recommend reviewing the log files before moving to doing things like looking at changelogs (and that is the order we do things when we properly clean up hacked WordPress websites), you would have been helped if you used our service since we not only would have listed what vulnerabilities had been in installed plugins, but provided an estimation of the likelihood of exploitation that would have further pointed you in the right direction without having to dig through changelogs (since we already do that as part of collecting our data).

      • We already knew there was a sort of injection into options table from logs, but weren’t sure from which plugin. The bit that saved us in the end was POST data logging on the reverse proxy end that I enabled after hacker’s first successful breach, as otherwise it just appeared as A post to admin end, but didn’t tell exactly what the payload was. It hammers server a bit more, but turns out to be invaluable in case of WP (or probably any webapp for that matter).
        I’ve found your post only after actually discovering the faulty plugin, but nevertheless you spared me from doing more research on the subject and looking for other possible vectors from that darn plugin.
        So big kudos, and definitely agreed your service looks interesting. I’ve brought it to clients’ spotlight already.

  3. Pingback: 0day w pluginie WordPressa do wysyłania maili

Leave a Reply

Your email address will not be published. Required fields are marked *