`Date: Mon, 4 Jan 1999 00:04:09 -0500
From: Wietse Venema <[email protected]>
To: [email protected]
Subject: Anonymous Qmail Denial of Service
In recent postings, Daniel Bernstein expands on the insecurity of
the Postfix world-writable directory for local mail submission.
Of all the attacks possible with such a scheme, one attack would
result in mail not being delivered. That is of course unacceptable.
After my request for input from the Bugtraq membership I received
much useful feedback. Many suggestions were made for implementing
a private rendez-vous between unrelated, untrusting processes. I
will try write up a summary of the responses.
I am grateful for all suggestions for improvements that were made,
in particular for one suggestion made by Daniel Bernstein himself,
in this same forum:
Why doesn't [Postfix] use a protected queue, and a setuid
program to add mail to the queue with guaranteed user
identification?
Postfix uses a set-gid program and a mode 0770 submission directory,
and it does so for a very good reason. Why doesn't Postfix use a
set-uid program, as suggested? The reason is that contrary to Daniel
Bernsteins's claim, a set-uid posting program cannot guarantee user
identification. I will illustrate this misconception with an example.
qmail uses a set-uid posting program, called qmail-queue. When
this program is invoked, it opens a queue file somewhere below
/var/qmail/queue. For example:
-rw-r--r-- 1 qmailq qmail 0 Dec 31 17:02 queue/mess/21/674956
What happens when the qmail-queue process is signaled with, say,
SIGKILL? The file will stay in the queue. That's a zero-length
file, owned by qmail, without any user identification whatsoever.
Each time a user does something like:
% /var/qmail/bin/qmail-queue
^Z
Suspended
% kill -9 %1
[1] Killed /var/qmail/bin/qmail-queue
%
There will be one more zero-length file, owned by qmail, without
any user identification whatsoever. It is an exercise for the
reader to write a small program that automates the process:
fork a child
child: execute /var/qmail/bin/qmail-queue
parent: wait briefly and SIGKILL the child
When this sequence is executed a sufficient number of times, the
queue file system runs out of available resources. No-one can send
mail. No-one can receive mail. And no-one can be held responsible.
I fully agree with Daniel Bernstein that every mail system, be it
Postfix or qmail or anything else, should be able to add mail to
the queue with guaranteed user identification. I am grateful for
reminding me of this very important and very desirable property.
The lack of user identification as described above was verified on
BSD/OS 2.1, BSD/OS 3.1, and FreeBSD 2.1.1. It is reasonable to
expect that the same behavior exists on other BSD systems/versions.
When the same tests are run on Solaris 2.6, RedHat 5.0, and on
SunOS 4.1.3_U1, the only difference is in the queue file group
ownership attributes:
-rw-r--r-- 1 qmailq users 0 Dec 31 18:10 queue/mess/1/418325
What can be done about this lack of accountability? On non-BSD
systems, the hole can be worked around by placing every user in a
different group, so that a malicious user can be recognized by the
queue file group ownership. That will not close the hole on BSD
systems, however. For this reason, the preferable solution is to
close the hole by changing qmail. For this I suggest the use of a
set-gid posting program, similar to the one that is used in Postfix.
Wietse
-----------------------------------------------------------------------------
Date: Mon, 4 Jan 1999 10:39:13 -0500
From: Illuminatus Primus <[email protected]>
To: [email protected]
Subject: Re: Anonymous Qmail Denial of Service
On Mon, 4 Jan 1999, Wietse Venema wrote:
> What happens when the qmail-queue process is signaled with, say,
> SIGKILL? The file will stay in the queue. That's a zero-length
> file, owned by qmail, without any user identification whatsoever.
Signals are one of the many gateways between setid processes that
programmers can easily forget about. An easy remedy for the signal
problem is to log the real uid on startup and then set it to the effective
uid before doing anything important. This is probably what ping had to do
to fix the SIGALRM ping flood exploit.
In my opinion, though, the "preferable solution" is to not do setgid and
be happy that the ownership of the 0 byte files can be traced. As you've
said yourself, set[ug]id offers too many avenues for exploitation. The
supposed tightening of Postfix's security by using a setgid queue helper
seems to be unclean to me. Will Postfix's queue daemon behave correctly
when queue files can be dropped in half-written (SIGKILL to the setgid
queue helper while its writing)? Will the queue daemon behave correctly
if a queue file is left locked indefinetly (SIGSTOP or SIGKILL, depending
on how the lock is made)? The only clear advantage you have over
Bernstein's method is that the first interaction with the queue atomically
logs the caller's uid.
I think it is far easier to implement secure enforcement of policy when
the privilege levels are more clearly separated than in setid. Sending
the data through sockets is one way to accomplish this. Check out userv:
http://www.chiark.greenend.org.uk/~ian/userv/
I'm sure implementing something similar that allows portable
authentication of uids wouldn't be that hard - I can think of several
schemes right now.
`
Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation