The current version of the File Transfer Protocol (FTP)
is defined
in RFC 959, October 1985. Its purpose is to reliably
transfer files
between computing systems independent of the operating
and storage
systems.
FTP uses a client-server model. The server side is implemented
by
a daemon called ftpd or in.ftpd. The client side is
implemented with a program called ftp. Figure 1 shows
a simpified
model of FTP.
The client starts the session by opening a control connection
with
the server, sending the request to port 21/tcp. The
client sends its
port number, and network address in the connection request.
If ftp
is not available at the network address, the transport
provider returns
a "connection refused message." If the request
for a control
connection is accepted, the ftp server sends back a
reply
code 220, saying that the server is ready, start the
authentication
process.
The reply code is a three-character digit code followed
by a text
string. The text string is for human use and is not
fixed by the protocol.
The digit code is used by the client process and is
fixed by the FTP
protocol. The first digit tells whether the reply is
positive or negative.
The second digit tells the reply's category. The third
digit, if not
0, is a gradation of the reply. See Figure 2 for the
meanings of the
first two digits.
Once authentication is done and a confirming reply is
returned, the
client issues commands, and the server responds with
replies on the
control connection. RFC 959 contains a list of all client
commands
and server replies. I found that only a subset of the
commands available
under the FTP protocol are implemented.
If there is data to transfer, the server opens and manages
a new connection
to transfer the data. It uses port 20/tcp on its side
of the connection.
By default the client's control port and network address
form the
other half of the connection. The client can specify
another port
and network address by using the PORT command.
This paper reports on an exploration of the server side
of the FTP
protocol. I used three versions of UNIX: System V/386
Release 3.2
from Interactive (SVR3), System V Release 4.0 from Dell
(SVR4), and
Sun 4.1.3 from Sun Microsystem (SunOS).
On all three operating systems, ftpd does not listen
for session
requests. Instead inetd is configured to listen for
requests.
inetd executes ftpd once for each request received.
If inetd is not listening for requests, when an ftp
request comes in, the client receives a "connection
refused"
message from the transport provider.
I tried to run ftpd as a standalone program, mostly
to see
what would happen because the program is designed to
work under inetd.
I removed ftpd from inetd.conf. I logged in as root
and started the ftpd program. In each case the program
stopped
executing with an error message showing there was a
problem with its
access to the network.
The last field of inetd.conf mimics starting the program
from
the command line. This allows the specification of options
for the
program. ftpd has three options:
-d, logging debugging information to syslog.
The -t option identifies the number of seconds of inactivity
allowed before ftpd closes the session. Figure 3 shows
the
results of setting the -t option to 20 seconds on SVR4.
The 421 time out reply code does not show on the screen
until another
command is issued. The default inactivity time is 900
seconds (15
minutes). The other systems' ftpds acted similarly.
The -T option of SVR3's ftp program allows a user
to override the -t option by specifying the timeout
for
this session. This has a maximum of two hours.
ftpd writes three levels of messages to the syslog
daemon facility. Figure 4 shows the levels and the types
of messages.
The err level messages are always written. The info
level messages are written only if the -l option is
set.
The debug level messages are written only if the -d
option is set. The syslog.conf file must be modified
to direct
messages or they are lost.
While testing for the -l options, I found that ftpd
writes login and logout information in the wtmp file.
Usually,
this information is sufficient. On DELL's SVR4 the wtmp
records
have an error and cannot be read by who. Here I do use
the
-l option.
The data available from ftpd's -d option is difficult
to correlate to the actions of the user of the ftp client.
The same data available from ftpd's -d option
is available from the client's ftp by using the verbose
and -d option. The sidebar "A Sample ftp Session
with
the -d Option" walks you through a session with
verbose and
-d enabled.
Configuration Files of ftpd
Basic access to ftpd requires a user to be listed in
the server's
/etc/passwd file and to have a password. Anonymous ftp
does
not require a valid password in /etc/passwd. The files
/etc/ftpusers
and /etc/shells modify the basic requirements.
The file /etc/ftpusers is a list of account names, one
per line, that
may not log into the system through ftp. I tried this
on all systems,
and it is true that you cannot login if your account
name is in the
file. However, this does not apply to anonymous ftp.
David A. Curry,
in UNIX System Security suggests:
As a minimum, the super-user, root, and any other
accounts with user id 0, should always be listed in
this file. System
accounts that do not normally have a human associated
with them, such
as bin, daemon, news, sync, sys, and
uucp, should usually be listed as well. (page 70)
For SVR3, the file /etc/shells determines which additional
shells are allowed over the standard shells: /bin/sh,
/bin/ksh,
/bin/csh, /usr/bin/sh, /usr/bin/ksh, /usr/bin/csh.
The SVR4 /etc/shells file works slightly differently.
If
the file does not exist, then only the standard shells
sh,
ksh, and csh in /bin and /usr/bin
are allowed to login using ftp. If there is an /etc/shells
file, then only accounts with a listed shell can use
ftp.
If the file is empty, then no one can use ftp.
SunOS's /etc/shells file works similarly to the SVR4's
except
that it uses a different list of default shells: sh
and csh
in the directories /bin and /usr/bin.
As a result of exploring the options and setup files
for ftpd,
I do the following when setting up ftpd: First, I use
the
timeout option (-t) with a value of 300 seconds --
five minutes is a long time for no activity. Second,
I follow David
Curry's recommendations on /etc/ftpusers and place all
super-user
accounts and all accounts not associated with an individual
in the
/etc/ftpusers. Third, I list all of the shells being
used
on the system in /etc/shells. I do not use the option
-d.
I only use the -l option on DELL's SVR4.
Configuring an Anonymous ftp
If the system administrator establishes an account named
"ftp,"
ftpd will allow access to anyone who can ping the
system using the account name "ftp" or "anonymous."
Any set of characters works as the answer to the password
question;
just pressing the enter key does not work. This access
method is generally
referred to as "anonymous ftp."
Each version of UNIX has a set of directions for setting
up anonymous
ftp. The emphasis here is on why the ftp account structure
must have
certain directories and files, and on the tools available
to find
the necessary directories and files.
The first step is to make sure your ftpd does not have
known
bugs. This means having the current version of the software.
I found
that the only sure way to know what version of ftpd
is being
used is to talk with the vendor.
In UNIX System Security, Curry talks about problems
with versions
of ftpd earlier than July 1989. Node agate.berkeley.edu
in
file /pub/NetBSD/NetBSD-current/src/libexec/ftpd/ftpd.c
shows the
current version to be 5.4 (Berkeley) 7/2/91. CERT advisory
CA-93:06
shows the current version from wuarchive.wustl.edu to
be 8 April 1993.
Versions of ftpd based on the BSD software are probably
safe
if the version date is later than July 1989 and are
probably the latest
version if the version date is 2 July 1991 or later.
The wuarchive
version date should be after 8 April 1993.
The second step is to create an account for the anonymous
ftp. The
structure, ownership, and permissions of the account
are determined
by three conditions. First, the account name must be
ftp. Second,
ftpd does chroot after accepting the password for
the ftp account. Third, placement of the home directory
is determined
by the use of the account.
An entry in /etc/passwd creates a new account. Figure
5 gives
a summary of what is in the seven fields. The account
name must be
ftp. Since ftpd does not use the password entry, I usually
keep it
locked. The uid is any available user id. The group
can be a default
user's group. In the gcos field we place the words,
"Anonymous
ftp login." The location of the home directory
can be any directory
(placement of the directory is discussed in the section
on downloading
and uploading). The initial command field (shell) is
not used, but
I have seen the ftp program placed there. I tried /dev/null
and it worked just fine. I normally place a non-executing
file here,
/noshell.
The standard startup files are not necessary for this
user. To handle
mail that might come to this account, I add an entry
to the aliases
file, forwarding it to another user.
The chroot command accepts a pathname as its only parameter.
It changes the root directory (/), to this pathname.
Only a uid 0
account can execute this command. (Note: for chroot(2)
to
be effective, the program must then do a chdir(2) to
/. Otherwise,
. will access the current local directory.)
After executing chroot, the kernel does not allow access
to
any file outside of the local hierarchy, does not allow
a cd
outside of the local hierarchy, and does not allow symbolic
links
outside of the local hierarchy. Thus, a limited file
system hierarchy
must be built under the ftp account's home directory,
the new /, to
contain the files ftpd needs. The chroot command is
executed as part of accepting the password. chroot restrictions
are in force when the 230 reply code (230 "Guest
login ok, access
restrictions apply.") is displayed.
The ftpd needs access to the ls command after the
chroot to comply with the ftp protocol commands LIST
and NLIST. The ls command is usually stored under
/bin and /usr/bin. On all systems I looked at, the
150 reply code to an ftp dir or ftp ls command
shows the path to the command being executed by ftpd.
The reply shows ftpd using the ls in /bin.
The limited hierarchy needs the directory ~ftp/bin to
hold
a copy of the ls command. The permissions on the command
should be 111 since ftpd needs only to execute the command.
The ls command depends on accessing dynamic libraries
for
some of its subroutines. In SVR4 and SunOS, the command
ldd
lists the dynamic libraries used by a command. SVR3
does not have
the ldd command; the command dump with the -Lv
options gives the same information. The dump command
is also
available on SVR4. Figure 6 shows the results on the
different systems.
The libraries are stored in /usr/lib on SVR4 and SunOS.
On
these systems, the ftp account needs the directory ~ftp/usr/lib
with copies of the libraries. On SVR3 the library directory
is /shlib.
Here the ftp account needs the directory ~ftp/shlib
and a
copy of the library. All of the ls accessed libraries
are
needed since ls is accessed after the chroot. The
libraries need the same protection as in the normal
hierarchy, so
permissions are 555.
The command lld or dump must be run on the ftpd
command since ftpd may access libraries after the chroot.
Figure 6 shows the results on the diffent systems. I
tested each library
to see if it was needed. SVR3 is easy since both ftpd
and
ls need the same libraries. SVR4 shows that ftpd needs
two additional libraries besides the one needed by ls.
Experimentation
shows neither library is needed. Under SunOS, a quick
experiment
accessing anonymous ftp without the library and with
the library shows
ftpd needs the /usr/lib/libdl.so.1.0 and /usr/lib/libc.so.1.8
libraries. SunOS also needs the file /usr/lib/ld.so,
the runtime
loader. This file is needed anytime a dynamic library
is used. When
I leave it out, the error message shows this file is
necessary.
For the ls command to display the correct information
it needs
to access the files /etc/passwd and /etc/group. Strip
these files of all entries that are not needed. The
/etc/passwd
file shows only the owners of files and directories.
The /etc/group
file shows only those groups associated with files and
directories.
In fact, the entries can be entirely bogus so long as
the uids and
gids match those in the ~ftp hierarchy. The files are
stored in ~ftp/etc.
The files need the same protection they have in the
normal hierarchy;
permissions are 444.
Commands may access a device file during their execution.
On SunOS,
the command trace shows all system calls and signals
for a
command given as a parameter. grepping for /dev shows
a superset of the devices needed. On SVR4 the output
of the command
truss, trace system calls and signals, can be greped
for /dev to find all of the possible device files. On
SVR3
neither trace nor truss exists, so I used strings,
grepping for /dev. Figure 7 shows that the ls
command accesses no device files in SVR3. Experimentation
shows the
only device file necessary in ~ftp/dev of all those
listed
by the strings command is tcp.
grepping the SVR4 truss files for /dev, as
shown in Figure 8, and doing some experimentation shows
that ls
needs /dev/zero and ftpd needs /dev/zero and /dev/tcp.
The /dev/tcp is a STREAMS device file accessed whenever
a
tcp port is opened. In STREAMS on SVR4, multiple transport
mechanisms are possible. The file /etc/netconfig contains
information on available transport mechanisms. It is
accessed whenever
a STREAMS device is used to find the underlying transport
mechanism.
Thus, the file must be available in ~ftp/etc.
grepping the SunOS trace files for /dev, as
in Figure 9, shows ls needs the device /dev/zero and
ftpd needs /dev/zero and /dev/null. Experimenting
shows the /dev/null driver is not needed.
The device files cannot be copied into ~ftp/dev. The
file
system entries must be made with the program mknod,
which
makes a special file using the same major and minor
numbers for the
corresponding device files in /dev. To find the major
and
minor numbers, do an ls -l on the device in /dev.
If ls is derived from SVR3 or SVR4, then the major and
minor
numbers are the 5th and 6th fields of the output. If
ls is
derived from a BSD-based system, then the major and
minor numbers
are the 4th and 5th fields of the output.
Figure 10 summarizes the directories, files, and their
permissions
needed in the ~ftp hierarchy. (Traditionally, there
is one more directory.
I discuss it in the Uploading and Downloading Directories
section.)
One question not decided is who should own the ~ftp
hierarchy. CERT
in Anonymous FTP Configuration Guidelines recommends
that the ftp
account's home directory and the subdirectories not
be owned by ftp.
This prevents anyone from making changes to the ~ftp
hierarchy. Without
recommending, CERT states that for most systems root
is acceptable
as the owner of the directories in the hierarchy, and
whatever corresponds
to root's group is good for the group of the hierarchy
directories.
Downloading and Uploading Directories
One more directory, ~ftp/pub, is traditionally added.
If the server will allow only downloading then the permissions
on
the directory are 755. It's under this directory that
you should build
the hierarchy used to hold the files clients are allowed
to download.
If uploading is allowed, create a directory, ~ftp/incoming,
with the permissions set to 777 to allow anyone to create
files in
the directory. This opens up ftp to some abuses. Placing
this directory
in its own partition or, if possible, limiting the space
available
for the directory allows you to protect the system from
some of the
abuses.
CERT, in Anonymous FTP Configuration Guidelines, suggests
a method
of hidden directories to limit access to uploading.
To implement this,
first change the permissions on ~ftp/incoming to 751.
This
allows the anonymous ftp user to change to the directory
but not to
list the contents of the directory. Second, create directory
names
using the same rules as making good password names.
Give these subdirectories
to ~ftp/incoming permissions 777. Now anyone knowing
a subdirectory
name can upload to the known directory. The security
of this system
is only as good as the password-directory names.
Generally, I follow the directions given in the ftpd
man page
for setting up anonymous ftp. I modify the directions
to follow CERT's
suggestion on ownership of the files and directories.
However, for
each system I explored, I found I needed to use ldd
or dump
-Lv, and trace, truss, or strings to
find missing data.
References
RFC 959. J. Postel and J. Reynolds, October 1985.
Available by anonymous ftp from host nic.ddn.mil, directory
/rfc,
file rfc959.txt.
UNIX System Laboratories. User's Reference Manual/System
Administrator's Reference Manual for Intel Processors.
Prentice
Hall, 1992. ISBN 0-13- 951310-8.
SunOS Reference Manual. Part Number:800-3827-10,
Revision A of 27 March 1990.
Anonymous FTP Configuration Guidelines. CERT.
Available by anonymous ftp from host cert.org, directory
/pub/tech_tips,
file anonymous_ftp.
Curry, David A. UNIX System Security. Addison-Wesley,
1993. ISBN 0-201- 56327-4.
About the Author
Arthur Messenger returned from the Air Force, where
he worked on numerious computer systems, in 1988.
Since then, he has been doing teaching and consulting.
His current interest is in UNIX and Network management.
He can be reached at p00449@psilink.com.