Local File Inclusion (LFI) Vulnerability in MailPress
One of the things we do to protect our customers from vulnerabilities in WordPress plugins is to monitor our websites for activity indicating that someone is looking to exploit a vulnerability in a plugin. That recently has been allowing us to detect quite a few serious vulnerabilities that it looks like no one else is spotting, so our service is the only one that actual provides you any warning and therefore any protection against them until they are fixed.
Usually by just knowing that a plugin appears to be of interest to hackers we are able to identify a vulnerability that hackers would actually exploit and is likely the vulnerability that they are attempting to exploit. In the latest case we were not able to figure out what that might be due largely to the fact the plugin is so insecure it is hard to narrow down where we might need to look to figure out what it is they are targeting. We did find one vulnerability that is very serious and could be targeted with the plugin in its default state, but it is not a type of vulnerability that is often exploited, so if the plugin is being targeted by hackers there is likely something else out there as well.
The plugin in question is MailPress, which is currently not in the Plugin Directory, which could indicate that some vulnerability in it was already reported to the Plugin Directory and it was subsequently removed due to that. Or it could have been removed for some other reason. Looking at archive.org, the plugin was still in the Plugin Directory as of June 10.
The request we had was a GET request for the file /wp-content/plugins/mailpress/mp-includes/action.php. While it is possible the request was just to check for the existence of the plugin before exploiting the plugin through something else, that file provides access to a lot of insecure code. The file causes WordPress to load and creates a new instance of the plugins’ MP_Actions class:
2 3 4 5 6 7 | // include('../../../../wp-load.php'); // include('../../../../wp-admin/includes/admin.php'); // new MP_Actions(); |
That class is defined in the file /mp-includes/class/MP_Actions.class.php, when it is constructed the person sending the request is given access to the class’ functions and any functions that start “mp_action_”:
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | function __construct() { switch (true) { case ( ( isset($_GET['tg']) ) && !( isset($_POST['action']) || isset($_GET['action']) ) ) : $action = 'tracking'; break; case ( isset($_POST['action']) ) : $action = $_POST['action']; break; case ( isset($_GET['action']) ) : $action = $_GET['action']; break; default : MP_::mp_die(-1); break; } $action = str_replace('-', '_', $action); if ( method_exists($this, $action) ) call_user_func_array( array($this, $action), array() ); do_action('mp_action_' . $action ); } |
A lot of the functions made accessible through that don’t include the proper security checks, so there are lot of code that someone could potentially used for an exploit.
While looking over the code we found one possible vulnerability that is of the type that is frequently exploited, but found that one the plugin’s feature, which was required to be able to exploit, was broken, so the problems with the plugin are not just with its security.
One vulnerability that we found that is exploitable is a local file inclusion (LFI) vulnerability in the function theme_preview() in the class MP_Actions. At the end on the function it takes the value of the GET input “type” and places that in an include statement:
494 495 496 497 | $type = $_GET['type']; $$type = $x->build_mail_content($type); $$type = ('html' == $type) ? $x->process_img($$type, $x->mail->themedir, 'draft') : $$type; include MP_ABSPATH . "mp-includes/html/{$type}.php"; |
Using directory traversal any .php file on the website could be included. That would cause the code in the included file to run, so it could be used load a .php file that is not directly accessible.
Proof of Concept
The following proof of concept will cause the file named lfi.php in the root directory of the WordPress installation to be included.
Make sure to replace “[path to WordPress]” with the location of WordPress.
<html> <body> <form action="http://[path to WordPress]/wp-content/plugins/mailpress/mp-includes/action.php?type=../../../../../lfi" method="POST" > <input type="hidden" name="action" value="previewtheme" /> <input type="submit" value="Submit request" /> </form> </body> </html>