Lock account users to public_html via mod_ruid2's RDocumentChRoot directive

cPanelTristan

Quality Assurance Analyst
Staff member
Oct 2, 2010
7,607
43
348
somewhere over the rainbow
cPanel Access Level
Root Administrator
[Issue]

Under the current implementation of file permissions under Linux-based systems, it is possible for scripts to show the contents of files outside their home directory in a browser such as trying to use "cat /etc/passwd" and obtain a full listing of the system's users. This is not a security issue found only in PHP, but can be exploited by other scripting languages as well.

[Proposed workaround]

On a machine using DSO + mod_ruid2, the RDocumentChRoot directive allows the user's document root to be restricted to /home/$user/public_html location, which prevents calling files or directories out of that path. Since mod_ruid2 handles all processes run by Apache to that user, all scripting languages used on the user’s account would be restricted by mod_ruid2’s RDocumentChRoot setting (this is unlike mechanisms used only via PHP to restrict such access).

[Steps to install mod_ruid2 in cPanel 11.31+ versions]

1. Go to WHM > EasyApache (Apache Update) or run /usr/local/cpanel/scripts/easyapache in command line
2. Check Mod Ruid2 under Step 5's Short Options List
3. Select "Save and Build"

[Steps to add RDocumentChRoot for existing accounts]

All commands noted would be run in root SSH command line

1. Add the userdata include folders

Code:
for i in `cat /etc/trueuserdomains | cut -d: -d' ' -f2-` ;do mkdir -p /usr/local/apache/conf/userdata/std/2/$i ;done
2. Add the RDocumentChRoot directive for each existing user

Code:
for i in `cat /etc/trueuserdomains | cut -d: -d' ' -f2-` ;do echo "RDocumentChRoot /home /$i/public_html" > /usr/local/apache/conf/userdata/std/2/$i/ruid2_chroot.conf ;done
3. Check all the includes are functioning

Code:
/usr/local/cpanel/scripts/verify_vhost_includes
4. Update all users to add the includes into httpd.conf file

Code:
/usr/local/cpanel/scripts/ensure_vhost_includes --all-users
5. Restart Apache

Code:
/etc/init.d/httpd restart
[Steps to add RDocumentChRoot for new accounts]

All commands noted would be run in root SSH command line

1. Create the postwwwacct file

Code:
touch /usr/local/cpanel/scripts/postwwwacct
chmod +x /usr/local/cpanel/scripts/postwwwacct
2. Add the following content to that file

Code:
#!/usr/bin/perl

my %OPTS = @ARGV;
$ENV{USER} = "$OPTS{'user'}";
system q(mkdir /usr/local/apache/conf/userdata/std/2/$USER/);
system q(echo "RDocumentChRoot /home /$USER/public_html" > /usr/local/apache/conf/userdata/std/2/$USER/ruid2_chroot.conf);
system q(/scripts/ensure_vhost_includes --user=$USER);
system q(/etc/init.d/httpd restart);
3. Try creating a new account to check that /usr/local/apache/conf/userdata/std/2/username exists where username is the new cPanel account created.

[Important Notes]

The following were tested and still function upon restricting the user to /home/username/public_html

1. phpinfo pages and basic PHP scripts
2. Ruby on Rails
3. cPanel > Optimize Website (mod_deflate)
4. cPanel > Password Protect Directories
5. Apache's mod_userdir

The following were tested and no longer function upon restricting the user to /home/username/public_html

1. Listing directories outside the user's public_html such as "cat /etc/passwd" in any script

Test script to use:

Code:
<?php
passthru( "cat /etc/passwd" ); 
?>
It will display a blank page after enabling RDocumentChroot on the account. Previously, it would list the server’s /etc/passwd contents.

2. PHP's open_basedir

Enabling open_basedir in PHP will cause the following example type warnings on a page

[12-Jan-2012 10:17:23] PHP Warning: Unknown: open_basedir restriction in effect. File(/username/public_html/php.php) is not within the allowed path(s): (/home:/usr/local/cpanel) in Unknown on line 0
[12-Jan-2012 10:17:23] PHP Warning: Unknown: failed to open stream: Operation not permitted in Unknown on line 0
[12-Jan-2012 10:17:23] PHP Fatal error: Unknown: Failed opening required '/username/public_html/php.php' (include_path='.:/usr/lib/php:/usr/local/lib/php') in Unknown on line 0
3. WHM > Web Template Editor > Default Website Page

