Google

Drupal 7 SQL Injection (CVE-2014-3704)

Written on:October 17, 2014
Comments
Add One

Introduction

This vuln has been getting a lot of attention, and rightfully so. The good news is an update is available (and a supplemental patch has been released as well). The bad news is that it’s pre-auth SQLi. The basic problem is the way Drupal core 7.x versions prior to 7.32 construct a SQL query. Contrary to some claims, this is not a flaw in the use of prepared statements/parameterized queries, which are still viable options for preventing SQL injection. The flaw in this case manifests itself before the prepared statement is constructed and executed. Let me show you what I mean…

Basic Vulnerability Overview

The  public function query (found in ../includes/database.inc) looks as follows:

As you can see, it does use a prepared statement but before doing so calls the expandArguments function (also in database.inc). Here’s an excerpt of that function:

Notice how the function parses the $args through the array_filter function before incorporating them into the query via the preg_replace function. This doesn’t pose a problem if the passed arg is not represented as an array with a defined key. For example, during login, the name parameter is passed as follows:

drupal_sqli_0

In the case of this login function, the query would be constructed as follows:

SELECT * FROM {users} WHERE name = :name AND status = 1

However, what happens if we were to pass the user parameter as an array with a defined key? Here’s the query after being processed by expandArguments when passing name[0] instead of name:

SELECT * FROM {users} WHERE name = :name_0 AND status = 1

As you can see, it incorporated the key value (0) directly into the sql query (by concatenating it to the parameter name with an underscore). Knowing this, we can inject crafted key values to execute SQL injection attacks. Since the login function is vulnerable, this is a pretty significant pre-auth vulnerability.

Here’s an example of how this could be used to add a user to the database:

drupal_sqli_3

Here’s a look at this query before being processed by the vulnerable expandArguments function:

SELECT * FROM {users} WHERE name = :name AND status = 1

And after…

And the result…

drupal_sqli_4

This being SQL injection, there are other options for exploit including data extraction. For example, here is an example of a pre-auth inference-based attack that extracts the admin user’s password hash.

drupal_sqli_2

Of course, success will depend on flood control and other brute-force protections employed by the site.

PoC Test Exploit Code and Video

Here’s a PoC script if you want to try the exploit for yourself on a test instance. All it does is add an admin user with password ‘pwnd’. There’s really no verification in this basic PoC script that a user is actually added so you’ll need to log in to check. A quick video demo follows.

 

Here’s a really short video demo of the above PoC code:

Conclusion

So what are the takeaways here? Well, of course upgrade or patch your installation of Drupal if it’s vulnerable. Also, while prepared statements are important tools in preventing SQL injection, they don’t do much good if you incorporate untrusted user input into the SQL query first!

If you haven’t patched yet, you may want to check your logs. The exploit may trigger an error message that looks something like this:

drupal_sqli_5

 

Check your Drupal logs for similar error messages which may indicate attempted or successful exploit attempts and look for any new accounts that may have been created or admin accounts whose passwords may have been changed recently.

2 Comments add one

  1. zhilevan says:

    This code work only on local website (the web server has config simply), I try it in many site that I am sure their drupal version is greater than 7 and below 7.32 with simple cpnael but not worked .

    Can you tell me why not worked ?

Leave a Comment

Your email address will not be published. Required fields are marked *