Multiple Authenticated Stored XSS in NinjaForms Settings Page (Version 3.4.22 )


Authenticated Stored XSS in NinjaForms Settings Page (Version 3.4.22 )



A Spider Sec Ltd consultant discovered an Authenticated Stored XSS vulnerability inside the Ninja forms WordPress Plugin which could allow attackers to hi-jack administrative cookies if an attack is coupled together with a phishing campaign.


Technical Details

The following parameters are vulnerable to Stored XSS on the administrative section of the Ninja Forms WordPress Plugin:

ninja_forms[date_format]=, ninja_forms[recaptcha_site_key]=, ninja_forms[recaptcha_lang]=

Using the following payload:

m/d/Yufyiy' onfocus=alert(document.cookie) autofocus= etyeqchypbw


So how can a hacker use this to attack my administrative panel?

Yes, but it requires a phishing campaign and a pretty trusting administrator.

First, create a button which submits the vulnerable POST and host it.

<form action="http://VictimsURL/wp-admin/admin.php?page=nf-settings" method="POST">
<input name="ninja_forms[date_format]" type="hidden" value="zm/d/Yufyiy' onfocus=alert(document.cookie) autofocus= etyeqchypbw" />
<input type="submit" value="Submit request" />

Next, persuade a victim to press the button, this would obviously be styled in a more persuasive manner or hidden inside a clickjacking attack.

The code is then stored on the back-end waiting for the administrator to access the settings page, wherein it will trigger.


Update to version 3.4.23

Registration Magic Multiple Unauthenticated XSS Vulnerabilities (Version


Registration Magic Version (Multiple XSS Vulnerabilities)


After discovering two new WordPress Plugin vulnerabilities on a recent web application penetration test (which were authenticated and difficult to weaponise) I decided to go in search for some higher ticket WordPress Plugin vulnerabilities in my spare time. I started downloading registration form and forum building plugins, as these are more likely to contain unauthenticated or customer-facing vulnerabilities.

It really did not take that long.  About 10minutes from installing the first plugin to be exact.

Introducing RegistrationMagic – Custom Registration Forms and User Login version a form building plugin which allows users to create custom login forms, contact forms and other form-based software ideas. However, the vulnerability in the discussion above would need authentication as an administrator to be useful. I had a feeling that a more useful bug could be found in this plugin so started building forms and adding them into my lab.

Technical Details

Unauthenticated Stored (XSS) on Contact Form

Here you can see the XSS being injected into the Name field of a contact form generated by Registration Magic.

Next, we go to the contact form and select to view the submissions.

Uh Oh… an unauthenticated user can make a submission into one of these generated contact forms and run code inside the administrators’ browser and potentially steal session tokens. Anyone running this plugin could easily lose access to their site.

Reflected XSS on Multiple Parameters

Next, we have more XSS vulnerabilities which were discovered during fuzzing.

The following parameters were also affected by XSS inside the application.

 rm_form_id, form_name,Textarea_, TextBox_

Code Breakdown

Plenty of places in the code parameter values are being taken by the application without proper validation checks. I am going to outline a few examples now.

Here we can see in the comments “take value from various variables and reload pages with those updated”, but there is no validation controls and using an interceptor such as burp we can modify the rm_form_id content in the dropdown.

//Takes value of various status variables (form_id, timeline_range) and reloads page with those parameteres updated.
function rm_refresh_stats(){
var form_id = jQuery('#rm_form_dropdown').val();
var trange = jQuery('#rm_stat_timerange').val();
if(typeof trange == 'undefined')
trange = ;
window.location = '?page=rm_analytics_show_form&rm_form_id=' + form_id + '&rm_tr='+trange;

Here we can see the form_id is being grabbed which is later echo’d into the application browser

$form_id= $_GET['form_id']


Update to the latest version of Registration Magic.

PART 2 – SQL Injection

Registration Magic Authenticated Blind SQL Injection inside URL


Registration Magic Version Authenticated Blind SQL Injection in URL



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.*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");


Update to the latest version of Registration Magic.

Calculated Fields Form WP Plugin (Version <= 1.0.353) Authenticated Stored XSS


Calculated Fields Form WP Plugin (Version <= 1.0.353) Multiple Authenticated Stored XSS


The Calculated Fields Form plugin through 1.0.353 for WordPress suffers from multiple Stored XSS vulnerabilities present in the input forms. These Calculated Fields Form vulnerabilities were discovered during a web application penetration test by a Spider Sec Ltd Consultant.

Technical Details​

An authenticated user with access to edit or create forms can inject javascript into input fields such as ‘field name’ and ‘form name’. This results in the XSS being stored both on the back-end and front-end of the WordPress website. As a result, both users and administrators could be a target if a WordPress website is compromised. However, these vulnerabilities are unlikely to be weaponised due to the level of authentication required to exploit.


Update to the latest version of this plugin version 1.0.354


WPVDB ID 10043

Chained Quiz WP Plugin Unauthenticated Reflected XSS (Version


Chained Quiz WP Plugin Unauthenticated Reflected XSS (Version


During a web application penetration testing engagement, we discovered our client was using the Chained Quiz Plugin to serve quizzes on the front-end of their site. A quick analysis using WPscan uncovered several historic Chained Quiz Vulnerabilities which had been disclosed in previous versions. As a result of the volume of historic vulnerabilities, we decided to set up a test lab to see if any new vulnerabilities had been introduced into the latest updates. Low and behold we discovered a new unauthenticated Reflected XSS vulnerability, the vulnerability was responsibly disclosed to the plugin developer and an update to the plugin was applied and can be observed here.

Technical Details

The POST parameter ‘total_questions’ fails to sanitize user input. As a result, it is possible to execute client-side JavaScript on a victims PC if the client is tricked into pressing a button containing the malicious request.
An attacker could leverage this vulnerability to steal administrative sessions tokens to a WordPress site or execute code in a victims browser.

The code in question accepts the ‘total_questions’ parameter without escaping special characters. The vulnerable code can be found in the following php file /models/quiz.php.

$output = str_replace('{{questions}}', $_POST['total_questions'], $output);

Spider Sec probed the Chained Quiz WP Plugin for Vulnerabilities as part of a web application penetration testing engagement.


Update to the latest version of this plugin, version


WPVDB ID 10029