13 Feb 2017

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.

Concerned About The Security of the Plugins You Use?

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

Plugin Security Scorecard Grade for Posts in Page

Checked on September 20, 2024
C

See issues causing the plugin to get less than A+ grade

3 thoughts on “Authenticated Local File Inclusion (LFI) Vulnerability in Posts in Page

  1. Thank you for your report and your commitment to security in the plugin repository.

    You can see the snippets of code mentioned as potentially exploitable in this report on line 186, self::has_theme_template returns a file in the theme directory.

    A user cannot upload a file via Media and have it included here. We require the file to be in the theme folder and, if it’s not there, fall back to the posts_loop_template.php file in the plugin’s directory.

    Again, it is not possible for even an Admin level user to designate a file outside the template directory. When they try, it fails the file exists test (those lines are testing for the template and if found, use it and if not found, use the default) and the default template is loaded instead.

    • For anyone wondering about the previous comment, we were subsequently able to clear up the confusion the developer had about how directory traversal works and a new version that fixes the issue should be out soon.

Leave a Reply

Your email address will not be published.