SLAC's CGI Script Security Wrapper
Last Update: May 27, 1998
SLAC, the Lab |
SLAC Home
Contents
This page and the Security Wrapper are still in development.
In many cases a WWW author may want to provide customized output which
is produced by a special script, exec or program.
This program may be used for such things
as extracting data from a database, doing calculations
or possibly to execute some other Unix command.
WWW provides this capability through what are called
CGI (Common
Gateway Interface) scripts.
A major drawback to providing CGI scripts at SLAC is
that scripts at this level do not have any security and could
potentially execute undesirable commands or have unexpected results.
See
an
overview on CGI script security risks and
Writing
More Secure CGI Scripts for more information.
Also see
SLAC's CGI Security Wrapper Implementation
for details on how the wrapper is implemented.
In order to easily provide some minimal level of security for CGI scripts on the
SLAC WWW server, we have provided a CGI security Wrapper called,
appropriately enough, cgi-wrap
.
The server invokes the user's CGI script through the Wrapper which
is itself a CGI script.
The Wrapper provides
some simple checking on the input to the user's CGI script. It also makes
it trivial to execute
"authorized" UNIX commands. Finally, it also kills any stalled processes
created by the user's CGI script and imposes some
resource-usage limits on the processes.
The
Wrapper
filters the input
from the various possible input sources:
the CGI
environment variables
PATH_INFO and
QUERY_STRING,
standard input
and the
command line
in the following ways:
- Converting plus signs (+) to spaces.
- Converting
certain special characters encoded as %XX, where
XX is the
ASCII code,
to the equivalent ASCII character.
- Checking the characters in the input to see
ensure that they are
restricted to a "safe" subset. Currently this subset is defined as
[0-9] [a-z] [A-Z] -_./@+, with the addition of & = if the input came from
a Form.
- By providing for special input to be included from an
HTML Form.
In order to reduce the possibility of the client attacking the server,
the Wrapper
will only call commands that are included in a Rules
file. This file provides
a list of correspondences between information in the URL or Form and the
actual command to be executed. It also provides information on restrictions to
be applied to executing the Script/Command. These restrictions include:
- Whether the Script/command is restricted to only send output
to SLAC nodes. This is indicated by the appearance of "SLAC" in the
retstrictions for this command.
- Whether execution of the Script/command must take place on the
test WWW server at http://www-dev.slac.stanford.edu/.
This is indicated by the appearance of "TEST" in the restrictions.
- Whether the Script/command can accept the special extra characters:
asterisk (*), percent sign (%),
colon (:), tilde (~), parentheses, less-than (<),
greater-than (>), and/or double quotation mark (").
This is indicated by
the appearance of "WILD" (for the asterisk (*)) and /
or the special character(s)
in the cgi-wrap configuration file (cgi-wrap.list) entry for the script.
- Whether the Script/command needs the Wrapper to insert a
<title>
, heading and <pre>
tags. The need for cgi-wrap to include a heading is indicated by the
appearance of "HEAD" in the restrictions.
Examples of Scripts/commands needing such support are raw UNIX commands.
- Whether the wrapper should supply a Content-type: text/html
header. The alternative is for the script to provide its
own Content-type: type/subtype. The latter allows
the script more flexibility, in that it may, for example, put out
Postscript by using the appropriate Content-type:. The wrapper
will not supply a Content-type: text/html if "TRANS" appears in the
restrictions.
To invoke your script from a URL:
- URLs invoking the Wrapper appear as one of the following,
where we use
user-cmd as the name that you wish the user of
your script to provide in order
to execute your script, and user-input as the input arguments to
be passed to your script. Note that user-cmd
is the name that will be used in the Rules file to look up the actual
command to be executed, and it is case sensitive:
http://www/cgi-wrap/user-cmd/user-input
- the input will appear in
the PATH_INFO environment variable.
http://www/cgi-wrap/user-cmd?user-input
- the input will appear in
the QUERY_STRING environment variable.
- An example of a URL is
http://www/cgi-wrap/ping/ftp.podunk.edu
.
In this example the user of your script sees the user-cmd
ping
. This is
translated by the Rules file to the actual
command ping -s
and the user-input will be
provided as the command line argument, i.e. the command to be
executed from the Wrapper
will be:
ping -s ftp.podunk.edu
.
To invoke your Script from a Form, proceed as follows:
- To identify the user-cmd to be executed from the wrapper:
- The usual way will be to include user-cmd following
cgi-wrap/ in the
<FORM ACTION="/cgi-wrap/user-cmd"
method="POST"> (where POST may be replaced by
GET)
- An alternative, more dynamic way, allows the user of the form to effectively
select what command will be executed. In this case
the first name following the FORM tag in your Form must be
NAME="wrap"
.
The value for the NAME="wrap"
must be the user-cmd
If you wish to pass on an argument string to a raw Unix command, then you must
use this dynamic way. In this case the
argument string must be specified as NAME="ARGV"
(where ARGV
is a reserved name), and the
value set to the argument string, e.g. VALUE="ftp.podunk.edu"
.
- Examples of a
simple form
and a
slightly more complex form may illustrate
the above better (unfortunately Mosaic will display these
examples as Forms rather than displaying the actual HTML
input, so you will have to use the Mosaic View Source
under the File menu to see the HTML for
these examples).
- Before you write your script you should carefully read and be familiar
with
Writing
More Secure CGI Scripts.
Then you have to write your Script and/or Form.
Usually you will start out with the script in a bin directory
in your home directory.
If you want to write a CGI script in
REXX
there are some
guidelines
you may want to review first.
- Then you will need to test it. To start out you can use the
Unix
setenv
command to set the appropriate environment
variables, and then call your script from the command line to test it.
- When you are satisfied that the script works, does not lock up,
does not have security
holes etc., then you will need to make it executable by the
WWW server.
On Unix this is done using
the
chmod
command, e.g.
chmod o+x /u/sf/cottrell/bin/cgi1.rxx
If your script is
in a compilable language (e.g.
C or C++) then it will need to be compiled and linked under SunOS.
- Finally you will need the Script's name and the name you wish to
appear in the URL or Form to be entered into the Wrapper's Rules file.
Currently Bebo White,
Dennis Wisinski and
Les Cottrell
are the keepers of the Wrapper's Rules file, so
you will need to contact one of them.
Assuming that the script qualifies (e.g. is in SLAC's interest, is robust and
secure),
then initially it will be entered into the
rules file to execute only in SLAC's test WWW server at
www-dev.slac.stanford.edu.
When the script is ready to go into production then:
- Example 1:
a simple script to display input from the Wrapper.
Also see Form 1 for how to invoke Example 1
from a Form.
- Example 2:
a fairly complete script to display all lines in a file that contain
a selected string of text. The script has reasonable error/debug
handling etc. and may be used as a template to start from.
- Form 2:
is an example of a Form which calls raw Unix commands and uses the
NAME="ARGV"
feature. To understand this Form and the raw Unix command
feature it may be useful to look at the
relevant part of the Rules file.
* This page is only accessible from SLAC hosts.
Les Cottrell and
George Crane
[
Writing REXX CGI Scripts |
Writing
More Secure CGI Scripts |
Feedback
]