In this article:
To make things short, this flaw relies on the fact that a hello cookie created by the server is generated using the current Unix timestamp (so up to the second) and the PID of the process handling the request. The exploit sends a high number of connection attempts in order to force the server to generate duplicated cookies. At the end this attacks aims to deduce the server private keys.
The author explains that such attack is not realizable on systems using traditionnal sequential PID because it would require more than 65000 connections attempts to made in less than one second.
However, thanks to random PIDs used on some “hardened” systems the author demonstrates that, with 20 connection attempts per seconds, there is statistically more than one chance over two to generate a duplicate in less than 5 minutes.
For me, this clearly shows that random PID creates new security weaknesses (and a remotely exploitable in this case) over sequential PIDs.
Poorly coded software are using the PID to generate “unique” temporary file names and as a main source of entropy: poorly coded software should remain limited to “Hello world” projects and minesweepers ports and should never be used for sensitive tasks.
Moreover, weakening the whole OS just to bring a marginal security gain for such software seems really counter-productive.
At last, the flaws above show that as long as entropy is concerned, sequential PID would be even more secure than random ones…
Protection against unknown future threats: I do not see the logic behind opening severe current and known threats to protect against potential future and unknown threats…
Race conditions: if it refers to the poor software using the PID to generate temporary file names, then I already covered this point. Otherwise, the flaw above shows how random PID is actually more prone to race conditions than sequential ones.
OpenBSD already uses it: this is indeed a good explanation regarding the fashion aspect of this measure, but it has nothing to do with security.
PID randomization was popularized by OpenBSD which added it as soon as 1997. At that time it pursued two main goals:
Protect against PID prediction vulnerabilities affecting mostly software which use the PID value to generate temporary file names. This was a common concern at that time, but today I think it would be quite rare to encounter production-level software still not using a cleaner method.
As a general preventive measure, “If something can be random, make it random.”, encompassing putting randomness at several places in the OS (from the IP stack to the memory allocation). While some of the protection resulting from this randomness proved to be useful and became more common, PID randomization has a more troubled history.
As detailed above, the cure may be worse than the disease. Due to faster PID reuse, fully random PID may allow remotely exploitable flaws, while sequential PID was mainly known to allow local-only exploits.
As a side note, in an ideal world, all this should not cause any issue (yes, I talk of this ideal world where software is free of bug and vulnerability). In fact these vulnerabilities usually find their root in wrong usage of the PID. Wikipedia finely defines the PID as being a “number used […] to uniquely identify an active process“.
A PID is not designed to build temporary file names.
Temporary files are usually created in a shared place, and that means danger! Because of this, temporary files must be created using dedicated functions which will ensure that the three required actions (checking that the file doesn’t already exists, create it and set restricted access permissions) are done in an atomic (uninterrupted) way. The C language proposes
tmpfile(), and most Unix environments offer a mktemp command to be used by shell scripts, etc.
A PID is not designed to seed a random number generator or generate session ID or cookies.
Here again you must refer to your language or environment documentation to get a proper entropy source. On UNIX systems the
/dev/urandomdevice file is there for this purpose.
It is not by accident that Wikipedia definition precises active process.
On some language like C, you stay proprietary of the child process’ PID until you
waitfor it, but this is not true for all languages (for instance in shell scripts…) and never true for processes which are not your child. In these cases the PID is just a shared resource, and you should remember that this “shared” notion implies “danger“, so must therefore ensure that your take proper care and use the right functions designed to match your situation and needs.
Linux kernel main stream never implemented PID randomization, however this feature was commonly provided for several years through a security oriented third-party patch which finally decided to abandon it.
Around year 2000-2001, several people tried to implement PID randomization for the Linux kernel (examples can be found here and there), however none of these patches were accepted by the kernel development team who rejected them mostly as “security through obscurity”.
However, since randomness may actually increase the global security posture of the OS and prevent some attacks, these kernel modifications finally reached their public through the third-party project: grsecurity.
This project started in 2001, bringing several new and advanced security
features to the Linux kernel. It allowed to enable/disable randomized PID using
kernel.grsecurity.rand_pids. However, in
the late 2006 (I guess - I hate news thread mentioning dates with no
year!) they finally decided to drop randomized PID functionality:
grsecurity 2.1.10 was released today for Linux 2.4.34 and 184.108.40.206. Changes in this release include:
- Removal of randomized PIDs feature, since it provides no useful additional security and wastes memory with the 2.6 kernel’s pid bitmap
OpenBSD having initiated randomized PID functionality, it is still present for historical purposes but has no real security scope nowadays. It is up to the application themselves to ensure they correctly handle fast PID reuse.
OpenBSD aim is to encourage good development practices and thorough code security auditing. That’s why they consider that it is not the responsibility of the OS to protect their users against flawed application. On the contrary an application flaw should be detected as soon as possible and corrected in the application instead of remaining hidden by OS (”The sooner we can break it, the sooner we can fix”).
As a side note, while such assertion justifies itself for the base OS which is under direct control of the OpenBSD team, this becomes more discutable with third-party software:
- Which do not go through the same audit as the base OS,
- While OpenBSD provides and recommends the use of binary packages over ports, no binary updates are provided between OS releases (every 6 months)1
- Some software versions may be outdated. For each case this might be either a deliberate choice from OpenBSD team or a consequence of the lack of resources in OpenBSD team.
However, in this context OpenBSD team makes the assumption that, for a correctly developed and audited software, the PID generation algorithm chosen by the OS must have no impact (neither stability nor security) on the software behavior. If some software is vulnerable to an attack taking advantage of the PID being reused, then it’s up to the software to be corrected, and not to the OS to ensure that the PID are not reused too quickly2.
FreeBSD provides a
sysctl parameter allowing the administrator to tune the
PID generation algorithm from sequential to fully random. It is sequential by default.
FreeBSD implemented random PIDs in 1999 (FreeBSD 4), using OpenBSD as reference, and improved it to let the administrator set a balance between potential issues caused by sequential PID (mostly PID prediction) and potential issues caused by PID randomization (PID reuse and resource consumption).
In fact, FreeBSD design seems quite original since it is not actually the PID
which is random, but the PID increment which is a random value taken between 1
- If PID randomization is disabled, then the increment will always be 1,
- At maximum this parameter can be set to
PID_MAX3, in this case the next PID will be fully randomly chosen.
By default PID randomization is disabled (PIDs are generated sequentially).
To take effect, the
kern.randompid parameter must be at least greater than 100.
If sequential PID remains a concern, I would personally recommend to set this parameter to a low value like a few hundreds: this should be sufficient to limit trivial PID prediction issues while avoiding more nasty issues caused by PIDs re-use.
Article based on a StackExchange answer.
For the curious, OpenBSD added in 2013 an hardcoded table storing the 100 lastly freed PIDs in order to limit reliability issues on low loaded systems. However, this does not constitutes a security measure since it quickly becomes effectless with higher loads, would this load be caused by genuine activity or as part of an attack. ↩
For the purists it is actually
PID_MAX - 100to cover only non-reserved PID range, it can also be set by using the special value
-1. Out of range values are corrected immediately when setting the
sysctlparameter so no risk to cause any damage here anyway. ↩