SetUID versus www-data
For years I’ve been an advocate of running apache as www-data rather than SetUID.
Quickly, an explanation of the differences:
The Apache (or alternate webserver) runs as a low privilege account, usually www-data or httpd or a similarly named user/group. When a request is served, the low privilege apache process needs to have access to read the file, which usually means that the files must be world readable, and, the directories world executable. As such, any rogue process on the machine that knows the filesystem structure could traverse the filesystem and read files, like, wp-config.php, etc. Preventing that traversal becomes difficult if one can read config files and know which domains are served from that machine. Using a predictable filesystem layout makes it easier. However, any file that is not world writeable cannot be modified by the web process. This is why an exploit running on a site is only able to write to particular directories – usually ones that are made world writeable to allow uploads.
In this case, the server takes the request, then, changes the UID to the user account that owns the files. Traversing the filesystem to find files like wp-config.php becomes difficult if the file and directory permissions are set correctly. The web process is the user, so, it is able to write to any file – just as it could with your FTP account. An exploit that is loaded now has access to modifying any file in your FTP account.
Why www-data or SetUID
While www-data has some shortcomings, SetUID is immensely more popular for two reasons: It avoids trouble tickets where people can’t understand why their application can’t upload a file to a directory, and, it protects the user’s files from being read by other people also running on that machine.
There is another mode that can be used – running the web server as www-data, but, running suPHP which spawns php processes as a particular user, while the webserver itself still runs in low privilege mode. Any PHP script still has the permission to write files on the filesystem, but, CGI/WSGI scripts would not have the ability to write to those files.
While I’m not a real fan of SetUID, one of the projects we’re working on will use it mostly to avoid the common questions regarding why this directory needs to be chmod 777 and it will cut down on the support tickets.
As a result, we need to plan for multiple generations of backups because rather than get trouble tickets regarding applications that can’t write files, we’ll be getting trouble tickets from users that have had their sites exploited and every file modified – rather than just the files in the directories that have been given permission.
I do have another theory on how to deal with this with groups. Basically, you would still run the webserver in a low privilege mode, but, it would switch to www-data.usergroup which would prevent traversal, and, the user could selectively allow group write on directories that needed it. Since usergroup would be given read access, a script running as a different user would not be able to traverse the directory since each user’s tree would be owned by their user:group.
I guess we would call this SetGID hosting.