SQL Injection Vulnerability in Ninja Forms

WordPress Vulnerablity Disclosre

Security Risk: Dangerous

Exploitation Level: Easy/Remote

DREAD Score: 6/10

Vulnerability: SQL Injection

Patched Version:

As part of our regular research audits for our Sucuri Firewall, we discovered an SQL Injection vulnerability affecting the Ninja Forms plugin for WordPress, currently installed on 600,000+ websites.

Vulnerability Disclosure Timeline:

  • August 11th 9:35 am, 2016 – Initial report to the Ninja Forms team
  • August 11th 2:49 pm, 2016 – Public release of version, fixing the vulnerability

Are You at Risk?

The attack vector used to exploit this vulnerability requires the attacker to have an account on the victim’s site. It doesn’t matter what the account privileges are – for example, a subscriber could exploit this issue. The issue occurs because the plugin doesn’t escape parameters provided by its shortcodes before concatenating it to an SQL query.

A malicious individual using this bug could (among other things) leak the site’s usernames and hashed passwords. In certain configurations, it can also leak WordPress secret keys.

Technical Details

SQL injections tend to be trickier to find in popular plugins now than they used to be, partly due to the increasing popularity of prepared statements like $wpdb->prepare(). That’s why when we stumbled upon the following snippet of code, we thought it could be interesting to investigate a bit further:


Suspicious Ninja Forms code snippet
Suspicious Ninja Forms code snippet

As you can see, the $meta_value variable (which contains the content of $form_id) is concatenated to the SQL query without being escaped first.

Ninja forms vulnerability
Direct user input

We found the function being used in a couple of places with direct user input as its first argument. While this would have been an SQL injection by itself in other PHP applications, it’s not the case with WordPress as it automatically escapes $_GET, $_POST and $_REQUEST when booting up. So we had to look a bit further to find some snippets that could be exploited. That’s when we found this snippet:

ninja forms vulnerability shortcode generation
Shortcode generation

Basically speaking, it registers the shortcode ninja_forms_display_sub_number using the WordPress Shortcode API and sets its callback function to the one we see above. From there, $atts contains the list of parameters the shortcode contains in their raw, unescaped value. This means if a user wrote a post containing a shortcode like [ninja_forms_display_sub_number id=”123′ SQL INJECTION OCCURS HERE”], he could perform an SQL injection attack.

Now, it isn’t that much of a big vulnerability if it’s restricted to more privileged users, so we had to dig deeper to find out how we could use this attack with less privileged accounts.

ninja forms vulnerability allows shortcode execution from wordpress core
Function in WordPress core allowing shortcodes execution

That’s when we found this function in WordPress core. It’s accessible by sending a POST request to /wp-admin/admin-ajax.php using the parse-media-shortcode POST action parameter. As you may understand from the code, it allows any user to execute any shortcodes they want (using do_shortcode), as long as it’s not embedded. To access this snippet one would need to POST a request like:

ninja forms vulnerability post request example
Example of malicious post request

Using this attack vector, the attacker would be able to exploit the vulnerability with low-privileged accounts, like subscribers.

Update as Soon as Possible

If you’re using a vulnerable version of this plugin, yes, update as soon as possible! In the event where you cannot do this, we strongly recommend leveraging the Sucuri Firewall or equivalent technology to have the vulnerability patched virtually.

  1. Hey Marc,

    Thanks for reporting this to us properly and allowing us to take care of the issue quickly! We appreciate the direct communication.

    For users, if you’re on version or higher, your site isn’t vulnerable.

    Thanks again!

    1. I gotta say I had a good experience reporting this vuln to you guys, loved how you quickly handled the whole process.. Definitely a good example for all developers to follow. 🙂

  2. As always, Thank you Sucuri for your diligence and efforts to keep our websites safe. Thank you WP Ninjas for fixing this quickly. I depend on your forms and have updated my sites.

  3. Already seeing a huge uptick in bot registration attempts on the one wordpress website where this plugin is in use.

  4. Hi, I am using Sucuri Firewall in some of my blogs. But i have been with a very tough and disturbing issue with all of my blogs.
    The Issue is: I see someone is posting spamy posts like “movie torrent, downloads etc” to my blogs and that too using my own administrative account. First i suspected a plugin named “WP Core 3” and i deleted the plugin but somehow the plugin used to get installed automatically no matter how many times i deleted them.

    I tried reinstalling one of my new blog (replacing with new files except wpconfig and wpcontents.) and deleted all the themes and plugins, then changed the SALT key. I thought the issue wont repeat with this blog now. But unexpectedly it happened again. 🙁
    Can i get some suggestion to get this issue fixed forever. I searched google but no effective results were found.

  5. You mention in the article that: “WordPress … automatically escapes $_GET, $_POST and $_REQUEST when booting up”. Can you give a reference or send more details on that ?

  6. Thanks! I did wonder why $_POST args have slashes before quotes in wordpress…
    But why is this useful ?
    Database queries should be performed using prepared mysqli_stmt that escape this these arguments, right ?

Comments are closed.

You May Also Like