Does not work as cgi-sys/defaultwebpage.cgi and img-sys are no longer in available paths to call

Other possible non-working components that were not yet tested

1. Tomcat
2. PHP's PEAR modules outside the user's public_html directory
 

rfxn

Active Member
Verifed Vendor
Apr 27, 2003
29
2
153
Re: Lock account users to public_html via mod_ruid2's RDocumentChRoot direc

I am excited to see mod_ruid2 integrated with easyapache, it is superior to suphp or mpm_itk in many ways, especially in performance and from a security standpoint for how it handles setuid/gid. Further, since it allows for php dso, one can leverage opcode cachers and native .htaccess php variables.

I currently utilize a script that installs mod_ruid2 outside of easyapache and am curious if the easyapache integration for the above sets the RUidGid option for each vhost such as the following example, in addition to the chroot parameter:
Code:
  <IfModule mod_ruid2.c>
    RMode config
    RUidGid rfxncom rfxncom
    RGroups nobody
  </IfModule>
In setting the above it ensures all content served from said vhost executes as the users user/group, this includes php and cgi's. As such apache suexec can be completely disabled which allows for its respective quirks to no longer be an issue, for example when trying to run php5.2 as a cgi along side php5.3 dso as default php handler.
 

rfxn

Active Member
Verifed Vendor
Apr 27, 2003
29
2
153
Re: Lock account users to public_html via mod_ruid2's RDocumentChRoot direc

Alright, so I updated my cpanel install to edge and in doing so now see the mod_ruid2 definitions in the apache templates ([ssl_]vhost.default).

What concerns me is the method for setting the RUidGid values, which is currently set as:

Code:
    <IfModule mod_ruid2.c>
        RUidGid [% vhost.user %] [% vhost.group %]
    </IfModule>
There are two modes in which mod_ruid2 can operate, as noted below from http://websupport.sk/~stanojr/projects/mod_ruid/:
1. stat
is default, httpd setuid and setgid to uid and gid of requested filename(script)/directory
this is good if you use mod_vhost_alias for virtual hosting

2. config
like mod_suid2, you must define uid and gid
Since the vhost template is not defining either mode with RMode, it is defaulting to the stat setup. This presents two issues.
  • The first is that it requires a stat on every HTTP request to check a file/directories uid/gid which impedes performance to an extent (although to what degree I am not sure, probably not by a huge margin).
  • The second and more concerning is that the default stat mode allows the ownership of a file/directory to dictate what mod_ruid2 will setuid/gid the request as, which is scary at best and at worse can lead to privilege escalation. In short, you are allowing a variable factor - the ownership of a file/directory, to dictate the privilege of the request.

The more sane option is to set RMode to config then mod_ruid2 will implicitly force all requests under that vhost to setuid/gid as the configured UID/GID for that vhost (RUidGid [% vhost.user %] [% vhost.group %]). This is more predictable behavior, forces user content to be owned by the user and removes the question mark associated with what a request will be setuid/gid as.

Proposed vhost template context:
Code:
  <IfModule mod_ruid2.c>
    RMode config
    RUidGid  [% vhost.user %] [% vhost.group %]
    RGroups nobody
  </IfModule>
One could argue you can also set the chroot parameter for mod_ruid2 in the vhost template but since that can break things as noted in your op, probably best left in an include file where it can easily be disabled on a case-by-case basis.
 
Last edited:

cPanelTristan

Quality Assurance Analyst
Staff member
Oct 2, 2010
7,607
43
348
somewhere over the rainbow
cPanel Access Level
Root Administrator
Re: Lock account users to public_html via mod_ruid2's RDocumentChRoot direc

We have /usr/local/apache/conf/mod_ruid2.conf file that has the following:

Code:
<IfModule mod_ruid2.c>
    RMode config
    RDefaultUidGid nobody nobody
    RUidGid nobody nobody
