Why Using Chroot in an FTP Server Is Insecure

DONG Yuxuan @ Jan 07, 2020


The famous FTP server program vsftpd has an option chroot_local_user. If it’s set to YES local users will be (by default) placed in a chroot() jail in their home directory after login. Intuitively this would make the server more secure but the document of vsftpd notes the following.

Warning: This option has security implications, especially if the users have upload permission or shell access. Only enable if you know what you are doing. Note that these security implications are not vsftpd specific. They apply to all FTP daemons which offer to put local users in chroot() jails.

The document doesn’t explain the reason so I decided to note it here.

When a user connects to the server, the FTP daemon will, of course, call some system-calls to function. Thus it may load things from a dynamic library, for example, libc. The user can put a faked library in $HOME/lib/x86_64-linux-gnu/libc.so.6. There is no damage if chroot is not called. However, if it does, the FTP daemon will think the faked libc is the real one because $HOME becomes the root path, and of course, you’re hacked.

However, after a discussion with Gogdizzy, I have realized this case is very hard to trigger. For the above example about libc, the FTP daemon usually has loaded libc before chroot is called. The more important point is that if an FTP daemon loads any dynamic libraries after calling chroot, it will not work because it can’t find the library if the user doesn’t fake it.

Besides faking dynamic libraries, faking config files like /etc/hosts is also very hard. The reason is the same. If an FTP daemon reads a config file after calling chroot, it won’t work if the user doesn’t fake the file.

So, to trigger the case the FTP daemon must have a “load if it exists” or “read if it exists” strategy. It’s hard to find a reason why a secure-conscious FTP daemon will perform the strategy. However, the whole system is very complicated. It will be too harsh to ask the programmer developing the FTP daemon to figure out every strategy of every function he called. God knows if there’s a library that takes the strategy.