Chapter 10: Common Gateway Interface
The Common Gateway Interface (CGI) is a language-independent gateway between a Web server and other programs on the same platform. CGI can invoke executables on your platform and pass variables to it, then return the output to the client. This chapter discusses CGI topics, including
- CGI error logging
- CGI security
CGI gives you the flexibility to write your Web applications in C, Perl, Java, Python, ksh, tsh, csh, or any other UNIX programming language. It can execute either a binary program or a script (assuming you have an appropriate interpreter). Both binaries and scripts behave identically in the CGI environment, and for the purposes of this chapter we will refer to both as programs.
As of Stronghold 2.4, CGI buffers are flushed whenever they contain data and Stronghold is waiting for more output from the program, allowing clients to receive partial responses while the program is finishing. Previous versions withheld the data until either the buffers were full or the program completed.
CGI Error Logging
For debugging purposes, the CGI module logs standard error data if the ScriptLog directive is set. Each error entry begins with two lines with this format:
%% [time] request-line
%% HTTP-status-code CGI-script-filename
These lines are followed by more specific error information, depending on the nature of the error. If CGI cannot start the script at all, the body of the error entry looks like this:
%%error
error-message
If the script returns incorrect header information, the body of the error entry looks like this:
%request
request-header(s) received by the script
%response
response-header(s) output by the script
%stdout
CGI-standard-output
%stderr
CGI-standard-error
If the script does not output anything on stdout or stderr, those fields may be empty.
CGI Security
Two characteristics of CGI pose security issues for your server:
- CGI executes programs on the server platform.
- Intruders can access CGI programs directly, bypassing any HTML interface.
Since CGI executes programs at the request of users, intruders can arbitrarily invoke programs that can directly influence your platform. By manipulating the input, a clever hacker can turn a benign program into a tool that threatens the integrity of your log files, user accounts, or programs. By bypassing the HTML interface to a CGI program, an intruder avoids its constraints and can freely enter manipulative data or view "hidden" data fields.
Authoring Tips
This section offers some authoring tips that can help you avoid potential security weaknesses on your system:
- Exercise extreme caution when using system(), popen(), eval(), pipes, and backquotes.
- In all CGI programs, check the input for invalid values, such as selection list values not included in the original list, or values that exceed the length you specified in your HTML form.
- Reject variables whose names are not already defined in the program.
- Reject hidden fields that your program did not create.
- Reject unescaped control characters.
- If your program must spawn a child process, avoid passing user input to that process. If you must, be sure to filter out meta characters.
- If your program allows users to send mail, use /usr/lib/sendmail. Never use /bin/mailx or /usr/ucb/mail.
- If you allow users on your system to use their own CGI programs, screen them carefully before posting them to the CGI directory.
- Secure the CGI directory so that only an administrator can add, remove, or modify programs.
- Delete all backup files that your editor creates while you are authoring programs, and advise users on your system to do the same.
- Although "security through obscurity" is generally inadvisable, it is a very good idea where CGI programs are concerned. Do not allow users to read the CGI programs on your server platform, and do not allow anonymous FTP access to the CGI directory.
- Exercise caution when using CGI programs written by others. If you download a CGI program from a remote site, examine it carefully before implementing it on your own site.
suEXEC
Stronghold can run CGI programs under user IDs (UIDs) other than its own. For example, if your site hosts a number of users, some of whom have their own CGI programs, Stronghold can execute these under the UIDs of their owners. The suEXEC CGI wrapper provides this functionality.
When CGI programs are confined to the UIDs of their owners, weaknesses cannot be exploited outside the realm of that user's directories and files. In addition, the suEXEC wrapper uses these rules for added security:
- The UID of the current CGI program must be a valid user on your system.
- The UID of the current CGI program must be the HTTPD_USER.
- The command being executed must not contain a slash (/).
- The command being executed must reside in the DOC_ROOT.
- The current working directory must be an actual directory.
- The current working directory must not be writable by group or other.
- The command being executed must not be a symbolic link.
- The command being executed must not be writable by group or other.
- The command being executed must not be a setuid or setgid program.
- The target UID and group ID (GID) must be a valid user and group on your system.
- The target UID and GID must match the UID and GID of the current working directory.
- The target UID and GID must not be root.
These rules shore up many of the security weaknesses that CGI normally poses.
This is an advanced feature; use it with caution. If you configure it improperly, suEXEC can severely compromise the security of your site. However, if you are familiar with setuid programs and their security issues, and you configure suEXEC properly, it reinforces your site's security considerably.
To compile Stronghold with suEXEC
- Edit ServerRoot/src/support/suexec.h so that the following macros match your server configuration:
- HTTPD_USER
The UID of the server process. Only this user is allowed to execute suEXEC. The value must be the same as that of the User directive, usually "nobody."
- LOG_EXEC
The path to the suEXEC error log file. Use a separate error file to isolate suEXEC errors.
- DOC_ROOT
Stronghold's root document directory, and it should match the value for DocumentRoot. Only this directory and the user directories can use suEXEC.
-
Compile suEXEC:
# gcc suexec.c -o suexec
- Add the following line to the Makefile Configuration section of ServerRoot/src/Configuration:
EXTRA_CFLAGS= -DSUEXEC_BIN=\"/path/to/suexec\"
- Recompile Stronghold according to the instructions in "Recompiling Stronghold" on page 4-9.
- Move the suEXEC executable you created in step 2 to the location specified in step 3.
- Set the setuid bit:
# chown root suexec
# chmod 4711 suexec
- Stop the old Stronghold process.
- Start Stronghold.
Note: Restarting does not allow Stronghold to recognize the suEXEC wrapper. It must be stopped and then started.
On startup, the server should print the following line:
Configuring Apache for use with suexec wrapper.
Stronghold can now implement suEXEC. However, if this line does not appear, suEXEC is incorrectly configured.
With suEXEC in place, Stronghold sets the UID of each CGI program to that of the user directory in which the program resides. For CGI programs that belong to a virtual host, use the User and Group directives to set the UID for that host's CGI programs.