SugarCRM and mod_ruid2

We tried suPHP on our servers for a short time. What suPHP does, is run PHP as the same user as owns that website. It will then only execute PHP scripts that are owned by that same user, and are not writeable by the group, i.e. not writeable by any other user. The idea of this on shared hosting, is to prevent one account writing PHP scripts in another account where the directory permissions have been left wide open, and then being able to execute those scripts through the HTTP interface.

The okay is okay at first glance, but does have a flaw. The scripts are all run as the same user that you FTP the PHP application as. The web user owns all the PHP scripts in the application. You may be protected fromĀ other users, but if a hacker gets into your site just by one back door or flaw, he can run riot with all your scripts, since he owns them and can change anything. By taking away the permission to change those files, you also take away the permission to execute those files at all, so you are stuck between a rock and a hard place. This would not do.

The more traditional way to run a PHP application, is to upload your files as an FTP user, then have them executed as a shared apache user – either apache or in older times nobody. This way you have more control of permissions and can decide which files in your application apache can read and write to, and which directories it has access to. The downside is that giving apache permissions to access files or write to a directory means giving everyone access to do so, which is especially dangerous on a shared hosting server.

One solution is a hybrid – mod_ruid2.

What mod_ruid2 does, is to give you control over which user a PHP process will run as. Note that your application will still be initially accessed by apache, so apache still needs to be able to read directories, the contents of .htaccess files and it needs access to non-PHP files (such as JavaScript and CSS files), but the moment it finds it needs to run a PHP script, the process will switch to another user.

This is how we would set a site up:

The site would have two Linux users: one to manage FTP and ssh into the site, and the other to run the PHP web scripts. A user group would be set up and both these users would be added to the same group. So for mysite.com, the users may be:

  • ftpmysite
  • webmysite

Only ftpmysite would have a home directory. webmysite would have no home directory and no shell set up.

The group wound be:

  • mysitegrp

I’ll list the Linux commands for setting this up later.

Now we need to tell mod_ruid2 to run any PHP scripts on this site as webmysite. This is done by adding an entry to:

/etc/httpd/conf.d/ruid2.conf

 

<Directory /httpdocs>
   RMode config
   RUidGid webmysite mysitegrp
</Directory>

The application is then uploaded to the web space as user ftpmysite. We then need to check permissions of the uploaded application:

  • Firstly all directories that contain web-accessible resources or scripts must have read and execute permission for “other”, for everyone.
  • Any .htaccess file must also be readable by “other”.
  • Any non-PHP resource such as JavaScript files, that need to be web-accessible, need read permission for “other”. The PHP scripts do not need that; they only need to be readable by the “group”.
  • Any php script needs read permission for “group”.

So when a PHP script is executed, the PHP process will run as webmysite. That user is a member of the mysitegrp group, and so can read that file.

The PHP script that runs as webmysite, may also need to create files on the server. This is where problems arise with SugarCRM.

SugarCRM makes heavy us of the “cache” directory. It will put PHP scripts in there for executing, and also web-accessible resources such as images and CSS files. By default SugarCRM will create files with this permission:

  • 0660 – read/write for owner and group; nothing for anyone else.

It will also create folders of this permission:

  • 02770 – read/write/list for owner and group; nothing for anyone else.

Remember, these files are being created by the webmysite user. The permissions lack two things:

  • Apache cannot scan the directories in the first place, so cannot find any of these files if it needs to. It will not be able to find any of the web resources in the cache.
  • Apache will not be able to read any of the files, even if it could find them. It cannot read .htaccess files, for example, or a JavaScript file for delivery to the browser.

This is fixed in a setting that can be configured in SugarCRM. Here is the default, from config.php:

$sugar_config['default_permissions'] =
 array (
 'dir_mode' => 1528, // == 02770
 'file_mode' => 432, // == 0660
 'user' => '',
 'group' => '',
 );

The permissions are bizarrely given in decimal. I’ve provided the octal equivalents. Copy this to config_override.php and change the permissions as follows:

  $sugar_config['default_permissions'] =
  array (
    'dir_mode' => 02775,
    'file_mode' => 0664,
    'user' => '',
    'group' => '',
  );

Once you have saved the permissions once, this array will be expanded into a separate line for each element, and will look like this:

$sugar_config['default_permissions']['dir_mode'] = 1533;
$sugar_config['default_permissions']['file_mode'] = 436;

That explains where the integers come from in the permissions settings – they are system generated. Remember to convert them back into octal before trying to understand exactly what those permissions do.

With this configured, directories generated in the SugarCRM cache area will gain the read and execute (aka list) permission for everyone, and files will gain read permission for everyone. Ideally, read permission is only needed for web accessible resources, and not for PHP scripts in the cache, but without some changes to core SugarCRM there is not a lot we can do about that (SELinux may offer some solutions here, but that is a whole different area altogether).

TODO: Linux commands to set up the users and groups. What the sticky bit does. Come and kick me if I haven’t finished this off!

5 Responses to SugarCRM and mod_ruid2

  1. John 2013-10-04 at 10:11 #

    Hi there,
    Interesting article. I’m particularly interested in the default_permissions part in config_override.php.
    I’ve tried to figure this out in the past, but always had the feeling that my settings weren’t being respected. e.g. when I upload a module which then gets saved in /upload/upgrades/module.

    Could you explain what you mean with “Once you have saved the permissions once, this array will be expanded into a separate line for each element, and will look like this:” ?
    I tried this, saved config_override.php and did a quick repair, but the array was not expanded by sugar and not converted to decimal.
    It would be very beneficial to have this behavior work, as sugar would do the conversion from octal to decimal for me and I could be sure that I didn’t screw up the numbers…

    Thanks for your comments!
    John

    • Jason Judge 2013-10-04 at 10:22 #

      It feels like I wrote this years ago, so I’m digging into the depths of my memory.

      I think I probably meant, once you have saved the configuration settings in the main config settings page of the SugarCRM application.

      What happens is that SugarCRM will ready the config file into memory, make any updates you have set, then write the file back out to disk. When it writes it back, it will do so in a different format. So you enter settings that make sense to us humans, but when you go back to look at it again, SugarCRM has turned it into something that makes a lot less sense to us, but is exactly equivalent to the application.

      My comment about it was just wondering why SugarCRM didn’t write those numbers back as octal, so you can easily amend them. But that’s just the way it is.

      • John 2013-10-04 at 10:48 #

        Ok, I didn’t realize that. So i can force Sugar reading my changes by opening and saving the main system settings page in Admin? That’s good to know.

        thanks,
        John

  2. John 2013-10-04 at 10:44 #

    One more thing: Even if I enter those two expanded lines directly in config_override.php with [‘file_mode’] = 436;

    It still creates files with permissions 644 instead of 664.

    Is this a cache issue? What other than quick repair might get this working?

    thanks,
    John

    • John 2013-10-04 at 10:56 #

      I just tried your method, entering it in octal and have sugar convert it. The conversion worked after I opened and saved the system settings page in admin.
      But modules that I upload in admin are still saved in /upload/upgrades/module/ with permissions 644!
      So no change in sugar behavior. beats me.

Leave a Reply