Security and the global user object

I'm starting to go through the book Cracking Drupal by Greg Knaddison. The book is written primarily for developers and seems to cover a broad range of security topics specific to Drupal and lots of topics that apply to any web-based application.

Over the next week, I'll post some of the best gems I find in the book.

In this post, I'll share an issue I've seen a few times with the global user object.

When a user is logged into a site (or even if they are anonymous), their user information is stored in a global PHP variable called $user. If you're familiar with Drupal code at all, you've probably seen the global user object called in many functions, usually something like this:

<?php function some_function() { global $user; // Do something } ?>

As a global variable, the $user object can be easily accessed by any function. The downside is that this variable can be very easily modified, even unintentionally.

A while back, I was working in a team environment on a development server, in which everyone was making changes to the site at the same time. To do debugging, developers would add a simple conditional to their code to output debug information, that only they would be able to see.

<?php global $user; if ($user->id == 3) { print_r($data); } ?>

Quick and dirty, and it gets the job done. However, one day, everyone noticed that their login name changed suddenly to one of the other developers. After, some investigation it was discovered that a minor typo caused every user of the site to be logged in as the developer who had made the typo.

Here is what they had typed instead of the example above:

<?php global $user; if ($user->id = 3) { print_r($data); } ?>

By using a single equal sign (=) instead of a double (==) they changed the conditional from a comparison to an assignment.

If you've ever used a similar practice in a team environment, or if you are a daring soul who does this kind of debugging on a production site, I would suggest creating a function specific to this purpose so you are less likely to cause trouble.

<?php // Only print debug info to a specific user function user_debug($data, $username) { global $user; if ($user->name == $username) { print_r($data); } } ?>