When an AF_INET socket is bound to a specific port number using the bind(2) system call, the process can choose the specific port, or elect that the system choose. Normal UNIX behavior resulted in the system allocating port numbers starting at 1024 and incrementing. Our new code chooses a random port, in the range 1024 to 49151.
A similar issue existed with reserved port creation, using the bindresvport(3) and rresvport(3) library routines, which are supposed to pick a free port in the reserved range (typically between 600 and 1023). The old behavior was to allocate decreasing port numbers starting at 1023. The old code for these library routines effected this downward search using successive calls to bind(2); we have replaced this with code using a newer kernel interface which is much more efficient and chooses a random port number within the reserved range.
There are a number of poorly designed protocols (e.g., rsh, ftp) which are affected by predictable port allocation; we believe that our approach is making it harder for attackers to gain an edge.
Programmers often use this value as if it is random, possibly because of the compellingly attractive argument that ``pid numbers are effectively random on a busy enough system.'' Code like ``srandom(getpid())'' is quite common, as is code similar to that shown in figure 3.
In a normal system the attacker will have a very easy time predicting the PID and thus the obvious race attack is trivial. The race is as follows: the attacker creates the directory first, choosing the mode and ownership; subsequently it is possible to look at and replace files in the directory.
In OpenBSD, we use randomized PIDs, with a couple of obvious exceptions, e.g., init(8).
Sun Microsystems Remote Procedure Call (RPC) messages contain a Transaction Identifier (XID) which matches a sent query against its received reply. In most RPC systems, the XID of the first message a process transmits will be initialized using the code shown in figure 4.
Subsequently, the XID for each packet is simply incremented from this. Previously we mentioned that a local user might be able to guess what kind of range the next PID on the system might fall into; here we see that an outside attacker might also be able to determine this information. Our new code uses arc4random() to initialize the XID, and also avoids using two identical numbers consecutively.
The NFS protocol uses RPC packets for communication. The RPC XID issue also applied to the NFS code we encountered, and we now use the same mechanism for NFS XIDs.
The fsirand(8) program makes use of arc4random(3) to generate random inode numbers for filesystem objects (files, directories, etc.). This increases the security of NFS-exported filesystems by making it difficult for an attacker to guess filehandles (which are partially derived from inode numbers).
Each IP packet contains a 16-bit identifier which is used, if the packet has been fragmented, for correctly performing reassembly at the final destination. Previously, this identifier simply incremented every time a new packet was sent out. By looking at the identifier in a sequence of packets, an outsider can determine how busy the target machine is. Another issue was avoiding disclosure of information when using IPsec in tunneling mode, as per section 2.2.2. A naive implementation might create a new IP header with an ID one more than the ID in the existing IP header. This could lead to known-plaintext attacks [4] against IPsec.
To avoid these problems, we use the non-repeating PRNG described in section 3.3.
Inside the kernel, a 32-bit variable called tcp_iss declares the Initial Send Sequence Number (ISS) to use on the next TCP [32] session. The predictability of TCP ISS values has been known to be a security problem for many years [25]. Typical systems added either 32K, 64K, or 128K to that value at various different times. Instead, our new algorithm adds a fixed amount plus a random amount, significantly decreasing the chances of an attacker guessing the value and thus being able to spoof connection contents.