Guide to Safe Gophering Paul Lindner In any software product as large and complex as gopher there is the possibility of security holes. In this paper we'll show you what they are and how to run a secure gopher server, gopher client, and gopher public access system. April 18, 1994 1.0 Introduction Gopher has had its small share of security problems. The University of Minnesota, in conjunction with CERT and other computer security agencies attempts to keep the Gopher software as secure as it possibly can. Now that the gopher software is installed on thousands of sites it is imperative that all holes be documented and fixed. We believe that release 1.13 and 2.013 are free of security holes and that you should upgrade to these releases as soon as possible. We make no claims as the security or insecurity of other software. This paper only applies to the Unix/VMS Gopher Software released by the University of Minnesota. 2.0 The Origin of Holes There are a few programming practices and design deci- sions that have caused most of the holes in gopher soft- ware. These practices pervade other software packages too. 2.1 Use of software routines to insure security. The most popular method of maintaining a secure environ- ment is to use the chroot() system call to change the loca- tion of the / directory to a subdirectory. This is the method used by most FTP servers. Consider the following code snippet: chroot("/usr/local/gopher-data"); This code causes the program to instantly think /usr/local/gopher-data is the slash directory. Thus if you try to access /etc/passwd you will, in fact, be attempting to access /usr/local/gopher-data/etc/passwd There are a couple of problems with this scheme however. The first is that you need root privileges to use this system call. Also, sometimes you want to access files that aren't in your gopher-data directory. For instance you might want to make a symbolic link to your manual pages like this: ln -s /usr/man /usr/local/gopher-data/manual-pages The solution to both of these problems was contributed by John Sellins from the University of Waterloo. Instead of relying on the chroot() system call, a suite of software routines were written to insure that all requests are legitimate. The routines strip out all occurrences of `..' in gopher requests and append the server data directory to certain requests. If these checks weren't in place a cracker could do this: 0/../../../../../../../../../../etc/passwd This request would retrieve the password file of the system running the gopher server if it wasn't for the dot stripping routines. Our example of a symbolic link works however, since there aren't any `..' character strings in the request. As we'll see later, bugs and oversights in this section of code have caused security holes. 2.2 Use of Dangerous Routines in the Server and Client The server and client use two highly dangerous routines to implement portions of the code. These calls are system() and popen(). The server uses this code to decompress files on the fly and run shell scripts to perform functions not implemented in the server. The client uses these routines to execute `helper' applications to send email, invoke tele- communications download protocols and display many data types. The problem with both of these calls is that they use the shell `sh' to evaluate the expression sent to them. The shell has a very extensive feature set that makes it difficult to ensure security through software routines. It's possible for a malicious user to exploit these weaknesses to actually run commands on the server. For instance the gopher server has a special notation for running an external shell script. Here's an example: exec:arg1 arg2:/bin/legisearch In this case the server executes: popen("/bin/legisearch arg1 arg2"); which in turn executes: sh -c "/bin/legisearch arg1 arg2" In earlier versions of the server a malicious user could send the following command to a server running with the `-c' (non-chroot) option: exec:arg1 ;cat /etc/passwd:/bin/legisearch The server then would then execute: sh -c "/bin/legisearch arg1 ;cat /etc/passwd" The semicolon (;) tells the shell to execute a second com- mand and add the results to that of the first. In this case the command prints out the contents of the Unix password file. This problem will only occur if you have shell scripts on your server (the software will not execute non-existent shell scripts.) If you're using the default chroot() mode a cracker won't be able to get at files outside of the gopher directory tree. However, they could still wreak major dam- age to your gopher data. This problem of hidden code execution plagued earlier versions of the client as well. The Gopher client allows connections to telnet sites by launching the telnet com- mand with the name of a host. It does this by using the sys- tem() system call like this: system("telnet pubinfo.ais.umn.edu"); However if an unscrupulous server administrator created a bogus telnet item with a hostname like this: "pubinfo.ais.umn.edu;echo + >.rhosts" This would cause the .rhosts file of the person using the client to be compromised when they selected the item. Gopher links like this are `telnet bombs' just waiting to be opened, much like physical mail bombs. Starting with release 2.0.12 we've started replacing these routines with more general secure code that does not use the shell. So far we've converted most of the client side and some of the server calls. Eventually we will be rid of this problem altogether. 3.0 Known Holes Here is a list of the known holes in gopher and gopherd for Unix system. It is probably not complete.