Date: Sat, 27 Feb 1999 15:00:00 -0500 (EST) From: Gregory A Lundberg To: WU-FTPD Discussion List Subject: upload.configuration.HOWTO This document is available on-line at: ftp://ftp.vr.net/pub/wu-ftpd/upload.configuration.HOWTO One of the more powerfull, yet most often misused, features of WU-FTPD is the upload clause. Historically, the problems with the upload clause stem from unclear documentation and poor implementation. This document is an attempt to address these issues. The features discussed in this document apply to WU-FTPD Version 2.4.2 (Beta 18) VR14. If you are not running VR14, you are strongly encouraged to upgrade; the VR updates include a number of corrections and security enhancements not available with earlier versions of WU-FTPD. Upload restrictions for anonymous FTP users ------------------------------------------- For this example, we'll assume your system /etc/passwd file contains an entry for the anonymous FTP user as follows: ftp:*:95:95::/home/ftp: If your /etc/passwd file does not contain an entry for the user 'ftp' your site will not allow anonymous FTP. In addition, if the usernames 'ftp' or 'anonymous' appear in the /etc/ftpusers file, anonymous FTP will not be allowed. In /etc/ftpaccess, we need a class which allows anonymous access. The following allows anonymous FTP from anywhere: class anonftp anonymous * To prevent anonymous FTP users attempting a Denial of Service (DoS) attack against your system, you should create a special filesystem to receive their uploads. This separate filesystem protects your server by limiting the total size of all uploaded files while preventing those files from consuming all available space on the server. For this example, mount the filesystem on /home/ftp/incoming By default, the server will not allow uploads from anonymous FTP users. Just to be safe, and so we don't forget, let's add a clause saying that: upload /home/ftp * no What this says is, "For any user whose home directory is the anonymous FTP area, /home/ftp, do not allow any uploads." As I said, this is the default, but put it in anyway so you don't forget. Now, we want to allow uploads into the incoming filesystem. We MUST add a clause granting that privilege to anonymous users. Right now we don't want to let anonymous users create directories. (I recommend NEVER allowing them to do it, but I'll show you how in a bit.) We want to ensure, however, that the server is safe, and that it cannot be used as a way-point for software pirates (warez traders). So we'll set the directory permissions for the incoming area to prevent anyone seeing what's there and make the area write-only for anonymous users. First, we need an FTP site administrator, someone who owns the files, but isn't the root user or the anonymous user. Something like the following /etc/passwd entry will do: ftpadmin:*:96:96::/home/ftp: Set the incoming area permissions and ownership to safe values. I recommend the following: chown ftpadmin /home/ftp/incoming chgrp ftpadmin /home/ftp/incoming chmod 3773 /home/ftp/incoming Actually, ftpadmin should own more of the site, but I'm only talking about uploads right now. Finally, before we get into allowing uploads, one last thing. Whether you allow on-the-fly tar'ing of directories or not, you should make sure that an end-run cannot be made and the incoming area downloaded using tar. To do that, create the special file '.notar' in both the FTP directory and the incoming area: touch /home/ftp/.notar chmod 0 /home/ftp/.notar touch /home/ftp/incoming/.notar chmod 0 /home/ftp/incoming/.notar The zero-length .notar file can confuse some web clients and FTP proxies, so let's mark it unretrievable. noretrieve .notar Time to allow uploads, put the following in /etc/ftpaccess: upload /home/ftp /incoming yes ftpadmin ftpadmin 0440 nodirs Notice the target directory for the uploads is relative to the view the user will have during the FTP session. What this says is, "For any user whose home directory is the anonymous FTP area, /home/ftp, allow uploads into the directory /incoming but do not allow the creation of new directories. Make all files uploaded owned by the FTP administrator, mark them read-only so we don't allow them to be downloaded." If uploaded files are to be made available for downloading, the safest thing to do is to tell the FTP administrator to move them into a public area and modify the permissions after validating and approving them. I know this seems draconian but, in the long run, it's best. Some FTP sites like to live dangerously and allow anonymous users to create directories. I don't recommend this; it cannot be done with absolute safety. If you insist, however, you can at least limit it to a single directory level. For example, replace the upload clause just added with the following: upload /home/ftp /incoming yes ftpadmin ftpadmin 0440 dirs 3773 upload /home/ftp /incoming/* yes ftpadmin ftpadmin 0440 nodirs The first line allows directories to be created in the incoming area and enforces the use of safe permissions on them. The second prevents creation of deeper sub-directories. Notice that one of the problems with allowing directory creation is there is no way to automatically create a '.notar' in the new directory, so a crafty user may be able to make an end-run and download it anyway using on-the-fly tar'ing. One last thing: since the incoming area shouldn't allow downloads, and since it's a file system, there will be a lost+found area; you will want to add the following clause to make SURE no downloads occur: noretrieve /home/ftp/incoming/ or, at least, add the following to prevent downloading of the lost+found files: noretrieve /home/ftp/incoming/lost+found/ Upload restrictions for guest users ----------------------------------- Setting up the FTP server for guest users is covered in the Guest HOWTO. It is not my purpose here to cover how to set up for guest access. If you have not yet done so, review the information in that document at: ftp://ftp.fni.com/pub/wu-ftpd/guest-howto For this example, I'll assume you have entries similar to the following in your system /etc/passwd file: dick:*:1010:1010::/home/users/./dick:/bin/sh jane:*:1011:1011::/home/users/./jane:/bin/sh By default, the WU-FTPD server will grant upload privileges to all guest users. The example users are chroot'd to /home/users and cannot access any area of the filesystem outside that directory structure. What we're interested in, then, is simply protecting the areas in the chroot directory structure we want to keep the users out of. In a minimal installation, there will be bin, etc and dev, subdirectories in the /home/users directory. Other files and subdirectories may exist depending upon the requirements of your operating system. We don't want users being able to upload into these areas. In case something happens to the permissions on them (you did set the permissions to safe values, didn't you?), you should deny upload privileges in your ftpaccess file. In our case, we'll say the following: upload /home/users/* / no upload /home/users/* /bin no upload /home/users/* /etc no upload /home/users/* /dev no While we're at it, we'll prevent downloads with noretrieve. Don't forget to prevent end-runs by also creating .notar files in each directory. noretrieve /home/users/bin/ noretrieve /home/users/etc/ noretrieve /home/users/dev/ Upload restrictions for real users ---------------------------------- First off, let me say that you shouldn't have any real users in your FTP site. Or, being more realistic, the only real user should be the site administrator. That being said, real users should be restricted to uploading only into specific areas. Let's start with a real user in /etc/passwd: ftpadmin:*:109:109::/home/users/ftpadmin:/bin/sh Again, by default, the server will grant upload privileges everywhere, so we have to start by revoking them and only allowing what we want to: upload /home/users/ftpadmin * no upload /home/users/ftpadmin /tmp yes nodirs upload /home/users/ftpadmin /home/users/ftpadmin yes upload /home/users/ftpadmin /home/users/ftpadmin/* yes upload /home/users/ftpadmin /home/ftp/incoming yes ftpadmin ftpadmin 0440 nodirs About matching rules -------------------- In the last example, you will notice there are two rules for the ftpadmin's home directory. It may seem simpler to just say: upload /home/users/ftpadmin /home/users/ftpadmin* yes But, if you do, there will be unintended consequences. In the example, we're trying to restrict upload privileges to just the ftpadmin's home directory. The appearently simpler rule will match other directories, which we don't want to allow. Consider, it will match all of the following directories: /home/users/ftpadmin /home/users/ftpadmin/mirrors /home/users/ftpadministration This last directory isn't wanted. Using the two rules as shown in the example will prevent matching it and accidentially allowing uploads as would happen if we used the appearently simpler single rule. umasks for guest and real users ------------------------------- In most cases you will want to allow guest and real users to control the permissions on their own files and directories. As in the examples shown, if there are no specific permissions given on upload clauses, any new files or directories created will have all permissions set. umasks can be used to reduce these permissions. The daemon has a command-line option (-u) to set the default umask for all users. Follow the -u option with an octal permissions mask. Bits in this mask are permissions to turn off whenever the daemon creates a new file or directory. The manpage for ftpd documents the -u option. Often times, the global -u option is not sufficient. In the ftpaccess file, you can control umasks by class by using the defumask clause. If no class is given, defumask overrides the -u umask from the command line. If the current user is a member of the named class, defumask overrides the umask setting for this user only. For example, assume there are several classes of users class admin real 10.0.0.0/8 127.0.0.0/8 class local guest 10.0.0.0/8 127.0.0.0/8 class remote guest * class anon anonymous * ( Notice, by the way, in this example, real users will not be allowed access unless from the local network since they are not in any class when coming from an outside IP address. Since the daemon gives no clue to the remote user in this case, to outside addresses it will appear as if the admin users do not exist on the server. The specific cause for their login failure will appear in your system logs. ) We can control the umask by class for these users. For example, we might say: defumask 0377 defumask 0177 admin defumask 0133 local remote The first clause applies whenever another defumask clause does not match the current user's class. This is the same as adding '-u 0377' to the command line for the FTP daemon. In this case, the clause applies only to anonymous users since all other classes have specific default umasks given. The second turns off execute permissions, as well as group- and world- read and write permissions, for all files and directories created by real users (users in the admin class). The last rule turns off execute permissions and group- and world-write permissions for files and directories created by guests (in the local and remote classes). Remember that umasks apply to ALL files and directories created EXCEPT those where an upload clause applies AND the upload clause gives specific permissions. Disabling execute permissions will cause problems using newly created directories; leaving them enabled is unsafe because all files uploaded will have execute permission and could, therefore, be used in attempts to break into the server. I recommend disabling all execute permissions and instructing your users to use the chmod command to add execute permissions to directories or to change the umask before creating directories. This may be a bit more work for your users, but it is safer than having a Trojan Horse program marked executable just waiting for someone, possibly root, to try running it. umask and chmod command restrictions ------------------------------------ As just mentioned, users have the ability to change the current umask and modify the permissions on files and directories. Obviously, you will want to disable this feature for anonymous users. You may also want to control who may use these features for your guest and real users. The defaults should be acceptable for most sites. The default settings are equivalent to the following (which you may want to add to your ftpaccess file so you don't forget): chmod no anonymous chmod yes real,guest umask no anonymous umask yes real,guest If, for example, you wanted to disable these commands for guests accessing the server from outside the local network, you could add the following: chmod no class=remote umask no class=remote Be sure to insert these _before_ the 'yes' clauses. Order is important; the daemon will apply the first matching rule it finds. If you do something like this, it is probably safer to rewrite the clauses to deny everything but what you allow. For example: chmod yes real,class=local umask yes real,class=local chmod no guest,anonymous umask no guest,anonymous Delete, overwrite, rename restrictions -------------------------------------- The daemon also provides control over the user's ability to delete, over- write and rename files. Again, the defaults are probably acceptable in most cases. These are: delete no anonymous delete yes real,guest rename no anonymous rename yes real,guest overwrite no anonymous overwrite yes real,guest As with the chmod and umask clauses, you can control these by class as well. Continuing the above example, restricting these to local users only, we could instead say: delete yes real,class=local rename yes real,class=local overwrite yes real,class=local delete no guest,anonymous rename no guest,anonymous overwrite no guest,anonymous Per-class upload clauses ------------------------ Just as we can restrict the ability to change permissions, delete files, etc., we can also define upload clauses which apply only to specific classes of users. For instance, with the classes from the above examples, we can revoke upload rights for remote guests. For example, we can deny all uploads the remote guests except to their personal tmp directories: upload class=remote /home/users/* * no upload class=remote /home/users/* /*/tmp yes nodirs Private incoming areas ---------------------- Often times, users would like to have private areas in the FTP site. Sometimes, it is usefull to also have incoming areas in those private areas. Examples of the permissions for private areas can be found in the layout at ftp://ftp.vr.net/pub/wu-ftpd/examples/ and, other than ownership, are no different than the public incoming area, so I'll simply present the upload clauses here. For this example, we'll allow anonymous uploads into all private incoming areas: upload /home/ftp /private/*/incoming yes * * 0440 nodirs upload /home/users/ftpadmin /home/ftp/private/*/incoming yes * * 0440 nodirs The assumption here is Unix shell users have private areas in the anonymous site. Those areas are owned by the appropriate user, and incoming files are to be owned by that user. The wildcard match on directory allows anonymous uploading to any private incoming directory. The wildcard for owning user and group instructs the daemon to set the file's ownership to that of the directory receiving it. Don't forget, if you allow private incoming areas, that they are open for anonymous access and you should take care to ensure a DoS attempt to fill the file system cannot take out your entire server. Create a separate filesystem for the private incoming areas or put them inside the public incoming area. Differences from earlier versions --------------------------------- This HOWTO was written for the VR upgraded versions of the WU-FTPD server. Earlier versions used different rules for the upload clause. Some versions of the daemon required the first parameter to be the name of the root directory for the chroot. This allowed upload control by area, but did not provide for different rules on a per-user basis. Some versions of the daemon required the first parameter to be lexically identical to the user's home directory entry. This was non-obvious and the '/./' was often forgotten. Some versions of the daemon got totally confused, attempted to apply both these methods at once, and ended up ignoring all your upload rules. If you were smart, you had your permissions set properly and didn't notice. Early versions of the VR upgrades, and all earlier versions of the daemon, allowed file system modification as the default for all users. The current VR upgraded version does not allow any modification commands (ie., upload, delete, rename) by anonymous users unless specifically granted in the ftpaccess file. Early versions of the VR upgrades, and all earlier versions of the dameon, had no method for specifying the permissions for a newly created directory. Also, they required exact matches for the first parameter (no globbing) and exact user and group names or numbers for ownership file files and directories. -- Gregory A Lundberg Senior Partner, VRnet Company 1441 Elmdale Drive lundberg@vr.net Kettering, OH 45409-1615 USA 1-800-809-2195