Improvements to Security in Drupal 7

Drupal 7 has several security improvements. People often ask if the book Cracking Drupal covers Drupal 6 or Drupal 7. The answer is that it mostly covers both because security issues did not change much between the versions. So the book is still just as relevant for Drupal 7 with the exception of the topics below. The only other major topic the book doesn't cover is CSRF, but you can read an article about Protecting Drupal from CSRF .

New Database API reduces opportunity for SQL Injection

SQL Injection makes up roughly 10% of the vulnerabilities that have been found in Drupal core or contributed modules. A lot of the times this comes from people not using query placeholders, using the wrong placeholders, or trying to build dynamic queries without properly filtering user inputs. The new database API solves these three problems:

  • It is based on object oriented system so people are taught to use the placeholder system by default
  • It completely re-thinks how placeholders work making it so the right placeholder will be automatically inserted wither your argument is a number, string, or an array of data.
  • It makes it much easier to do dynamic queries - See Jeff Eaton's post for details

It's still possible to create SQL Injections in Drupal 7, of course. The first is to use the ->where() method of conditional clauses which "allows for the addition of arbitrary SQL as a conditional fragment." If your code can insert arbitrary SQL then it can insert a SQL Injection. The other way is to simply use db_query for a static query but put concatenated user input into the query string. Luckily both of those things are easy to spot in a review and will soon become red-flags for every code reviewer.

As you can see, the redesigned database API is much less likely to be used incorrectly. I believe we'll see a decrease in SQL Injection vulnerabilities as Drupal 7 is adopted.

Improved hashing algorithms

We moved away from the increasingly crackable md5 hashing algorithm for all hashes. Passwords are now hashed with a user specific salt which makes them harder to crack. By default they are hashed 2^15 times, though you can control that number by setting

<?php
$conf['password_count_log2'] = 16;
?>

or whatever other number you choose. The benefit of setting that variable in your settings.php is that it is not in the database so a malicious user attempting to crack a password would have to try hashing it a different number of times. This provides several benefits. It makes it very difficult to reverse engineer the passwords associated with accounts/emails if a database backup is exposed to the world or a SQL injection is found. It also makes it harder for developers to make mistakes when building an external authentication mechanism since they are practically forced to use the password/user API.

The password hashing mechanism is based on phpass and is compatible with other systems that use that system. This is helpful if importing users from another site or exporting users from one version of Drupal to another.

There is now a site specific salt called

<?php
$drupal_hash_salt
?>

that lives in the settings.php in addition to the site specific key called drupal_private_key which is stored in the database. These private key values can be used to increase the strength of hashed/encrypted data.

If you just install Drupal it wil create a drupal_hash_salt value for you, but if you want to use a different one that is managed outside of your settings.php you can simply edit the settings.php prior to installation and set the

<?php
$drupal_hash_salt = file_get_contents('/home/example/salt.txt');
?>

. The salt.txt file should be somewhere that the webserver can read, but is not generally available to other users on your unix system. It should be read-only for the webserver. The permissions on settings.php should give a good guide for how to set the salt.txt permissions. The file should contain a string of randomly generated information. Random.org can give tips on how to create random strings.

These improvements are more about hardening Drupal to stay "current" than it is about reducing any specific vulnerability.

Drupal 7's built-in brute force detection

Drupal 7 also includes brute force login attack prevention. This was possible in Drupal 6 via solutions like the Login Security module but now it's part of core. This feature was added in the issue to Improve security: rate limit login attempts which does not provide a specific user interface to the feature. It does, however, have four important variables. The first two are for limiting the failed logins by IP: user_failed_login_ip_limit which defaults to 50 and user_failed_login_ip_window which defaults to 3600 seconds (i.e. one hour). The second set are for limiting failed logins per user: user_failed_login_user_limit which defaults to 5 attempts and user_failed_login_user_window which defaults to 21600 seconds (i.e. 6 hours).

Easier module updates: plugin manager

One of the persistent problems with security releases is getting sites upgraded. If the patch is out but nobody has installed it then it doesn't help. Drupal 7 includes the ability to install or update modules via the administrative interface making it much easier to keep a site up to date. This process uses ssh or ftp in a local loopback to access the files so that the webserver doesn't have to have the ability to write files. This, of course, can be seen to have drawbacks. The ideal way to manage this is as a separate user and keep close tabs on the proper file permissions and the web-based installer promotes some bad practices (e.g. leaving FTP running). I think this feature is good for some sites and hope people will use it to keep their sites up to date. If you are scared of the practices it allows then I suggest you disable it by going into settings.php and uncommenting this line at the bottom to disable the feature.

<?php
$conf['allow_authorize_operations'] = FALSE;
?>

Drupal.org improvements in security coincide with Drupal 7 release

Drupal 7 was released in January of 2011 and the git migration wrapped up in March of 2011. The move to git helps module maintainers to create a new release of their module based on an old tag without having to do gymanistics in CVS. This will allow security releases to contain ONLY security fixes which will help site builders to deploy those changes quickly. Site builders will be able to QA the change much more rapidly and worry less about features and bugfix changes in the code that might break their site.

Knowing security is a process, we have also made improvements to our security advisory process. The security.drupal.org site is where the Security Team collaborates on issues. It now provides access to an issue for issue reporter and module maintainer to make collaboration with the team easier. This should increase the free time the Security Team has to work on other items, and for maintainers it will increase the ease of interacting with the Security Team making them more likely to get the fix released properly. We also are using a template for writing the Security Advisories. This process increases the quality of the advisories and lets module maintainers write them directly without needing nearly as much help from the security team. Again, that's a big help to both the Security Team and the module maintainers.