RegistrationMagic – Custom Registration Forms, User Registration, Payment, and User Login <= 6.0.7.1 - Authenticated (Subscriber+) Information Exposure
Description
The RegistrationMagic – Custom Registration Forms, User Registration, Payment, and User Login plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 6.0.7.1. This makes it possible for authenticated attackers, with Subscriber-level access and above, to extract sensitive user or configuration data.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:NTechnical Details
<=6.0.7.1What Changed in the Fix
Changes introduced in v6.0.7.2
Source Code
WordPress.org SVNvars.nonce`. Wait, I see a huge potential leak: `admin/controllers/class_rm_form_controller.php`: ```php $data[$i]->form_attachments = $attach_service->get_all_form_attachments($form->form_id); ``` This lists all files uploaded to a form. Let's formulate the plan: T…
Show full research plan
vars.nonce`.
Wait, I see a huge potential leak:
`admin/controllers/class_rm_form_controller.php`:
```php
$data[$i]->form_attachments = $attach_service->get_all_form_attachments($form->form_id);
```
This lists all files uploaded to a form.
Let's formulate the plan:
The vulnerability allows any authenticated user (Subscriber+) to access admin-only controllers by leveraging the `rm_get_stats` AJAX action (or other actions mapped to `RM_Main_Controller::run`) and specifying a privileged `rm_slug`.
Wait, I'll bet the `rm_ajax_secure` nonce is *not even checked* for `rm_get_stats`.
Many RM vulnerabilities in 2024/2025 involve `run()` not checking nonces or permissions correctly.
1. Login as Subscriber.
2. Request `admin-ajax.php?action=rm_get_stats&rm_slug=rm_user_manage`.
3. Check if it returns the user manager HTML.
4. If it needs a nonce, try to find one. (Check `wp-admin` dashboard for any localized RM nonces).
Wait, looking at `class_rm_admin.php` again:
`$this->icon = base64_encode('<svg ...');`
Nothing there.
Summary
RegistrationMagic for WordPress is vulnerable to sensitive information exposure because several administrative controller actions and views lack proper authorization and nonce checks. Authenticated users with Subscriber-level privileges can invoke these actions—such as retrieving additional user details or accessing form attachment lists—by directly interacting with the plugin's controller routing system.
Vulnerable Code
// admin/controllers/class_rm_user_controller.php line 428-440 public function additional_details($model, RM_User_Services $service, $request, $params){ $user_details = array(); //if(check_ajax_referer('rm_ajax_secure','rm_sec_nonce')) { if(!empty($request->req['user_ids'])){ $user_ids = $request->req['user_ids']; $user_details = $service->user_additional_details($user_ids); } //} wp_send_json_success($user_details); die(); } --- // admin/controllers/class_rm_form_controller.php line 292-311 public function quick_add($model, $service, $request, $params) { $valid = false; if ($this->mv_handler->validateForm("rm_form_quick_add")) { $model->set($request->req); $valid = $model->validate_model(); } if ($valid) { //By default make it registration type $model->set_form_type(1); $model->set_default_form_user_role('subscriber'); if (isset($request->req['form_id'])) $valid = $service->update($request->req['form_id']); else $service->add_user_form(); } $this->manage($model, $service, $request, $params); } --- // admin/class_rm_admin.php line 487-495 if (in_array( $role_slug, $value[2] )){ if ( ! $rm_role->has_cap( $value[0]."manage_options" ) ) { $rm_role->add_cap( $value[0]."manage_options" ); $role_added = true; } }
Security Fix
@@ -477,7 +477,6 @@ $admin_order = $gopts->get_value_of('enable_admin_order') == 'yes' ? $gopts->get_value_of('admin_order') : $gopts->default['admin_order']; $admin_order = apply_filters('rm_admin_menu_order_list',$admin_order, $gopts); $role_top_admin = array("administrator"); - foreach ($admin_order as $value) { foreach ( $roles as $role_slug => $role ) { @@ -485,8 +484,7 @@ $rm_role = get_role( $role_slug ); if (in_array( $role_slug, $value[2] )){ - - if ( ! $rm_role->has_cap( $value[0]."manage_options" ) ) { + if ( ! $rm_role->has_cap( $value[0]."manage_options" ) && !empty(trim($value[0])) ) { $rm_role->add_cap( $value[0]."manage_options" ); @@ -805,7 +803,7 @@ } elseif ($value[0] == 'rm_subscriptions') { // attachments menu - do_action("rm_admin_menu_after_automation",$value[0]); + do_action("rm_admin_menu_after_automation",$value[0], $value[3]); } elseif ($value[0] == 'rm_analytics_show_form') { @@ -1125,6 +1123,10 @@ // do_action("rm_admin_menu_after_field_stats",""); + } elseif ($value[0] == 'rm_subscriptions') { + // attachments menu + do_action("rm_admin_menu_after_automation",$value[0], $value[3]); + } elseif ($value[0] == 'rm_analytics_show_form') { // Analytics > FORMS @@ -1174,7 +1176,7 @@ // setting - add_submenu_page("rm_form_manage", RM_UI_Strings::get('ADMIN_MENU_SETTINGS'), RM_UI_Strings::get('ADMIN_MENU_SETTINGS'), "manage_options", "rm_options_manage", array($this->get_controller(), 'run')); + add_submenu_page(current_user_can('manage_options') ? "rm_form_manage" : "rm_dummy_string", RM_UI_Strings::get('ADMIN_MENU_SETTINGS'), RM_UI_Strings::get('ADMIN_MENU_SETTINGS'), "manage_options", "rm_options_manage", array($this->get_controller(), 'run')); // setting options @@ -290,24 +290,26 @@ } public function quick_add($model, $service, $request, $params) { - $valid = false; - if ($this->mv_handler->validateForm("rm_form_quick_add")) { - $model->set($request->req); + if (current_user_can('manage_options') || current_user_can('rm_form_managemanage_options')) { + $valid = false; + if ($this->mv_handler->validateForm("rm_form_quick_add")) { + $model->set($request->req); - $valid = $model->validate_model(); - } - if ($valid) { - //By default make it registration type - $model->set_form_type(1); - $model->set_default_form_user_role('subscriber'); + $valid = $model->validate_model(); + } + if ($valid) { + //By default make it registration type + $model->set_form_type(1); + $model->set_default_form_user_role('subscriber'); - if (isset($request->req['form_id'])) - $valid = $service->update($request->req['form_id']); - else - $service->add_user_form(); - } + if (isset($request->req['form_id'])) + $valid = $service->update($request->req['form_id']); + else + $service->add_user_form(); + } - $this->manage($model, $service, $request, $params); + $this->manage($model, $service, $request, $params); + } } public function import($model, $service, $request, $params) { @@ -560,7 +560,7 @@ } public function admin_menu($model, RM_Setting_Service $service, $request, $params){ - if ($this->mv_handler->validateForm("options_admin_menu")){ + if ($this->mv_handler->validateForm("options_admin_menu") && current_user_can('manage_options')) { if ($request->req['restore'] == 'false'){ $options = array(); $options['admin_order'] = ""; @@ -428,17 +428,15 @@ $this->manage($model,$service,$request,$params); } - public function additional_details($model, RM_User_Services $service, $request, $params){ - $user_details = array(); - //if(check_ajax_referer('rm_ajax_secure','rm_sec_nonce')) { - if(!empty($request->req['user_ids'])){ + public function additional_details($model, RM_User_Services $service, $request, $params) { + if(check_ajax_referer('rm_ajax_secure','rm_sec_nonce') && (current_user_can('manage_options') || current_user_can('rm_user_managemanage_options'))) { + $user_details = array(); + if(!empty($request->req['user_ids'])) { $user_ids = $request->req['user_ids']; $user_details = $service->user_additional_details($user_ids); } - //} - wp_send_json_success($user_details); - die(); - + wp_send_json_success($user_details); + } }
Exploit Outline
An authenticated attacker with Subscriber-level privileges can exploit this vulnerability by directly calling administrative actions registered through the plugin's `RM_Main_Controller::run` router. Specifically, the attacker can use the `rm_get_stats` AJAX action (intended for admins) and provide a privileged `rm_slug` (e.g., `rm_user_manage`) along with the target action (e.g., `additional_details`). Because the vulnerable functions lacked permission checks and sometimes bypassed nonce verification, the attacker can retrieve sensitive user profile data by supplying a list of `user_ids` in the request, or perform other unauthorized actions like creating/modifying forms via `quick_add`.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.