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.