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
- Running WordPress? You can get email notifications about vulnerabilities in the plugins or themes installed on your blog.
- On Twitter: @nintechnet