Headline
CVE-2023-2517: plugin.php in metform/trunk – WordPress Plugin Repository
The Metform Elementor Contact Form Builder plugin for WordPress is vulnerable to Cross-Site Request Forgery in versions up to, and including, 3.3.2. This is due to missing or incorrect nonce validation on the permalink_setup function. This makes it possible for unauthenticated attackers to change the permalink structure via a forged request granted they can trick a site administrator into performing an action such as clicking on a link. While nonce verification is implemented, verification only takes place when a nonce is provided.
1<?php23namespace MetForm;45use MetForm\Core\Integrations\Onboard\Attr;6use MetForm\Core\Integrations\Onboard\Onboard;78defined(‘ABSPATH’) || exit;910final class Plugin {1112 private static $instance;1314 private $entries;15 private $global_settings;1617 public function __construct()18 {19 Autoloader::run();20 add_action( 'wp_head’, array( $this, ‘add_meta_for_search_excluded’ ) );21 add_action( 'init’, array ($this, ‘metform_permalink_setup’));22 }2324 public function version()25 {26 return '3.3.3’;27 }2829 public function package_type()30 {31 return apply_filters( 'metform/core/package_type’, ‘free’ );32 }3334 public function plugin_url()35 {36 return trailingslashit(plugin_dir_url(__FILE__));37 }3839 public function plugin_dir()40 {41 return trailingslashit(plugin_dir_path(__FILE__));42 }4344 public function core_url()45 {46 return $this->plugin_url() . 'core/’;47 }4849 public function core_dir()50 {51 return $this->plugin_dir() . 'core/’;52 }5354 public function base_url()55 {56 return $this->plugin_url() . 'base/’;57 }5859 public function base_dir()60 {61 return $this->plugin_dir() . 'base/’;62 }6364 public function utils_url()65 {66 return $this->plugin_url() . 'utils/’;67 }6869 public function utils_dir()70 {71 return $this->plugin_dir() . 'utils/’;72 }7374 public function widgets_url()75 {76 return $this->plugin_url() . 'widgets/’;77 }7879 public function widgets_dir()80 {81 return $this->plugin_dir() . 'widgets/’;82 }8384 public function public_url()85 {86 return $this->plugin_url() . 'public/’;87 }8889 public function public_dir()90 {91 return $this->plugin_dir() . 'public/’;92 }9394 public function account_url(){95 return 'https://account.wpmet.com’;96 }9798 public function i18n()99 {100 load_plugin_textdomain(‘metform’, false, dirname(plugin_basename(__FILE__)) . ‘/languages/’);101 }102103 public function init()104 {105 /**106 * ----------------------------------------107 * Ask for rating ⭐⭐⭐⭐⭐108 * A rating notice will appear depends on109 * @set_first_appear_day methods110 * ----------------------------------------111 */112 Onboard::instance()->init();113114 if(isset($_GET[‘met-onboard-steps’]) && isset($_GET[‘met-onboard-steps-nonce’]) && wp_verify_nonce(sanitize_text_field(wp_unslash($_GET[‘met-onboard-steps-nonce’])),’met-onboard-steps-action’)) {115 Attr::instance();116 }117118 \Wpmet\Libs\Rating::instance(‘metform’)119 ->set_plugin_logo(‘https://ps.w.org/metform/assets/icon-128x128.png’)120 ->set_plugin('Metform’, ‘https://wpmet.com/wordpress.org/rating/metform’)121 ->set_allowed_screens(‘edit-metform-entry’)122 ->set_allowed_screens(‘edit-metform-form’)123 ->set_allowed_screens(‘metform_page_metform_get_help’)124 ->set_priority(30)125 ->set_first_appear_day(7)126 ->set_condition(true)127 ->call();128129130 $filter_string = '’; // elementskit,metform-pro131 $filter_string .= ((!in_array('elementskit/elementskit.php’, apply_filters('active_plugins’, get_option(‘active_plugins’)))) ? ‘’ : ‘,elementskit’);132 $filter_string .= (!class_exists(‘\MetForm\Plugin’) ? ‘’ : ‘,metform’);133 $filter_string .= (!class_exists(‘\MetForm_Pro\Plugin’) ? ‘’ : ‘,metform-pro’);134135 // banner136 \Wpmet\Libs\Banner::instance(‘metform’)137 ->set_filter(ltrim($filter_string, ‘,’))138 ->set_api_url(‘https://api.wpmet.com/public/jhanda’)139 ->set_plugin_screens(‘edit-metform-form’)140 ->set_plugin_screens(‘edit-metform-entry’)141 ->set_plugin_screens(‘metform_page_metform-menu-settings’)142 ->call();143144145146 /**147 * Show WPMET stories widget in dashboard148 */149 \Wpmet\Libs\Stories::instance(‘metform’)150151 ->set_filter($filter_string)152 ->set_plugin('Metform’, ‘https://wpmet.com/plugin/metform/’)153 ->set_api_url(‘https://api.wpmet.com/public/stories/’)154 ->call();155156 /**157 * Pro awareness feature;158 */159160 $is_pro_active = '’;161162 if (!in_array('metform-pro/metform-pro.php’, apply_filters('active_plugins’, get_option(‘active_plugins’)))) {163 $is_pro_active = 'Go Premium’;164 }165166 $pro_awareness = \Wpmet\Libs\Pro_Awareness::instance(‘metform’);167 if(version_compare($pro_awareness->get_version(), '1.2.0’, ‘>=’)) {168 $pro_awareness169 ->set_parent_menu_slug(‘metform-menu’)170 ->set_pro_link(171 (in_array('metform-pro/metform-pro.php’, apply_filters('active_plugins’, get_option(‘active_plugins’)))) ? ‘’ :172 'https://wpmet.com/metform-pricing’173 )174 ->set_plugin_file(‘metform/metform.php’)175 ->set_default_grid_thumbnail($this->utils_url() . ‘/pro-awareness/assets/images/support.png’)176 ->set_page_grid([177 ‘url’ => 'https://wpmet.com/fb-group’,178 ‘title’ => 'Join the Community’,179 ‘thumbnail’ => $this->utils_url() . '/pro-awareness/assets/images/community.png’,180 ‘description’ => 'Join our Facebook group to get 20% discount coupon on premium products. Follow us to get more exciting offers.’181182 ])183 ->set_page_grid([184 ‘url’ => 'https://www.youtube.com/playlist?list=PL3t2OjZ6gY8NoB_48DwWKUDRtBEuBOxSc’,185 ‘title’ => 'Video Tutorials’,186 ‘thumbnail’ => $this->utils_url() . '/pro-awareness/assets/images/videos.png’,187 ‘description’ => 'Learn the step by step process for developing your site easily from video tutorials.’188 ])189 ->set_page_grid([190 ‘url’ => 'https://wpmet.com/plugin/metform/roadmaps#ideas’,191 ‘title’ => 'Request a feature’,192 ‘thumbnail’ => $this->utils_url() . '/pro-awareness/assets/images/request.png’,193 ‘description’ => 'Have any special feature in mind? Let us know through the feature request.’194 ])195 ->set_page_grid([196 ‘url’ => 'https://wpmet.com/doc/metform/’,197 ‘title’ => 'Documentation’,198 ‘thumbnail’ => $this->utils_url() . 'pro-awareness/assets/images/documentation.png’,199 ‘description’ => 'Detailed documentation to help you understand the functionality of each feature.’200 ])201 ->set_page_grid([202 ‘url’ => 'https://wpmet.com/plugin/metform/roadmaps/’,203 ‘title’ => 'Public Roadmap’,204 ‘thumbnail’ => $this->utils_url() . 'pro-awareness/assets/images/roadmaps.png’,205 ‘description’ => 'Check our upcoming new features, detailed development stories and tasks’206 ])207208 // set wpmet products209 ->set_products([210 ‘url’ => 'https://getgenie.ai/’,211 ‘title’ => 'GetGenie’,212 ‘thumbnail’ => $this->core_url() . 'integrations/onboard/assets/images/products/getgenie-logo.svg’,213 ‘description’ => 'Your AI-Powered Content & SEO Assistant for WordPress’,214 ])215 ->set_products([216 ‘url’ => 'https://wpmet.com/plugin/shopengine/’,217 ‘title’ => 'ShopEngine’,218 ‘thumbnail’ => $this->core_url() . 'integrations/onboard/assets/images/products/shopengine-logo.svg’,219 ‘description’ => 'Complete WooCommerce Solution for Elementor’,220 ])221 ->set_products([222 ‘url’ => 'https://wpmet.com/plugin/metform/’,223 ‘title’ => 'MetForm’,224 ‘thumbnail’ => $this->core_url() . 'integrations/onboard/assets/images/products/metform-logo.svg’,225 ‘description’ => 'Most flexible drag-and-drop form builder’226 ])227 ->set_products([228 ‘url’ => 'https://wpmet.com/plugin/wp-social/’,229 ‘title’ => 'WP Social’,230 ‘thumbnail’ => $this->core_url() . 'integrations/onboard/assets/images/products/wp-social-logo.svg’,231 ‘description’ => 'Integrate all your social media to your website’232 ])233 ->set_products([234 ‘url’ => 'https://wpmet.com/plugin/wp-ultimate-review/?ref=wpmet’,235 ‘title’ => 'Ultimate Review’,236 ‘thumbnail’ => $this->core_url() . 'integrations/onboard/assets/images/products/ultimate-review-logo.svg’,237 ‘description’ => 'Integrate various styled review system in your website’238 ])239 ->set_products([240 ‘url’ => 'https://products.wpmet.com/crowdfunding/?ref=wpmet’,241 ‘title’ => 'Fundraising & Donation Platform’,242 ‘thumbnail’ => $this->core_url() . 'integrations/onboard/assets/images/products/wp-fundraising-logo.svg’,243 ‘description’ => 'Enable donation system in your website’244 ])245246 ->set_plugin_row_meta('Documentation’, 'https://help.wpmet.com/docs-cat/metform/’, [‘target’ => ‘_blank’])247 ->set_plugin_row_meta('Facebook Community’, 'https://wpmet.com/fb-group’, [‘target’ => ‘_blank’])248 ->set_plugin_row_meta('Rate the plugin ★★★★★’, 'https://wordpress.org/support/plugin/metform/reviews/#new-post’, [‘target’ => ‘_blank’])249 ->set_plugin_action_link('Settings’, admin_url() . ‘admin.php?page=metform-menu-settings’)250 ->set_plugin_action_link($is_pro_active, 'https://wpmet.com/plugin/metform’, [‘target’ => '_blank’, ‘style’ => ‘color: #FCB214; font-weight: bold;’])251 ->call();252 }253254255256 // Check if Elementor installed and activated.257 if (!did_action(‘elementor/loaded’)) {258 $this->missing_elementor();259 return;260 }261 // Check for required Elementor version.262 if (!version_compare(ELEMENTOR_VERSION, '3.0.1’, ‘>=’)) {263 $this->failed_elementor_version();264 // add_action('admin_notices’, array($this, ‘failed_elementor_version’));265 return;266 }267268 // pro available notice269 if (!file_exists(WP_PLUGIN_DIR . ‘/metform-pro/metform-pro.php’)) {270 $this->available_metform_pro();271 // add_action('admin_notices’, [$this, ‘available_metform_pro’]);272 }273274 if (current_user_can(‘manage_options’)) {275 add_action('admin_menu’, [$this, ‘admin_menu’]);276 }277278 add_action('elementor/editor/before_enqueue_scripts’, [$this, ‘edit_view_scripts’]);279 add_action( 'elementor/editor/after_enqueue_scripts’, [$this, ‘metform_editor_script’] );280281 add_action('init’, [$this, ‘i18n’]);282283 add_action('admin_enqueue_scripts’, [$this, ‘js_css_admin’]);284 add_action('wp_enqueue_scripts’, [$this, ‘js_css_public’]);285286 $my_theme = wp_get_theme();287 if(current_user_can(‘manage_options’) && $my_theme->get(‘Name’) == ‘Cleano’){288 add_action( 'admin_enqueue_scripts’, [$this, ‘cleanoThemeConflict’], 100 );289 }290 291292 add_action('elementor/frontend/before_enqueue_scripts’, [$this, ‘elementor_js’]);293294 add_action('elementor/editor/before_enqueue_styles’, [$this, ‘elementor_css’]);295296 add_action('admin_footer’, [$this, ‘footer_data’]);297298 Core\Forms\Base::instance()->init();299 Controls\Base::instance()->init();300 $this->entries = Core\Entries\Base::instance();301302 Widgets\Manifest::instance()->init();303304 // settings page305 Core\Admin\Base::instance()->init();306307 Core\Forms\Auto_Increment_Entry::instance();308 }309310 function metform_editor_script(){311 wp_enqueue_script('editor-panel-script’, $this->public_url() . '/assets/js/editor-panel.js’, [‘jquery’], $this->version(), true);312 }313314 function js_css_public()315 {316 $this->global_settings = \MetForm\Core\Admin\Base::instance()->get_settings_option();317 $is_form_cpt = (‘metform-form’ === get_post_type());318319 wp_register_style('metform-ui’, $this->public_url() . 'assets/css/metform-ui.css’, false, $this->version());320321 wp_register_style('metform-style’, $this->public_url() . 'assets/css/style.css’, false, $this->version());322323 wp_register_script('htm’, $this->public_url() . 'assets/js/htm.js’, null, $this->version(), true);324325 wp_register_script('metform-app’, $this->public_url() . 'assets/js/app.js’, ['htm’, 'jquery’, ‘wp-element’], $this->version(), true);326327 wp_localize_script('metform-app’, 'mf’, [328 ‘postType’ => get_post_type(),329 ‘restURI’ => get_rest_url(null, ‘metform/v1/forms/views/’),330 ]);331332 // Recaptcha Support Script.333 wp_register_script( 'recaptcha-support’, $this->public_url() . 'assets/js/recaptcha-support.js’, [‘jquery’], $this->version(), true );334335336 // begins pro feature337 // begins for mf-simple-repeater338 wp_register_style('asRange’, $this->public_url() . 'assets/css/asRange.min.css’, false, $this->version());339 wp_register_script('asRange’, $this->public_url() . 'assets/js/jquery-asRange.min.js’, [], $this->version(), true);340341 wp_register_style('mf-select2’, $this->public_url() . 'assets/css/select2.min.css’, false, $this->version());342 wp_register_script('mf-select2’, $this->public_url() . 'assets/js/select2.min.js’, [], $this->version(), true);343 // ends for mf-simple-repeater344345 wp_register_script('recaptcha-v2’, 'https://google.com/recaptcha/api.js?render=explicit’, [], null, true);346347 if (isset($this->global_settings[‘mf_recaptcha_version’]) && ($this->global_settings[‘mf_recaptcha_version’] == ‘recaptcha-v3’) && isset($this->global_settings[‘mf_recaptcha_site_key_v3’]) && ($this->global_settings[‘mf_recaptcha_site_key_v3’] != ‘’)) {348 wp_register_script('recaptcha-v3’, ‘https://www.google.com/recaptcha/api.js?render=’ . $this->global_settings[‘mf_recaptcha_site_key_v3’], [], $this->version(), false);349 }350351 if (isset($this->global_settings[‘mf_google_map_api_key’]) && ($this->global_settings[‘mf_google_map_api_key’] != ‘’)) {352 wp_register_script('maps-api’, ‘https://maps.googleapis.com/maps/api/js?key=’ . $this->global_settings[‘mf_google_map_api_key’] . '&libraries=places&&callback=mfMapLocation’, [], '’, true);353 }354355 // for date, time, simple repeater356 wp_deregister_style(‘flatpickr’); // flatpickr stylesheet357 wp_register_style('flatpickr’, $this->public_url() . 'assets/css/flatpickr.min.css’, false, $this->version()); // flatpickr stylesheet358 // ends pro feature359360361 if($is_form_cpt){362 wp_enqueue_style(‘metform-ui’);363 wp_enqueue_style(‘metform-style’);364 wp_enqueue_script(‘htm’);365 wp_enqueue_script(‘metform-app’);366 }367368 do_action(‘metform/onload/enqueue_scripts’);369 }370371 372373 public function edit_view_scripts()374 {375 wp_enqueue_style('metform-ui’, $this->public_url() . 'assets/css/metform-ui.css’, false, $this->version());376 wp_enqueue_style('metform-admin-style’, $this->public_url() . 'assets/css/admin-style.css’, false, null);377378 wp_enqueue_script('metform-ui’, $this->public_url() . 'assets/js/ui.min.js’, [], $this->version(), true);379 wp_enqueue_script('metform-admin-script’, $this->public_url() . 'assets/js/admin-script.js’, [], null, true);380381 wp_add_inline_script('metform-admin-script’, “382 var metform_api = {383 resturl: '” . get_rest_url() . “’384 }385 ");386 }387388 public function elementor_js()389 {390 }391392 public function elementor_css()393 {394 if (‘metform-form’ == get_post_type()) {395 wp_enqueue_style('metform-category-top’, $this->public_url() . 'assets/css/category-top.css’, false, $this->version());396 }397 }398399400401 /**402 * @function - {cleanoThemeConflict}403 * @description - this function is used to remove conflict of bootstrap between metform & cleano theme.404 */405 function cleanoThemeConflict() {406407 $screen = get_current_screen();408 if(in_array($screen->id, ['edit-metform-form’, 'metform_page_mt-form-settings’, 'metform-entry’, ‘metform_page_metform-menu-settings’])){409 wp_dequeue_script( ‘bootstrap’ );410 }411 }412413414 function js_css_admin()415 {416417418 wp_enqueue_style( 'mf-wp-dashboard’, $this->core_url() . 'admin/css/mf-wp-dashboard.css’, [], $this->version() );419420 $screen = get_current_screen();421422 if (in_array($screen->id, ['edit-metform-form’, 'metform_page_mt-form-settings’, 'metform-entry’, ‘metform_page_metform-menu-settings’])) {423 wp_enqueue_style('metform-admin-fonts’, $this->public_url() . 'assets/admin-fonts.css’, false, $this->version());424 wp_enqueue_style('metform-ui’, $this->public_url() . 'assets/css/metform-ui.css’, false, $this->version());425 wp_enqueue_style('metform-admin-style’, $this->public_url() . 'assets/css/admin-style.css’, false, null);426427 wp_enqueue_script('metform-ui’, $this->public_url() . 'assets/js/ui.min.js’, [], $this->version(), true);428 wp_enqueue_script('metform-admin-script’, $this->public_url() . 'assets/js/admin-script.js’, [], null, true);429 wp_localize_script('metform-admin-script’, 'metform_api’, [‘resturl’ => get_rest_url(), ‘admin_url’ => get_admin_url()]);430 }431432 if ($screen->id == ‘edit-metform-entry’ || $screen->id == ‘metform-entry’) {433 wp_enqueue_style('metform-ui’, $this->public_url() . 'assets/css/metform-ui.css’, false, $this->version());434 wp_enqueue_script('metform-entry-script’, $this->public_url() . 'assets/js/admin-entry-script.js’, [], $this->version(), true);435 }436 }437438 /**439 * Excluding Metform form from search engine.440 *441 */442 public function add_meta_for_search_excluded() {443 444445446 if ( in_array(get_post_type(), [‘metform-form’]) ) {447 echo '<meta name="robots” content="noindex,nofollow" />’, “\n";448 }449 }450451 public function footer_data()452 {453454 $screen = get_current_screen();455456 if ($screen->id == ‘edit-metform-entry’) {457 $args = [458 ‘post_type’ => ‘metform-form’,459 ‘post_status’ => ‘publish’,460 ‘numberposts’ => -1,461 ];462463 $forms = get_posts($args);464 //phpcs:ignore WordPress.Security.NonceVerification – Nonce can’t be added in CPT URL465 $get_form_id = isset($_GET[‘form_id’]) ? sanitize_key($_GET[‘form_id’]) : ‘’;466?>467 <div id=’metform-formlist’ style=’display:none;’><select name=’mf_form_id’ id=’metform-form_id’>468 <option value=’all’ <?php echo esc_attr(((($get_form_id == ‘all’) || ($get_form_id == ‘’)) ? ‘selected=selected’ : ‘’)); ?>>All</option>469 <?php470471 foreach ($forms as $form) {472 $form_list[$form->ID] = $form->post_title;473 ?>474 <option value="<?php echo esc_attr($form->ID); ?>” <?php echo esc_attr(($get_form_id == $form->ID) ? ‘selected=selected’ : ‘’); ?>><?php echo esc_html($form->post_title); ?></option>475 <?php476 }477 echo "</select></div>";478 }479 }480481 function admin_menu()482 {483 add_menu_page(484 esc_html__('MetForm’, ‘metform’),485 esc_html__('MetForm’, ‘metform’),486 'read’,487 'metform-menu’,488 '’,489 $this->core_url() . 'admin/images/icon-menu.png’,490 5491 );492 }493494 public function missing_elementor()495 {496 //phpcs:disable WordPress.Security.NonceVerification – Can’t set nonce. Cause it’s fire on ‘plugins_loaded’ hook497 if (isset($_GET[‘activate’])) {498 unset($_GET[‘activate’]);499 }500 //phpcs:enable501 if (file_exists(WP_PLUGIN_DIR . ‘/elementor/elementor.php’)) {502 $btn[‘text’] = esc_html__('Activate Elementor’, ‘metform’);503 $btn[‘id’] = 'unsupported-elementor-version’;504 $btn[‘class’] = 'button-primary’;505 $btn[‘url’] = wp_nonce_url('plugins.php?action=activate&plugin=elementor/elementor.php&plugin_status=all&paged=1’, ‘activate-plugin_elementor/elementor.php’);506 } else {507 $btn[‘id’] = 'unsupported-elementor-version’;508 $btn[‘class’] = 'button-primary’;509 $btn[‘text’] = esc_html__('Install Elementor’, ‘metform’);510 $btn[‘url’] = wp_nonce_url(self_admin_url(‘update.php?action=install-plugin&plugin=elementor’), ‘install-plugin_elementor’);511 }512513 $message = sprintf(esc_html__('MetForm requires Elementor version %1$s+, which is currently NOT RUNNING.’, ‘metform’), ‘2.6.0’);514515 \Oxaim\Libs\Notice::instance('metform’, ‘unsupported-elementor-version’)516 ->set_dismiss('global’, (3600 * 24 * 15))517 ->set_message($message)518 ->set_button($btn)519 ->call();520 }521522 public function available_metform_pro()523 {524 //phpcs:disable WordPress.Security.NonceVerification – Can’t set nonce. Cause it’s fire on ‘plugins_loaded’ hook525 if (isset($_GET[‘activate’])) {526 unset($_GET[‘activate’]);527 }528 //phpcs:enable 529 $btn[‘text’] = esc_html__('MetForm Pro’, ‘metform’);530 $btn[‘url’] = esc_url(‘https://products.wpmet.com/metform/’);531 $btn[‘class’] = 'button-primary’;532533 $message = sprintf(esc_html__('We have MetForm Pro version. Check out our pro feature.’, ‘metform’), ‘2.6.0’);534 \Oxaim\Libs\Notice::instance('metform’, ‘unsupported-metform-pro-version’)535 ->set_dismiss('global’, (3600 * 24 * 15))536 ->set_message($message)537 ->set_button($btn)538 ->call();539 }540541542 public function failed_elementor_version()543 {544545 $btn[‘text’] = esc_html__('Update Elementor’, ‘metform’);546 $btn[‘url’] = sprintf(esc_html__('MetForm requires Elementor version %1$s+, which is currently NOT RUNNING.’, ‘metform’), ‘2.6.0’);547 $btn[‘class’] = 'button-primary’;548549 $message = sprintf(esc_html__('We have MetForm Pro version. Check out our pro feature.’, ‘metform’), ‘2.6.0’);550 \Oxaim\Libs\Notice::instance('metform’, ‘unsupported-elementor-version’)551 ->set_dismiss('global’, (3600 * 24 * 15))552 ->set_message($message)553 ->set_button($btn)554 ->call();555 }556557 public function flush_rewrites()558 {559 $form_cpt = new Core\Forms\Cpt();560 $form_cpt->flush_rewrites();561 }562563564 public static function instance()565 {566 if (!self::$instance) {567 self::$instance = new self();568 }569 return self::$instance;570 }571572 public function metform_permalink_setup(){573 574 Utils\Util::permalink_setup();575 }576577578}