safecgiperl beta1 Introduction ------------ This distribution is intended to be installed on a World Wide Web server and allows CGI programs written in Perl5 to be run in a sanitised environment. It makes use of the Safe extension module for Perl5--any attempted unsafe operation in the CGI program is trapped and causes a fatal compile-time error. Wrappers and utility functions for useful but potentially unsafe operations (such as opening files and sending mail) can be written in (unrestricted) perl and then shared with the sanitised compartment. Pre-requisites -------------- * Perl5, version 5.001m or later. Available widely. * The Safe extension module for Perl5. Current version is beta2, available as ftp://ftp.ox.ac.uk/pub/perl/Safe-b2.tar.gz from its home site. Description ----------- This distribution contains two programs: safeperl.c The C source of a program which needs to be installed setuid root in the cgi-bin directory of the web server. It is a small program and, just like with any suid root program, the systems administrator should convince himself/herself of its security before installing it. cgiperl A Perl5 program which lives in /usr/local/bin (or similar location). Once safeperl has done some sanity checking and switched its identity to the relvant user, cgiperl is invoked to create a Safe compartment and run the user's CGI program within that compartment. Capabilities ------------ Once safecgiperl has been installed, any user, quux say, can place a perl program in ~/cgi/bin, foo say, and the URL http://www.somewhere/cgi-bin/safeperl/quux/foo will cause the web server to run the perl program ~quux/cgi/bin/foo as a CGI program under the uid of quux *provided* foo does not try to use any restricted perl operators. The remaining sections are addressed to those who write CGI programs intended to run under this system. For installation instructions, see the file INSTALL. Perl programming in the safecgiperl environment ----------------------------------------------- The web server uses the Safe extension to Perl version 5 to run user-written CGI programs. For those of you who aren't familiar with Perl5, there aren't many differences that you are likely to notice. One is that the @ character now needs to be escaped within double quotes--Perl no longer guesses whether you meant to interpolate an array or not. Running perl with the -w flag will warn about this and many other potential errors besides. Although Perl5 is mostly backward compatible with Perl4, there are many new features in Perl5 which you can take advantage of: lexical variables, reference variables (arrays of arrays of hashes...), object oriented classes/methods, first class anonymous subs, closures and more. As mentioned above, the web server runs your CGI Perl program in a special compartment which restricts what operators are allowed. You can mimic the behaviour of the web server invoking your program by typing cgiperl foo (replacing foo by the name of your program). This mimics the web server's invocation even to the extent of displaying errors in HTML markup. You can type cgiperl -i foo to have any errors displayed in a more human readable form. Restricted operators -------------------- There are many Perl operators not available to the compartment in which your CGI program is run. These mostly include operators which provide access to the operating system. The following list is not exhaustive but includes the most common excluded operators: * system, `backticks`, exec, fork, syscall, signal handlers, pipes (including open(FOO, "|bar") and open(FOO, "bar|")) * network access (socket, bind, connect, ...) * File munging (rename, link, opendir, chown, ...) * System V IPC (shared memory, message queues, semaphores) * File tests (-r, -w, -l, ...) * Calling perl on other files (require, use, do 'file') Opening files for reading/writing is restricted. The "open" command is subject to the following restrictions: * Files opened for reading must be owned by the user. * Files opened for writing must be opened by using a filename containing no "/" characters. The filename is taken to live in the directory ~/cgi/out and the file must already exist at the time the open is performed. It can be a symbolic link if desired. Sending mail ------------ There is a subroutine available which allows the sending of mail from a CGI program. The syntax is mail(RECIPIENT, SUBJECT, CONTENTS); For example, mail('foo@bar.baz', 'Test mail', "Hello world\n") or oops("mail failed"); Note that @ interpolates an array when used in double quotes ("") (unlike in perl4 which tried to guess whether you wanted to interpolate or have a raw @ in there). If you want to hard-wire an email address with an @ in it then either use single quotes or prefix the @ with a backslash ("$user\@wherever"). Note also that you gather the whole message together into one string to pass as the third argument. Installing your CGI program --------------------------- Once you have written and debugged your CGI program, put it in ~/cgi/bin (creating that directory if necessary). There is no need to include a leading '#!' line, nor will one be honoured if you do. Supposing that your username is quux and your program is called foo, the URL which will cause the web server to invoke your program is http://yourwebserver.somewhere/cgi-bin/safeperl/quux/foo When the web server runs your program it will run it with the privileges of *your* username. Any use of a masked operator in your Perl program will trigger a compile time error (which your browser will display) and the program will not run at all. By a "masked operator", I mean an operator which is restricted but which, unlike "open", is not aliased to a secure sanitised version. The error message will be something like <opname> trapped by operation mask at line ... where <opname> is replaced by the name of the offending operator. Malcolm Beattie mbeattie@sable.ox.ac.uk 24 October 1995