Hello,

I had a question regarding random PID usage and implementation in
OpenBSD. Sorry by advance if my question may seem obvious, but I did
not manage to find any really satisfying answer.

I was reading an article (french magazine MISC issue 74) written by the
author of CVE-2014-0016 (stunnel) and CVE-2014-0017 (libssh) affecting
the random number generator used by the server to construct the hello
cookie.

These software were using the child process PID + a Unix timestamp as
seed. The author demonstrated how, on systems using random PIDs, it was
therefore easy to trick the system into generating two times the very
same cookie (a very few minutes with an average of as few as 20
requests per second), thus giving the opportunity to deduce private
keys thanks to some cryptographic magic out of scope here.

On the other side, systems using a traditional sequential PID were
practically not vulnerable to this attack since it would need to be
able to remotely make the server cycle through all the available PID in
less than a second.

As per my understanding, random PID was implemented mostly in order to
protect bogus application using the PID to generate temporary file
names and other "race conditions" (cited by most sources without ever
defining what kind of race condition they precisely mean). The example
above show that it just does not prevent race conditions, actually it
helps them, and while it protect against the locally exploitable
temporary file name prediction it opens remotely exploitable flaws
which seems worse.

FreeBSD servers are particularly subject to such attacks because they
generate really random PIDs, so it takes 3-4 minute in average with 20
requests per seconds to get the system generate two identical PID
during the same second.

OpenBSD, as a security conscious OS, has already implemented a
protection against such exploit (cool :) !), but I'm surprised by the
technical choices made here (less cool :( ). The protection has been
added in the revision 1.150  (mid-2013) of the file
`src/sys/kern/kern_fork.c'. It adds a array of a fixed and hardcoded
size of 100 entries storing the lastly freed PIDs (`pid_t
oldpids[100];').

So, blindly execute the 20 requests described in the article will
indeed not work on a lowly loaded OpenBSD system. However, on a highly
loaded system (whether the load results from genuine traffic or is part
of the attack), this array will just become useless and OpenBSD falls
as well as FreeBSD.

Years ago (2003) Theo de Raadt wrote an email
(http://www.monkey.org/openbsd/archive/misc/0301/msg00720.html) as part
of a discussion related to PID randomization side-effects in which he
mentions "At best, we could use some sort of high-bit non-repeating
trick like we do with dns and ip id's". I suppose he was referring to
what has been implemented in `src/sys/netinet/ip_id.c' ensuring that
"an ID will not be reused for at least 32768 calls".

I was wondering why this has never been implemented? At the first
glance, this seem to be the safe and best way to do, isn't it?

PID related security issues mainly seems to come from application
wrongly assuming that:
- PID are unguessable,
- PID will not be reused quickly.

IMHO PID full randomization as implemented in FreeBSD correctly
addresses the first assumption, but heavily breaks the second one. A
more clever partial randomization would address both aspects,
effectively improving security for both local and remote attacks. The
current small array of 100 entries seems quite weak to me,  while the
model based on IP id generation would seem more resistant but has
nevertheless be left in profit of this small array... I suppose there
must be a good reason behind this choice, but I do not manage to get
it, would you help me to understand this?

Thank you by advance,
Best regards,
Simon.

Reply via email to