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?


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.

  • 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? Jun 22, 2010 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, 2010 at 14:58

4 Answers 4


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


  • 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, 2010 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, 2010 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, 2010 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, 2010 at 12:38

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:


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.

  • 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, 2010 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, 2010 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, 2010 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. Jun 23, 2010 at 18:26

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).



  • 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, 2010 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, 2010 at 15:12

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.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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