123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- This document explains the design goals and decisions behind vsftpd.
- The importance of a secure design
- =================================
- In a world full of good, careful coders who do not make mistakes, a secure
- design would not be necessary. After all, in the absence of any programming
- errors, security would not differ no matter how the program is arranged.
- Unfortunately, this is not an ideal world, and coders make plenty of mistakes.
- Even the careful coders make mistakes. Code auditing is important, and goes
- some way towards eliminating coding mistakes after the fact. However, we
- have no guarantee that an audit will catch all the flaws.
- So, a secure design acknowledges the possibility of undiscovered flaws, and
- takes steps to minimise the security impact these flaws can have. An obvious
- example of something we want to do is to apply the principle of least
- privilege, which ensure that every part of the program runs with the privilege
- it needs and no more.
- An example of insecure design
- =============================
- Examples of insecure design may be found in most other ftpd's. That's one of
- the reasons vsftpd has been written. We'll pick on wu-ftpd as a specific
- example, since it is rumoured to run about half of all ftp services.
- If I log on to wu-ftpd as an anonymous user, a process is run on my behalf to
- serve my ftp session. Unfortunately, this process typically runs with full
- root privileges on the remote machine. This means that any security flaw
- present in parsing the copious ftp protocol will lead to full compromise of
- that machine. Two concrete examples are the recent wu-ftpd format string bug
- (June 1999), and a buffer overflow dealing with large paths a few months
- beforehand.
- Even OpenBSD's ftpd-BSD had a format string bug leading to remote root
- compromise of the affected machine, illustrating an earlier point about the
- requirement for secure design even in the presence of heavy auditing.
- Secure design under UNIX
- ========================
- vsftpd is written to run under UNIX-like operating systems, and so its secure
- design is constrained by the facilities offered by UNIX. Ideally, UNIX would
- have a proper security model which would offer fine grained access control
- to all system interactions (files, network, etc). It doesn't, but it does
- offer some useful and often overlooked facilities which help us to implement
- the principle of least privilege:
- - Strong inter-process communication facilities
- In UNIX, the process is a strongly defined boundary. Different privilege
- credentials may be assigned to different processes, which are not able to
- interfere with each other. This is a very basic facility of UNIX.
- It makes sense to use this facility to totally separate parts of a program
- which do not need to be privileged (most) from those parts that do (typically
- minimal).
- The privileged and unprivileged parts of the program then communicate via
- one of many UNIX IPC mechanisms - perhaps a socketpair or IPC (the former
- is attractive because UNIX lets you pass file handles over a socket).
- The minimal privileged process exercises the "principle of distrust" - it
- carefully filters what the unprivileged process asks it to do, so that even
- if the unprivileged process is compromised, it cannot ask the privileged
- process to do anything we don't want to allow.
- - chroot()
- chroot() is an often overlooked but useful tool. It can be used very
- effectively as a damage limitation tool.
- Imagine a remotely compromised process which does not run as root, but also
- does not use chroot(). Now look at what the attacker can do. Amongst the worst
- items are pilfering of all publicly readable files, and also attempting to
- execute any publicly executable suid-root programs to try and elevate
- privilege.
- Now imagine the same compromised process with a chroot() to an empty directory.
- The attackers options to do unpleasant things are substantially diminished.
- No, chroot() is not the ideal way to do what we have just accomplished, but
- it is what we have got to work with. In an ideal environment with fine
- grained security, we would default to having access to _no_ files at all, and
- deliberately not ask for access to any.
- - Capabilities (Linux 2.2+)
- Like chroot(), capabilities are essentially a damage limitation excercise.
- They are also much less widespread than the other UNIX facilities detailled
- above. Nonetheless, they warrant mentioning because Linux has them, and they
- are used in vsftpd because that is the primary devlopment platform.
- Capabilities split up the all powerful root privilege into lots of sometimes
- orthogonal privileges. Some of the capabilities represent privileges which
- are often the basis for requiring a program to run with full root privileges.
- Examples include CAP_NET_RAW (ping, traceroute) and CAP_NET_BIND_SERVICE
- (rlogin).
- By using capabilities to ensure we only have the privilege we need (within
- the somewhat disappointing granularity they offer), we again limit the
- potential damage of security holes.
- Presenting vsftpd's secure design
- =================================
- vsftpd employs a secure design. The UNIX facilities outlined above are used
- to good effect. The design decisions taken are as follows:
- 1) All parsing and acting on potentially malicious remote network data is
- done in a process running as an unprivileged user. Furthermore, this process
- runs in a chroot() jail, ensuring only the ftp files area is accessible.
- 2) Any privileged operations are handled in a privileged parent process. The
- code for this privileged parent process is as small as possible for safety.
- 3) This same privileged parent process receives requests from the unprivileged
- child over a socket. All requests are distrusted. Here are example requests:
- - Login request. The child sends username and password. Only if the details
- are correct does the privileged parent launch a new child with the appropriate
- user credentials.
- - chown() request. The child may request a recently uploaded file gets
- chown'ed() to root for security purposes. The parent is careful to only allow
- chown() to root, and only from files owned by the ftp user.
- - Get privileged socket request. The ftp protocol says we are supposed to
- emit data connections from port 20. This requires privilege. The privileged
- parent process creates the privileged socket and passes it to child over
- the socket.
- 4) This same privileged parent process makes use of capabilities and chroot(),
- to run with the least privilege required. After login, depending on what
- options have been selected, the privileged parent dynamically calculates what
- privileges it requires. In some cases, this amounts to no privilege, and the
- privileged parent just exits, leaving no part of vsftpd running with
- privilege.
- 5) vsftpd-2.0.0 introduces SSL / TLS support using OpenSSL. ALL SSL
- protocol parsing is performed in a chroot() jail, running under an unprivileged
- user. This means both pre-authenticated and post-authenticated SSL protocol
- parsing; it's actually quite hard to do, but vsftpd manages it in the name of
- being secure. I'm unaware of any other FTP server which supports both SSL / TLS
- and privilege separation, and gets this right.
- Comments on this document are welcomed.
|