Right now, since all settings.php files are owned by the www-data user, sites can read each other's database settings. That's a security issue that can be worked around using various techniques described in:

http://groups.drupal.org/node/12066

In any case, I feel that hostmaster should have plugins to manage permissions on those files depending on the technique chosen.

CommentFileSizeAuthor
#7 libnss-mysql.cfg_.txt1.46 KBanarcat
#5 libnss-mysql.txt1.33 KBanarcat
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

anarcat’s picture

Priority: Normal » Critical

We want to at least move the db_url into the apache environment so that sites can't access each other's databases. They will still see private file uploads and things like that, but at least damage is limited for 0.1.

adrian’s picture

The issue we have then is we can't rely on the settings in settings.php to install / synch / disable / etc sites.

This is an issue since we are only interfacing with drupal in command line mode. In HM1, i was parsing the vhost and setting up _SERVER vars by hand, but that was a hack. In this case i think we might need to use site.php instead of the vhost.

anarcat’s picture

Then maybe we just need to bite the bullet and properly setup file permissions and setup vhosts with fastcgi and proper permissions...

anarcat’s picture

Status: Active » Needs work

I have made a lot of progress here.

I have built a hosting_itk and provision_itk modules that creates a vhost configuration file for the Apache ITK module. It's *almost* working: the file is created properly (through a new hook_provision_vhost_config()), the web_group is modified to be 5000 (hardcoded for now) + the client_id, and the webserver actually runs as that group. The only problem at this point is that the hosting task refuses to fix the permissions properly:

Could not change group ownership of settings.php to 5001 (the group does not exist)

That would be actually true if I didn't make any other modification to my system. But I also experimented with libnss-mysql. I installed the libnss-mysql-bg package, which allows UID/GID <-> name mappings to be performed by MySQL. I have configured it to consult the Drupal 'users' and 'hosting_client' tables, the latter being the "group" "users" are part of...

It works on the command line:

mumia:/var/hostmaster/drupal-5.x/sites/testitk11# chgrp 5001 settings.php 
mumia:/var/hostmaster/drupal-5.x/sites/testitk11# ls -l settings.php 
-r--r----- 1 hostmaster Administrator 1820 nov 28 00:44 settings.php

Of course that's as root. If I add the "hostmaster" user to the "Administrator" group, it also works:

mumia:~/drupal-5.x/sites/testitk11# echo Administrator:x:5001:hostmaster >> /etc/hosts
mumia:~/drupal-5.x/sites/testitk11# su hostmaster
mumia:~/drupal-5.x/sites/testitk11$ chown :5001 settings.php 
mumia:~/drupal-5.x/sites/testitk11$ 

Note that I had to patch provision.path.inc so that it would take regular UIDs:

--- provision.path.inc	13 nov 2008 17:17:47 -0500	1.13.2.3
+++ provision.path.inc	28 nov 2008 00:42:56 -0500	
@@ -183,10 +182,11 @@
   return provision_posix_username(fileowner($path));
 }
 