</IfModule>
This is loaded prior to the individual VirtualHost entries and should be used for all of them. We are forcing these to RMode config rather than defaulting to RMode stat. Here is the include line in /usr/local/apache/conf/httpd.conf file directly below the php.conf include:

Code:
Include "/usr/local/apache/conf/php.conf"
Include "/usr/local/apache/conf/mod_ruid2.conf"
If possible, it would be great to split your posts to a new thread, since my guide isn't about mod_ruid2 in general but about a specific directive for that module (RDocumentChRoot).
 

ChrisRHS

Well-Known Member
Jul 12, 2006
292
5
168
Re: Lock account users to public_html via mod_ruid2's RDocumentChRoot direc

Hello there folks,

I've been testing this for a couple of days now, and to be honest, I've had nothing but issues with mod_ruid2 and RDocumentChRoot. The first issue, MySQL is not able to connect through the localhost socket:

Code:
MySQL said: Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)
Now, I have overcome that issue, with setting up the "server" variable to be the IP of the server, instead of localhost, not the most ideal situation though.

The second issue, which I have not been able to rectify, is with RDocumentChRoot enabled, calls to external sites are broken. I found this out with my billing script (used curl), as it connects to check the license, and it locked me out, as it was not able to verify. I was able to ping the IP for the script from the server without issues, it was only with RDocumentChRoot disables that I was able to get the license activated again.

Third issue, .htaccess password protected directories are not working. It was previously set to use the /home/user/.htpasswds/yyy/ directory for the htpasswd file, and since this is now outside of the chrooted home directory, the user did not have access. I moved the htpasswd file into the public_html folder, and change the .htaccess files path to the the htpasswd file, yet it still gave a 500 error when trying to access. Another note on that, the 500 error was only logged as that, nothing more:

Code:
GET /support/admin/ HTTP/1.1" 500 9018
I've looked in many places for configuration help/settings for this module, there does not seem to be very much information out there regarding this one though. Not sure if anyone within the cPanel community has had these issues either. Running this without RDocumentChRoot just does not seem like a valid option, I would rather go back to running Worker/FCGID with suexec for speed and security.

Any help or hints regarding these matters would be appreciated!

Regards,
Chris
 

cPanelTristan

Quality Assurance Analyst
Staff member
Oct 2, 2010
7,607
43
348
somewhere over the rainbow
cPanel Access Level
Root Administrator
Re: Lock account users to public_html via mod_ruid2's RDocumentChRoot direc

I had previously tested password protect directories without issues using RDocumentChroot even though outside the document root because the public_html folder .htaccess contains the details for that authorization. I didn't see any issues with it working under my tests.

I'd have to re-test it again under our setup to see if I run into any issues in case we made changes after I tested it a few months ago.

As for the various issues noted, you will certainly run into some changes being required when switching to a security mechanism that locks a user inside the public_html directory. One option is to lock the user into /home/username instead of /home/username/public_html as I indicated in the guide might be the case for some people.
 

Stefan

Member
Jul 24, 2003
6
0
151
cPanel Access Level
DataCenter Provider
Re: Lock account users to public_html via mod_ruid2's RDocumentChRoot direc

I have a question about this setup:

- does it lock to the home directory scripts written in perl or other cgi scripts ? a simple script like above, to read /etc/passwd, but in perl?


Thank you

Stefan Ioan
 

cPanelTristan

Quality Assurance Analyst
Staff member
Oct 2, 2010
7,607
43
348
somewhere over the rainbow
cPanel Access Level
Root Administrator
Re: Lock account users to public_html via mod_ruid2's RDocumentChRoot direc

It should lock any scripts accessed by Apache in a browser to /home/username or /home/username/public_html location. I did not, however, test anything other than PHP for accessing outside of that location.
 

Ivan@rh

Member
Apr 23, 2012
9
0
51
cPanel Access Level
Root Administrator
Re: Lock account users to public_html via mod_ruid2's RDocumentChRoot direc

Had followed this tutorial and it killed clients' web sites. I wasn't able to find any error messages in apache logs and they were coming up with 500 server error. Surprisingly, some web sites were working, while others were not.

The scripts in this tutorial created folders and ruid2 config files. Right after restarting apache most of web sites go down, apache restarts ok.

/usr/local/cpanel/scripts/verify_vhost_includes did not report a single issue.

