This document contains information about securing the Internet File Transfer Protocol (FTP) server. While there are a variety
of daemons around, most of the material covered here pertains only to wu-ftpd.
In the past there have been bugs found in older versions of various ftpd daemons. Crackers have exploited these bugs and will continue to do so. See
for the latest attack exploiting a problem in the realpath() function.
So, the first order of business is to upgrade that server to the latest version! My favorite site for finding wu-ftpd is at ftp://ftp.vr.net/pub/wu-ftpd/wu-ftpd/, which also includes "vr" patches; they're in
my mind akin to the Linux kernel's "ac" patches.
Now on to some really fun steps (as if compiling ftp isn't already fun):
- Check your /etc/ftpusers (a misnomer in my opinion)
This file includes the login names of those users who are NOT allowed to login to your site. This file may look something like:
~[root(lindstrom)1]: cat /etc/ftpusers
At the very least, this file should contain root, system accounts, and nobody. Other possible users will include
anonymous and ftp. Adding those accounts will effectively disable anonymous ftp. Removing the ftp user from /etc/passwd will also disable anonymous ftp.
- Lets take a peek at /etc/ftpaccess as well
This file configures ftpd, but only if ftpd is called with -a. I recommend using this handy feature. Discussing all the possibilities of this file is out of the scope of this document. I urge you to man ftpaccess to get a better understanding of it.
- Every happy server should do some logging.
In order to do such things we'll use the "log" directive. Typically you'll want to log transfers and violations of security rules. I also log commands as well. To achieve this, I've added:
log transfers anonymous,real,guest inbound,outbound
log security anonymous,guest,real
log commands real,anonymous,guest
Logging of incoming and outgoing transfers will go to /var/log/xferlog, unless otherwise changed by adding:
- Well isn't that a funny-looking file..
Path-filters are useful, particularly if you have your site setup for "drop-off" areas where uploading is permitted. Path-filters use regular expressions to determine what a file can or cannot be. /etc/pathmsg will be displayed when a filename is unacceptable according to the following filters:
path-filter anonymous /etc/pathmsg ^[-A-Za-z0-9_\\.]*$ ^\\. ^-
path-filter guest /etc/pathmsg ^[-A-Za-z0-9_\\.]*$ ^\\. ^-
path-filter real /etc/pathmsg ^[-A-Za-z0-9_\\.]*$ ^-
These filters permit anonymous and guest users to create only files containing A-Z, a-z, 0-9, a period, an underscore or a dash, but NOT beginning with a period or dash. Now these users will no longer be able to create directories that contain spaces, special characters, con
trol characters, or the like. Directories of this nature are often used to hide pirated software.
Real users have almost the same rules as anonymous and guest, except a real user can create a file beginning with a period.
- Noretrieve and the wonderful world of uploads
To prevent certain files from being retrieved, use the noretrieve directive. Some examples might include:
Marking the file ".notar" noretrieve will prevent it from confusing some clients. I'll talk about its purpose later on.
The incoming directory shouldn't allow downloads until the admin has had a chance to inspect the files and move them to an appropriate public place for downloading. If your /incoming directory is on its own partition/drive (which is good practice to prevent Denial of Service attacks on the filesystem, and you might also consider mountin
g it with the "nodev" and "noexec" options), there will be a lost+found directory. The contents of this directory shouldn't be downloaded.
wu-ftpd by default doesn't allow anonymous uploads, so this will have to be changed if you so desire. For this example, we'll assume that the upload directory in the chroot environment is /incoming. This is what a typical configuration may look:
upload /home/ftp * no
upload /home/ftp /bin no
upload /home/ftp /etc no
upload /home/ftp /lib no
upload /home/ftp /incoming yes ftpadmin ftpadmin 0440 nodirs
Here we've explicitly said that uploads are denied everywhere except for /incoming. Files uploaded will have owner and group of ftpadmin, permissions set to 0440. Users will not be able to make directories by adding "nodir." I don't recommend allowing users to make directories.
One note about directories and incoming: You may like to setup your incoming directory to something like /incoming/[some dir], where "some dir" is a directory known only to your local users and those you want to have upload access to your site. This way the occasional passer-byer who logs in wont be able to upload anything unless th
e correct directory is known. Granted, this is like a weak password in many ways.
Sometimes it may be desirable to set a umask for uploaded files. This can easily be accomplished by using "defmask" or calling ftpd with the -u option. The following sets a umask of 0377 for everyone:
or this sets a umask of 0377 for class remote only:
defumask 0377 remote
- Everybody loves guests!
Let's talk about guestgroup for a moment. When a real user is a member of a guestgroup (as defined in ftpaccess), the user is treated like an anonymous user and the session is chrooted. This also requires a little bit /etc/passwd fun! Let's say we put:
in our ftpaccess file. Any user logging in as a member of "ftpguest" will be setup as a guest. However, before we can rejoice, we need to do that passwd editing. For this example, user bob is a member of "ftpguest" and we want bob to be chrooted. Normally his passwd line would look like
bob:x:1051:502:mister the bob:/home/bob/:/bin/ftpshell
so instead we change it to
bob:x:1051:502:mister the bob:/home/bob/./:/bin/ftpshell
The path specified before the /./ tells the daemon where to chroot to. The path that follows the /./ is the user's home directory in the chrooted environment. Now, when bob logs in, he will be chrooted to /home/bob, and his current directory will be / (which, outside of the chrooted environment is /home/bob).
Also, since the user is chrooted to /home/bob, he will require an ls binary inorder to be able to do a dir listing, just like how any anonymous user will require the same thing. necessary binaries and the structure of ~ftp/ is the next topic.
- I'm sorry I can't allow you to do that, Dave.
While it's the default in most wu-ftpd configurations, it's
a good idea to explicitly disallow anonymous/guest users any privileges. So, to revoke these rights, add to ftpaccess:
delete no guest,anonymous
overwrite no guest,anonymous
rename no guest,anonymous
chmod no guest,anonymous
umask no guest,anonymous
- Setting up the FTP area file structures
Finally we setup restrictions at the file level.
The root directory and every directory under it should not be owned by the same user/group of the ftp account. We certainly don't want anonymous users writing to just anywhere.
d--x--x--x 2 ftpadmin ftpadmin 1024 Feb 12 18:34 bin/
d--x--x--x 2 ftpadmin ftpadmin 1024 Jul 11 06:36 etc/
drwxr-xr-x 2 ftpadmin ftpadmin 1024 Feb 5 14:48 lost+found/
drwxr-xr-x 7 ftpadmin ftpadmin 1024 Mar 31 17:04 pub/
drwxrws-wt 2 ftpadmin ftpadmin 1024 Jul 18 01:00 incoming
or if you want to use the 'secret' directory approach for uploads:
drwxr-x--x 3 ftpadmin ftpadmin 1024 Jan 2 1999 incoming/
drwxrws-wt 3 ftpadmin ftpadmin 1024 Jan 2 1999 incoming/secret_upload_dir
ls, tar, and gzip live here. tar and gzip are optional and used for on-the-fly compression. All files should be compiled statically, mode 111, and owned by root. NEVER put any command interpreters in here.
Passwd and group files go in here, and possibly other needed files like pathmsg (see above). Please note, however, these should NOT be the same files from /etc/passwd and /etc/group. This would permit anyone to retrieve a copy of your account information. Instead, they should contain only the usernames and groups of files in t
he FTP directories, and NO password information. An example might be
lindstrom(root):/home/ftp# cat ./etc/passwd
lindstrom(root):/home/ftp# cat ./etc/group
- So what about the rest of those directories?
If you've done everything concerning /incoming you should be fine. There is no need for a /lib because all of our binaries are compiled statically. However, if you weren't able to compile your binaries static, the libs that they require would live here. /lost+found we've talked about earlier, (remember it's that directo
ry you magically get when you create a partition) and /pub will also be fine as long as sane user/group/permissions are used, as talked about in this section.
- Odds and Ends..
Adding .forward .rhosts to the FTP root would be a good idea to prevent these from being added later by some other means, such as an exploit. The justifiably paranoid may chattr +i these files.
/home/ftp[root(lindstrom)2]: touch .forward .rhosts
/home/ftp[root(lindstrom)3]: chmod 0 .forward .rhosts
/home/ftp[root(lindstrom)4]: chattr +i .forward .rhosts
Also, its a good idea to add ".notar" as well to your incoming directories so as to prevent keen users from downloading files using on-the-fly tarring.
- Other points of interest
For the paranoid, wu-ftpd has something just for you. Define paranoid in config.h and "questionable functions" will be disabled. Check out FIXES-2.4-HOBBIT from wu-ftpd source for more info on this.
Support for S/Key and OPIE are included in wu-ftpd, and I've seen patches for SSL and SRP floating around the internet. SSL for wu-ftpd is at ftp://ftp2.replay.com/pub/crypto/crypto/SSLapps/. However, it's a bit dated as far as keeping up with recent versions of wu-ftpd. There i
s also edssl (a non SSL to SSL translator) in the /pub/crypto/crypto/SSLapps/SSLlynx/ directory on that site. SRP patches can be found at MrWizard's homepage along with some other nifty things.
Comments, suggestions, or additions are welcome. Just point them to email@example.com.
jh is a freelance UNIX Systems Administrator with over 4 years of experience maintaining machines and networks throughout the south-east.