Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I work with the systems administration at a university and just stumbled across something which is probably common, but was quite a shock to me.

All public_html directories and web areas are stored on afs, with read permissions for the web servers. Since users are allowed to have php scripts in their public_html, this means that they can access each others' files from within php (and the main web files!).

Not only does this render any .htaccess password protection completely useless, it also allows users to read php source files containing mysql database passwords and similar sensitive information. Or if they find that other people have directories where the web servers have write access (e.g. for personal logs or to save submitted form data) they can store files in those accounts.

A simple example:

<?
  header("Content-type: text/plain");
  print file_get_contents("/afs/example.com/home/smith/public_html/.htpasswd"); 
?>

Is this a common problem? And how do you typically solve it?

UPDATE:

Thanks for the input. Unfortunately, it seems there is no simple answer. In a big shared environment such as this, users should probably not be given this much choice. The best approach I can think of is to set "open_basedir" in the main configuration for all "public_html" directories, run suphp and only allow clean php (no cgi scripts, running external commands with backticks etc).

Changing the policy like this would break a lot of things though, and quite possibly make users grab their pitchforks and chase us... I will discuss it with my colleagues and update here if we make a decision on how to change the setup.

share|improve this question
    
This is an interesting question. I'm sure on major shared hosting providers (e.g. DreamHost), this is not possible. But I'd be interested in how they protect from this. suphp, as cstamas mentioned, looks like a good solution, but is this what most hosting providers use? –  Lèse majesté Jun 22 '10 at 19:21
1  
I've used the open_basedir solution below on production shared hosting systems, but we split everyone into their own vhost -- Not sure if it works for single directories... –  voretaq7 Jun 23 '10 at 14:58
add comment

4 Answers

up vote 7 down vote accepted

One can use suphp which runs the php script with the uid of its owner.

http://www.suphp.org

share|improve this answer
    
This will probably not solve the above problem (at least in a shared hosting environment .htpasswd files are usually owned by the user who owns the site and group(apache) or world(because users don't know/care about security) readable, so even with suphp they would be able to read those files) –  voretaq7 Jun 22 '10 at 14:57
    
@voretaq7: Several other restrictions can be applied. As far as I remember you can even deny access to files you do not own. So this rules out the attack above. –  cstamas Jun 22 '10 at 15:13
    
I know you can restrict permissions on files ("Can't be writable by group/other/anyone"), but I don't know of a way to block reads beyond FS permissions. They have check_vhost_docroot, but AFAIK that only applies to the script being executed (? I could be wrong on that) –  voretaq7 Jun 22 '10 at 15:30
1  
I'm not sure if suphp is a good solution in an environment like this. A user may have all sorts of permissions that the www-user does not have. An attacker which found a way in through php could find ssh keys or keytabs, or change a users' login scripts to create backdoors. And "vhosts" settings are not that helpful since public_html directories are available through "/~username" on the main virtual host. I'm thinking maybe scripts in public_html should be completely disabled. –  Pontus Jun 23 '10 at 12:38
add comment

My suggestion would be to limit PHP's access to files (via open_basedir & similar directives, on a per-vhost basis): You want users to be able to open/read/write files under their webroot, and perhaps one level above it (for scratch space), but not a directory where they would be storing e.g. htpasswd files.

A directory structure like:

/Client
    /auth
    /site
        /www_root
        /www_tmp

Would meet this requirement: open_basedir could be pointed at /Client/site safely, and htpasswd files stored in /Client/auth (with .htaccess files or httpd.conf modified to point at the appropriate location instead).
This prevents your clients from opening anyone else's files, AND as a benefit malicious users can't read the stuff in /Client/auth (or anything else on your system, like /etc/passwd :-)

See http://php.net/manual/en/ini.core.php for more details on open_basedir & per-vhost implementation.

share|improve this answer
1  
suphp as noted by cstamas is also a really good idea in a shared hosting environment -- There is a little overhead getting it set up, but I would say the security gain is totally worth it. Short of sandboxing all of your PHP sites in something like a FreeBSD Jail or a dedicated virtual machine that's one of the biggest security wins. –  voretaq7 Jun 22 '10 at 15:05
    
"open_basedir" seems to be a simple way to separate the main web files from the user ones, provided that "public_html" is served through it's own virtual host. But it doesn't protect the users from each other, since they don't have their own virtual hosts. Right? –  Pontus Jun 23 '10 at 12:41
    
I haven't tried setting open_basedir inside a <Directory> directive, but I think it should be allowable ("try it and see" -- worst it can do is not work :) –  voretaq7 Jun 23 '10 at 14:55
1  
So far it looks like open_basedir is what most commercial web hosts use (usually subscribers have their own paid domains or receive a free subdomain), but for directory-based homepages like in an academic institution, suphp seems to be the best answer. –  Lèse majesté Jun 23 '10 at 18:26
add comment

No it's not a common problem because most shared hosts would define a open_basedir config in the htaccess file in the public_html directory of each user (or in the vhost if each user has their own vhost).

e.g. of .htaccess file:

# Assuming these are not set globally - its good practice to limit:
  php_flag magic_quotes_gpc off
  php_flag magic_quotes_runtime off
  php_flag register_globals off
  php_flag short_open_tag off
  php_value max_execution_time 60

# These set the user-specific paths
  php_value open_basedir /afs/example.com/home/smith:/usr/share/php/include
  php_value session.save_path /afs/example.com/home/smith/tmp
  php_value upload_tmp_dir /afs/example.com/home/smith/tmp

But do make sure you set the right permissions on the .htaccess file to prevent the user changing the open_basedir (if they try to override it in subdir/.htaccess, it shouldn't work - but you should probably test this to make sure).

HTH

C.

share|improve this answer
2  
This might help to offer some initial protection of new accounts. But the fact that a user can't edit it may make it tempting to remove the .htaccess file (which they can do since it only requires write access to the public_html directory) and create their own. Adding a "<Directory>"-block in the main config for each user would work, but here they are still allowed to backtick external commands from php, which means open_basedir is easily circumvented. –  Pontus Jun 26 '10 at 11:18
    
@Pontus: good point about deleting the file (I'm not sure if afs supports the immutable file attribute). I'd have given +1 if you'd said that running the webserver in chroot jail would protect against all sorts of program execution vulnerabilities. –  symcbean Jun 27 '10 at 15:12
add comment

AFS ignores simple unix user permissions. suPHP executes a setuid before running the php program, but that does not give the process the kerberos tokens needed to access AFS and be restricted to its permissions. suPHP would have to be modified in some way to obtain those tokens before it could present itself to the AFS system as that user. As far as I know, that has not been done. (In fact, I found this question when looking to see if anyone else had done so.)

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.