Postfix Overview - Security


Note: this web page is no longer maintained. It exists only to avoid breaking links in web pages that describe earlier versions of the Postfix mail system.

Up one level | Introduction | Goals and features | Global architecture | Queue Management | Security

Introduction

By definition, mail software processes information from potentially untrusted sources. Therefore, mail software must be written with great care, even when it runs with user privileges, and even when it does not talk directly to a network.

Postfix is a complex system. The initial release has about 30,000 lines of code (after deleting the comments). With a system that complex, the security of the system should not depend on a single mechanism. If it did, one single error would be sufficient to compromise the entire mail system. Therefore, Postfix uses multiple layers of defense to control the damage from software and other errors.

Least privilege

Most Postfix daemon programs can be run at fixed low privilege in a chrooted environment. This is especially true for the programs that are exposed to the network: the SMTP server and SMTP client. Although chroot(2), even when combined with low privilege, is no guarantee against system compromise it does add a considerable hurdle. And we all know that every little bit helps.

Insulation

Postfix uses separate processes to insulate activities from each other. In particular, there is no direct path from the network to the security-sensitive local delivery programs. An intruder first has to break through multiple programs. Some parts of the Postfix system are multi-threaded. However, all programs that interact with the outside world are single-threaded. Separate processes give better insulation than multiple threads within a shared address space.

Controlled environment

No Postfix mail delivery program runs under control of a user process. Instead, most Postfix programs run under control of a resident master daemon that runs in a controlled environment, without any parent-child relationship to user processes. This approach eliminates exploits that involve signals, open files, environment variables, and other process attributes that the UNIX system passes on from a possibly-malicious parent to a child.

Set-uid

No Postfix program is set-uid. Introducing the concept was the biggest mistake made in UNIX history. Set-uid (and its weaker cousin, set-gid) causes more trouble than it is worth. Each time a new feature is added to the UNIX system, set-uid causes a security problem: shared libraries, the /proc file system, multi-language support, to mention just a few examples. Set-uid makes it impossible to introduce some of the features that make UNIX successors such as plan9 so attractive, for example, per-process file system name spaces.

Initially, the maildrop queue directory was world-writable, so that local processes could submit mail without assistance from a set-uid or set-gid command or from a mail daemon process. The maildrop directory was not used for mail coming in via the network, and its queue files were not readable for unprivileged users.

A writable directory opens up opportunities for annoyance: a local user can make hard links to someone else's maildrop files so they don't go away and/or are delivered multiple times; a local user can fill the maildrop directory with garbage and try to make the mail system crash; and a local user can hard link someone else's files into the maildrop directory and try to have them delivered as mail. However, Postfix queue files have a specific format; less than one in 10^12 non-Postfix files would be recognized as a valid Postfix queue file.

Because of the potential for misbehavior, Postfix has abandoned the world-writable maildrop directory, and uses a small set-gid postdrop helper program for mail submission.

Trust

As mentioned elsewhere in the overview, Postfix programs do not trust the contents of queue files or of the Postfix internal IPC messages. Queue files have no on-disk record for deliveries to sensitive destinations such as files or commands. Instead, programs such as the local delivery agent attempt to make security-sensitive decisions on the basis of first-hand information.

Of course, Postfix programs do not trust data received from the network, either. In particular, Postfix filters sender-provided data before exporting it via environment variables. If there is one lesson that people have learned from Web site security disasters it is this one: don't let any data from the network near a shell. Filtering is the best we can do.

Large inputs

Other defenses


Up one level | Introduction | Goals and features | Global architecture | Queue Management | Security