Drupal 7.31 pre Auth SQL Injection Vulnerability

A vulnerability in Drupals handling of SQL queries allows SQL injection and remote code execution.

Introduction

/images/drupalgeddon_small.png
Drupal is an open source content management platform powering millions of websites and applications. It’s built, used, and supported by an active and diverse community of people around the world.

Drupal 7 is used by a vast number of sites and all of them are vulnerable.

During a sourcecode audit for a customer we found an SQL Injection Vulnerability in Drupal's core handling of SQL queries, which we disclosed to the vendor. With this bug an attacker can gain full control over all Drupal sites (Admin privileges), without knowledge of internals or authentication on the site. He can even execute PHP Code without leaving a trace in any log.

The Bug was introduced in early 2011 and stayed well hidden in the core framework.

In this post we will discuss the SQL Injection on a higher level. If you want all technical details please refer to the Advisory we released

We will wait until enough sites had time to update before we release a PoC, since this is a severe bug, which allows an attacker to execute arbitrary code with only one HTTP request and no knowledge of the site whatsoever.

The Vulnerability

All database queries in Drupal are handled via prepared statements. Placeholders are used in the SQL queries to indicate where user input should be included:

SELECT * FROM {users} WHERE name IN (:name_0, :name_1)

This prepared statement is called with a binding to variables for :name_0 and :name_1. This way an attacker cannot alter the SQL query, since he cannot inject values into the prepared statement. The number of placeholders has to be correct. Therefore Drupal uses a function to expand :name to :name_0, :name_1. This function handles the arrays incorrectly and expands the array to :name_$key0, :name_$key1. If the attacker can control the $key0 and $key1 he can manipulate the SQL query to look like this:

SELECT * FROM {users} WHERE name IN (:name_test) OR name = 'Admin' -- , :name_test)

which results in an SQL injection, where the attacker has full control over the database. He can dump all data, delete the whole database or create new users for example.

If the user can control the database, he can insert values to gain remote code execution on the web server by using Drupal features with callbacks.

Stefan Horst