cgi-bin | CGI programs to be executed by the server |
conf | Configuration files for the server |
htdocs | The top-level directory for the archive |
icons/images | Common image files and icon bitmaps |
logs | Logfiles are created here by httpd |
support | Programs used for maintenance of the server |
The important thing here is to be sure that the appropriate access is afforded to the appropriate components of this structure, while maintaining privacy and some level of security through obscurity against uninvited snoopers. If you're managing your archive as a team, you will probably create a group-ID for the members of the team who will be modifying the contents. These people may also need to access the files within the directories listed in the preceding list. Thus, it's recommended to make all of the files and directories within the list owned by root and accessible by the group you've created for the Web team--something like this:
drwx--x--x 2 root www 512 May 10 21:36 cgi-bin/ drwx------ 2 root www 512 Jul 20 16:11 conf/ drwxr-xr-x 3 root www 512 May 14 16:02 htdocs/ -rwx------ 1 root www 155648 May 5 15:33 httpd* drwxr-xr-x 2 root www 1024 Feb 17 00:32 icons/ drwx------ 2 root www 512 Jun 23 11:28 logs/ drwxr-xr-x 2 root www 512 Feb 17 00:32 support/
In this case, the restrictions on the logs directory or the conf directory may be excessive, again depending on the level of access you wish to provide. If the person who has the root password can't be bothered to create new directories under the htdocs directory, to truncate/archive the logfiles periodically, or to modify the configuration options within the config files, then these files or directories may need to have write-perms for the group www
, or possibly ownership by the userid, www
. The most important thing is that root
owns the server binary itself, httpd
, and that the userid the server runs under (nobody
) has no write permissions to anything within this hierarchy.
It's a good idea to use some sort of security package, like TripWire or COPS, to occasionally verify that these permissions haven't been changed. Such a practice is also useful for the detection of unwanted files or changed files within your archive. This will be discussed further in the next section. We'll take a closer look at these tools at the end of the chapter. For now, we can add a few lines to the previous script to check some of the most important of these permissions for us:
use HTTPD::Config; require "stat.pl"; $conf = `/usr/local/etc/httpd/conf'; @files = qw(httpd.conf srm.conf access.conf); $V= new HTTPD::Config (SERVER => Apache, SERVER_ROOT => $conf, FILES => [@files]); print "Userid: ", $V->user,"\n"; print "Group: ", $V->group,"\n"; print "Administrator is: ", $V->server_admin,"\n"; print "Running at port: ", $V->port,"\n"; print "Access filename: ",$V->access_file_name,"\n"; print "User Directory: ", $V->user_dir,"\n"; print "Global Types:\t", join("\n\t\t",$V->add_type),"\n"; print "\n\n"; foreach $dir (keys %{$V->{`Directory'}}){ print "Options for Directory: $dir\n"; while(($opt,$val) = each %{$V->{`Directory'}{$dir}{`OPTIONS'}}){ print "\t",$opt, " : ", @{$val},"\n"; } } # rudimentary permissions checking $webuser = (getpwnam($V->user))[2]; opendir(ROOT,$V->server_root); @files = grep(!/\.\.?/,readdir(ROOT)); closedir(ROOT); foreach $f (@files){ @s = Stat($V->server_root."/$f"); if($s[$ST_UID] == $webuser){ print "Warning: ",$V->server_root,"/$f is owned by ", $V->user,"\n\n"; } if($f eq "httpd"){ if(($s[$ST_MODE] != 0100700) or ($s[$ST_UID] != 0)){ print "\tWarning: ",$V->server_root,"/httpd may have\n"; print "\tpermission problems. Recommend root ownership\n"; print "\tand readable, writable and executable only by\n"; print "\troot user\n"; } } }
Now, when we run our simple security script, we'll get a warning if anything in the RootDir
is owned by the userid that runs the server, or if the httpd itself isn't owned by root with the permissions specified in the preceding code. Note that we used the old stat.pl library in this example, as well. It provides a simplified interface to the stat(2)
function.