Multiple vulnerabilities fixed in CMP – Coming Soon and Maintenance plugin.

The WordPress CMP – Coming Soon and Maintenance plugin (100k+ active installations) fixed multiple vulnerabilities. Affected versions are 3.7.9 and below and, to some extend, versions 3.8 and 3.8.1 (see Timeline below for more details).

All vulnerabilities are related to the AJAX actions found in the “cmp-coming-soon-maintenance/niteo-cmp.php” script.

Arbitrary Post Read

The plugin registers the cmp_get_post_detail AJAX action and makes it accessible to any user, authenticated or not:

94    add_action( 'wp_ajax_cmp_get_post_detail', array( $this, 'cmp_get_post_detail' ) );
95    add_action( 'wp_ajax_nopriv_cmp_get_post_detail', array( $this, 'cmp_get_post_detail' ) );
...
...
2657  public function cmp_get_post_detail() {
2658	   $id = isset($_POST['id']) ? esc_attr($_POST['id']) : '';
2659	   $size = $this->isMobile ? 'large' : 'large';
2660	   wp_send_json( array(
2661	      'img'   => get_the_post_thumbnail( $id, $size ),
2662	      'date'  => get_the_date( 'F j, Y', $id ),
2663	      'title' => get_the_title( $id ),
2664	      'body'  => apply_filters( 'the_content', get_post_field('post_content', $id) ),
2665	      'url'   => get_the_permalink( $id ),
2666	   ));
2667  }

The function will display the post whose ID is $_POST['id'], regardless of its status : an unauthenticated user could view any post or page, including those that are marked as draft, pending, private or even password-protected.

Subscribers List Export

It registers the niteo_export_csv AJAX action, used to export its list of subscribers:

100   add_action( 'wp_ajax_niteo_export_csv', array( $this, 'niteo_export_csv' ) );
...
...
1829  public function niteo_export_csv() {
1830	   // load subscribers array
1831	   $subscribers = get_option('niteoCS_subscribers_list');
1832
1833	   if( !empty($subscribers) ) {
1834	      $filename = 'cmp-subscribers-export-' . date('Y-m-d') . '.csv';
1835
1836	      header('Content-Type: text/csv');
1837	      header('Content-Disposition: attachment;filename='.$filename);
1838
1839	      $fp = fopen('php://output', 'w');
1840
1841	      fputcsv($fp, array(
1842	         __('ID','cmp-coming-soon-maintenance'),
1843	         __('Date','cmp-coming-soon-maintenance'),
1844	         __('Email','cmp-coming-soon-maintenance'),
1845	         __('Firstname','cmp-coming-soon-maintenance'),
1846	         __('Lastname','cmp-coming-soon-maintenance'),
1847	         __('Fullname', 'cmp-coming-soon-maintenance')
1848	         )
1849	      );
1850	      foreach ( $subscribers as $key => $value ) {
1851
1852
1853
1854	         if ( isset( $value['ip_address'] ) ) {
1855	            unset($subscribers[$key]['ip_address']);
1856	         }
1857
1858	         if ( isset( $value['timestamp'] ) )     {
1859	            $format="Y-m-d H:i:s";
1860	            $subscribers[$key]['timestamp'] = date_i18n($format, $subscribers[$key]['timestamp']);
1861	         }
1862
1863	         $subscribers[$key]['Name'] = '';
1864
1865	         if ( $value['firstname'] !== '' || $value['lastname'] !== '' ) {
1866	            $subscribers[$key]['Name'] = $value['firstname'] . ' ' . $value['lastname'];
1867	         }
1868
1869	         $subscribers[$key]['Name'] = trim($subscribers[$key]['Name']);
1870
1871
1872	      }
1873
1874	      foreach ( $subscribers as $key => $value ) {
1875	         fputcsv($fp, $value, $delimiter = ',', $enclosure = '"' );
1876	      }
1877	      fclose($fp);
1878	   }
1879	   die();
1880  }

It lacks a capability check and a security nonce, allowing any authenticated user to download the plugin’s subscribers list which includes email addresses and names.

Plugin Deactivation

The plugin registers the cmp_disable_comingsoon_ajax AJAX action, accessible to anyone, used to disable itself after expiry of the countdown when its “Countdown Timer Setup” option is enabled:

109	add_action( 'wp_ajax_nopriv_cmp_disable_comingsoon_ajax', array( $this, 'cmp_disable_comingsoon_ajax' ) );
...
...
1153	public function cmp_disable_comingsoon_ajax() {
1154
1155	   $theme = $this->cmp_selectedTheme();
1156
1157	   if ( !in_array( $theme, $this->cmp_builder_themes() ) ) {
1158	      check_ajax_referer( 'cmp-coming-soon-maintenance-nonce', 'security' );
1159	   }
1160
1161	   $result = array( 'message' => 'error');
1162
1163	   if ( get_option('niteoCS_countdown_action', 'no-action') !== 'disable-cmp' ) {
1164	      echo json_encode( $result );
1165	      wp_die();
1166	   }
1167
1168	   if ( !empty( $_REQUEST['status'] ) && $_REQUEST['status'] === 'disable-cmp' ) {
1169	      update_option('niteoCS_status', '0');
1170	      $this->cmp_purge_cache();
1171	      $result = array( 'message' => 'success');
1172	   }
1173
1174	   echo json_encode( $result );
1175	   wp_die();
1176	}

It relies only on a security nonce that is accessible to anyone in the source of the main HTML page:

Unauthenticated users could use it to disable the plugin whenever they want.

Timeline

The vulnerabilities were reported to the authors on July 15th, 2020 and a new version 3.8 was released the following day. However, because it was still possible to access password-protected posts, a new version 3.8.2 was released on August 3rd, 2020.

Recommendations

Upgrade immediately if you have version 3.8.1 or below. If you are using our web application firewall for WordPress, NinjaFirewall WP Edition (free) and NinjaFirewall WP+ Edition (premium), you are protected against this vulnerability.

Stay informed about the latest vulnerabilities