-function provision_path_chgrp($path, &$group, &$reason) {
-  if ($group = provision_posix_groupname($group)) {
+function provision_path_chgrp($path, &$gid, &$reason) {
+  if ($group = provision_posix_groupname($gid)) {
     if (provision_user_in_group(PROVISION_SCRIPT_USER, $group)) {
       if (chgrp($path, $group)) {
+        $gid = $group;
         return $group;
       }
       else {
@@ -197,7 +197,7 @@
       $reason = t("@user is not in @group group", array("@user" => PROVISION_SCRIPT_USER, "@group" => $group));
     }
   }
-  else {
+  elseif (!@chgrp($path, $gid)) { # try to change the group anyways
     $reason = t("the group does not exist");
   }
 

That hack is kinda crude and I probably should load that client and find its name, and chgrp on that, which may work.

I also needed this patch to make the settings.php fixed with the right perms:

--- provision_drupal.module	27 nov 2008 23:54:10 -0500	1.37.2.23
+++ provision_drupal.module	28 nov 2008 00:42:44 -0500	
@@ -83,7 +83,7 @@
   provision_path("chmod", "sites/$url/settings.php", 0440,
     t('Changed permissions of settings.php to @confirm'),
     t('Could not change permissions of settings.php to @confirm'));
-  provision_path("chgrp", "sites/$url/settings.php", PROVISION_WEB_GROUP,
+  provision_path("chgrp", "sites/$url/settings.php", $data['web_group'],
     t('Change group ownership of settings.php to @confirm'),
     t('Could not change group ownership of settings.php to @confirm'));
 }

... not sure this is right, though..

Anyways, long story short, this works in principle, but there are implementation problems at this point. There also may be performance problems, but I would need a much larger test scenario here.

Note that the libnss configuration is minimal:

mysql> grant select on hostmaster.hostmaster_client to nss@localhost identified by '2JV2OHuO1dxb';
mysql> grant select on hostmaster.users to nss@localhost identified by '2JV2OHuO1dxb';

I also include my configuration file.

Bottomline:

* works (or "should work" if it wasn't for PHP/provision.path.inc) as a module, marked as experimental
* depends on user/client relationship
* there will need to be a hostmaster users that is a member of every group for this to work
* needs benchmarking

anarcat’s picture

FileSize
1.33 KB

Stupid drupal.org refused my file...

anarcat’s picture

I have committed some changes to provision described above so that ITK can work out of the box with HEAD.

I have also committed nodeapi hooks that automatically add the hostmaster user to the right groups when they are created.

I need to test all this.

anarcat’s picture

FileSize
1.46 KB

the gid listings were broken in the nss configuration, here's an updated (fixed) config.

anarcat’s picture

I have imported ITK into provision HEAD now, but issues remain. Even though I committed code regarding that in hosting_itk, I still can't find a way to elegantly add the hostmaster user to every group created. Mainly because the Drupal users start at 1, so I have to add a "base uid" offset (GID_BASE, hardcoded to 5000 right now). This then means that the hostmaster user cannot be in that database because it's very likely to be created with a lower UID than GID_BASE. And anyways, the 'hostmaster user' isn't in the Drupal user database in the first place.

So in short, it's pretty hard to fix group memberships with 'real' unix users (in /etc/password) and groups define in the mysql database without some major hooplas. I even tried to make the hosting_client_user table to be unsigned, but that doesn't change anything because the libnss looks into the users table even for group lookups.

So the problem remaining still:

  • The hostmaster (PROVISION_SCRIPT_USER) user need to be part of every 'client group' (originally PROVISION_WEB_GROUP, now the client is a group) created out there. Just adding to the hosting_client_user table isn't enough.
  • The system needs some benchmarks and testing

The symptom right now is this:

Could not change group ownership of settings.php to 5390 (the group does not exist)

In fact, it's not that the group does not exist: it's that hostmaster isn't part of the group and therefore cannot change the ownership to that group. Example:

$ chgrp 5390 settings.php
chgrp: modification du groupe de `settings.php': Opération non permise

Right now, I see only two remaining solutions:

  • run provision tasks as root
  • use sudo where necessary (chmod for the settings.php and private files , backups, etc...)

This is rather unfortunate and a major blocker at this point.

anarcat’s picture

Another solution would be to put the hostmaster user directly in the mysql database, as a real drupal user, and then manage permissions properly.

adrian’s picture

Version: 5.x-0.1-beta2 » 5.x-0.2.x-dev
Priority: Critical » Normal

Not needed for 0.2 release.

anarcat’s picture

Title: security between sites » security between sites (settings.php protection)
Version: 5.x-0.2.x-dev » 6.x-0.4-alpha3
Status: Needs work » Fixed

This has actually been worked around pretty well by storing the credentials in the Apache environment, so I will close this for now. The rest of the discussion can happen in the broader #762138: Design security issue with developer access to sites' modules and themes.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.