We're a company that builds web sites (among other things) and are transitioning from moving most of our clients from various crappy shared hosting accounts to our own FreeBSD-powered web server. Some of them got used to the idea of having FTP access to their accounts at the shared hosting services - for example, a photographer who often sells prints and used equipment via eBay wants to be able to host photos for his auctions from his webspace without having to use some cheesy web-based file uploader to get the files uploaded. Previously, we just had accounts/access for the sysadmins, but it was becoming clear that that's going to be untenable. So after reading up on it in Absolute FreeBSD, I created some chrooted user accounts with /dev/null as their shell and fired up ftpd via inetd.

Issues:

I'd prefer to have people be able to connect via SFTP, but it looks like doing this chrooted will be some big huge ugly affair involving setting up jails and using the sftponly shell, which is really more complicated than I think it should be. Is there any way to simply say, "Okay, behave just like ftpd is now, but also allow SFTP connections?"

Also, is there any way to make it so these users can absolutely, positively never set the execute bits on any file they upload?

Any other security tips for this sort of a situation would be appreciated. Thanks in advance.

I'd prefer to have people be able to connect via SFTP, but it looks like doing this chrooted will be some big huge ugly affair involving setting up jails and using the sftponly shell, which is really more complicated than I think it should be. Is there any way to simply say, "Okay, behave just like ftpd is now, but also allow SFTP connections?"

To avoid confusion, there are two kinds of sftp:
o Secure File Transfer Program -- This is part of SSH and has little to do with the ``real'' FTP but is similar in operation.
o FTP with SSL/TLS encryption added. usually called ftps and more or less the same as https.

I'm not sure which you are using.
For the SSH sftp you can use the ChrootDirectory option in sshd_config and should be fairly easy to setup.
One advantage of sftp is that you van use ssh-keygen for keys, which is more secure.

__________________
UNIX was not designed to stop you from doing stupid things, because that would also stop you from doing clever things.

I was speaking of SSH's SFTP, as it's my understanding that that is more commonly implemented in FTP clients and WYSIWYG editors than FTP with SSL/TLS - please correct me if I'm wrong.

Chrooting folks logging in via SSH is sort of tangental to the problem; if possible, I'd prefer that folks not be able to log in to the server via a shell at all, and only be able to transfer files. Maybe that's unavoidable…?

After perusing the suggested man pages (no, really, I did!), I configged sshd_config as suggested. Logging in wasn't working, though. Finally I went through and read the directions on http://www.minstrel.org.uk/papers/sftp/builtin/ a bit more closely, and noticed:

Quote:

Important (OpenSSH tests for this condition): ensure their home directory is owned by root, and is not writable by any other user or group. This must also be the case for each directory in the path up to the root of your system.

Aww, damn! That's not going to work, because the web server (which is not running as root) is going to need write access to this directory too. (If I created a home directory which met these requirements, things worked, so otherwise this seems to be the only obstacle.)

I tried various things with symlinks, but couldn't trick OpenSSH. I'll keep experimenting, but it looks like I may have hit another wall.

This is indeed true. Sorry, forgot all about that. It is buried in the man page(s), somewhere. [EDIT: in sshd_config(8), under ChrootDirectory]

A simple solution would be to have all of the users share a $HOME directory owned by root, and then they can "cd" into their individual, writeable-readable-just-by-them personal directory underneath. e.g.: Give root ownership and control of a read-only directory, /home/sftpusers. Have the *actual* personal directories one folder in, such as /home/sftpusers/user1, /home/sftpusers/user2, etc.

There might even be a way to programatically automate a cd into the individual's directory at sftp login time, though I've never investigated such a feature.

Ah, you were too quick with a reply… I found a solution. I just created a new home directory which was owned by root, set that as the user's home dir with chpass, moved all of the web files into a subdirectory in that directory, then linked to that directory from where the web server was looking for those files. It works! Previously, I was trying to link the other way around. So… Success! Thanks again, Carpetsmoker and jggimi.

Still looking for advice on how to make sure users can't set execute bits on uploaded files - though I may be able to figure that one out on my own.

That's not a terrible idea, but unfortunately I don't have /home on a separate partition and don't have the luxury of being able to repartition at the moment. (And there's some interesting discussion about the efficacy of noexec I found in this thread on the freebsd-security mailing list - see this post specifically.)

Though I've been thinking… If users don't have shell access, then they can't really run applications, right? The real concern here is that they upload a PHP script and set it executable, then try to access that script in a web browser so that the web server passes it to the PHP interpreter and it gets executed. But what if I simply configure the web server so that it never tries to execute files in user directories? That way, trying to access it simply causes it to be passed through to the user as if it were a text file. That might be all I need.