Would Tristan@cPanel be able to advise steps to debug the problem?
 

cPanelTristan

Quality Assurance Analyst
Staff member
Oct 2, 2010
7,607
43
348
somewhere over the rainbow
cPanel Access Level
Root Administrator
Re: Lock account users to public_html via mod_ruid2's RDocumentChRoot direc

When you received the Internal Server error, did you tail /usr/local/apache/logs/error_log for any error messages or tail /home/username/public_html/error_log for any possible error messages? If you didn't and know the time(s) you accessed the sites with the internal server error, please check the logs to see what shows up. There has to be some sort of error outputting at that point.

Also, are you already on mod_ruid2 with it working properly under DSO on these sites? If you were on suPHP and were only switching to DSO for this guide, you could be having issues relating to the change from suPHP to DSO instead.
 

xanubi

Well-Known Member
Jun 28, 2006
86
2
158
Re: Lock account users to public_html via mod_ruid2's RDocumentChRoot direc

This doesn't work anymore, since easyapache 3.12, because of the PHP "System Timezone -Use system timezone data in /usr/share/zoneinfo instead of PHP timezonedb".

Now php use /usr/share/zoneinfo and that's a problem for the RDocumentChRoot, because it's chrooted to the user public_html directory, giving a fatal error on all php scripts.
 

cPanelTristan

Quality Assurance Analyst
Staff member
Oct 2, 2010
7,607
43
348
somewhere over the rainbow
cPanel Access Level
Root Administrator
Re: Lock account users to public_html via mod_ruid2's RDocumentChRoot direc

You won't be able to select that option in EasyApache. Simply do not select to use that option and it does work.
 

xanubi

Well-Known Member
Jun 28, 2006
86
2
158
Re: Lock account users to public_html via mod_ruid2's RDocumentChRoot direc

I tried, i didn't select the option in this latest easyapache, but after i click continue, cpanel by itself TURN ON the option saying it must be turned on because of cpphp compatibility.
 

xanubi

Well-Known Member
Jun 28, 2006
86
2
158
Re: Lock account users to public_html via mod_ruid2's RDocumentChRoot direc

cPanelTristan, if possible, can you give a solution for that please?

I never choose the "System Timezone", but the system automatically turns that ON. What should i do?
 

cPanelTristan

Quality Assurance Analyst
Staff member
Oct 2, 2010
7,607
43
348
somewhere over the rainbow
cPanel Access Level
Root Administrator
Re: Lock account users to public_html via mod_ruid2's RDocumentChRoot direc

I suggest opening up a ticket if you aren't selecting to use the system timezone and EasyApache is automatically re-enabling it. You can do that in WHM > Support Center > Contact cPanel or using the link in my signature. It would be highly appreciated if you would post the ticket number here after opening one.

I had no trouble a few days ago when I was recompiling EasyApache in unselecting to use the system timezone, so I cannot reproduce the issue.
 

xanubi

Well-Known Member
Jun 28, 2006
86
2
158
Re: Lock account users to public_html via mod_ruid2's RDocumentChRoot direc

did you use easyapache from whm 11.32.27 right?
Can you post the options of your yaml file?

I'll put the ticket, but i would like to see your configuration, if is equal to mine. Thank you in advance, cPanelTristan.
 

xanubi

Well-Known Member
Jun 28, 2006
86
2
158
Re: Lock account users to public_html via mod_ruid2's RDocumentChRoot direc

Latest version i could now compile without the option being automatically choosen.

I've found many problem with that configuration, like in others said in this pos. For example the mysql problem (localhost).

I had to revert back.
 

cPanelTristan

Quality Assurance Analyst
Staff member
Oct 2, 2010
7,607
43
348
somewhere over the rainbow
cPanel Access Level
Root Administrator
Re: Lock account users to public_html via mod_ruid2's RDocumentChRoot direc

The MySQL issue simply requires using 127.0.0.1 for scripts to connect rather than localhost if using RDocumentChRoot

Security is going to have drawbacks. If you want something to be more secure, you need to find workarounds after setting it up. If you told users to use 127.0.0.1 rather than localhost, then that issue itself is no longer one. Other issues could be worked through, but you shouldn't be testing this on production anyway.