Types of Vulnerabilities

NOTE: Some USNs are "Multiple Vulnerabilities." These may contribute to multiple categories; or may supply multiple vulnerabilities from a given category. USNs supplying multiple vulnerabilities from a given category (for example, 5 buffer overflows) are counted as 1, because most of them are not clear on exactly how many.

Analysis

Most commonly (45%), vulnerabilities stem from buffer overflows.

The IBM Stack Smash Protector, or ProPolice, supplies an excellent, complete solution which is binarily compatible with non-protected code, and can be deployed to mitigate the threat of future buffer overflow based vulnerabilities. It protects passed arguments, local variables, the stack frame pointer, and the return pointer. Considerations not completely blocked mainly include structures, esp. those created on the stack or in arrays; but not pointers in the stack frame that reference heap based structures. The Protector is functional on many platforms, including at least i386 and x86-64, and probably many others which grow the stack down.

Bug #4374 should be tracked; it was submitted by the Hardened Debian project, and includes security enhancing patches for gcc. Among these is the IBM Stack Smash Protector. The Hardened Debian project is working on making these easily deployable from within Debian-based infrastructures, such as Ubuntu.

Also considerable is LibSafe, already in Universe. Adding libsafe to /etc/ld.so.preload provides buffer overflow protection. The difference is that libsafe prevents overflows from leaving the current stack frame, but notably not from clobbering the current stack frame's return pointer or function pointer; while ProPolice protects data inside the current stack frame. These two systems deployed together each cover some of the others' shortcomings. Libsafe can be built on x86-64, though the makefile requires a tweak, as it installs to /lib instead of /lib64 (as AMD and the FHS both mandate, 64 bit libs go to /lib64).

The next most common (18.3%) vulnerabilities involve tempfile races. There are two main ways to handle this.

GrSecurity supplies a Filesystem Protection called "Linking restrictions" which proactively prevents /tmp races. This option should be enabled by default in the Ubuntu kernel if it can be assessed that none of the Ubuntu main is affected by it. The restrictions prevent symlinks owned by other users from being followed in world-writable +t directories, unless the owner of the symlink is also the owner of the directory. Because it is not normal for a process to be running as two different EUIDs at the same time, this restriction should have no negative effects.

Applications should be audited periodically; the Debian Audit Project already does an excellent job of this. It is recommended here that all temporary file creation be considered a potential risk if mkstemp() and mkdtemp() are not used where appropriate; although tmpfile() may also be safe. The shell command mktemp(1) performs the same functions as mkstemp() and mkdtemp(), and should be used for all shell scripts creating temporary files and directories. The rational for this is that while it is easy to create temporary directories and files appropriately, a standardized interface provides us with a single point of failure. This is a good thing; in the event of a security flaw in mkstemp() and mkdtemp(), glibc can be fixed, which simultaneously repairs all inherited bugs. The unfortunate trade-off is that such a flaw creates a catostrophic, gaping hole.

Bad handling of malformed data (11.7%) and integer overflows (8.3%) make up a set of bugs which may execute arbitrary code (shellcode injection) or arbitrarily execute existing code out of order without the need of a buffer overflow. The IBM Stack Smash Protector may not catch these cases.

As some of these bugs allow the program flow to be modified in a controlled manner, a subset of this (19.0%) set of vulnerabilities can be proactively mitigated using PaX. Deploying PaX requires some research and development, especially when third party software is involved. The use of PaX can "break" third party software which expects A) executable stack/heap, or functional unsafe mprotect() calls. PaX is functional on a wide range of architectures, including i386, x86-64, PPC(32/64), SPARC(32/64), and PA-RISC. PaX can be deployed in several ways to mitigate these concerns, using various schemes to decide how to mark executables with flags that relax the restrictions PaX adds; however, there are problems with aiming for full compatibility. The more "compatible" you are with broken software, the less secure an environment third party software is run in, AND the less inclined third party vendors will be to properly mark or fix their software. Because a minimum of software is incompatible with PaX, it may be plausible to simply turn on full PaX and only give concern to marking and/or fixing core Ubuntu packages such as X.

(Second level bullets above should just be indented, wtf? indentation just makes one big paragraph in a bullet)

Conclusions

Somewhere between 61.7% and 81.7% of vulnerabilities can definitely be stopped before they're known. Thus, 61.7-81.7% of zero-day exploits can be prevented, reducing privilege escallations to simple Denial of Service attacks (software or system crashes).

45% of vulnerabilities (buffer overflow based) can definitely be proactively protected by deflecting an entire class of bugs.

19% of vulnerabilities (integer overflow and bad malformed data handling) may facilitate exploits which can be definitely proactively protected by deflecting two entire classes of exploits. PaX is able to deflect these classes of exploits by enforcing a more advanced and mostly compatible memory protection scheme.

18.3% of vulnerabilities (tmpfile races) can be protected via a GrSecurity Filesystem Protection known as "Linking Restrictions" which should cause no incompatibilities with existing software. Careful testing is still recommended.

These protections overlap in places; many buffer overflows are used as preludes to exploits stopped by PaX.

The USNs containing multiple from the same set reduce the figure from 87.3% to 81.8%.

The 18.3% of exploits known as tempfile races can be prevented proper coding practice as well.

This class of vulnerabilities can be prevented by the programmers using two functions to do the work of what would involve a couple tens of lines of code; and so following these practices is actually easier (and thus more natural once learned) than not.

All source code auditing should count the creation of temporary files and directories in any way aside from using mkstemp() and mkdtemp() as potential security bugs, whether they are now or "may later become" security flaws.

Any patches to replace existing temporary file and directory creation methods with mkstemp() and mkdtemp() should be submitted to the upstream maintainers immediately upon their verification.

The mktemp(1) command should be used in shell scripts to create temporary files and directories. The binary for this should physically exist in /bin, as it may be needed by init scripts or during system maintenance before /usr is mounted.

Kernel level code injection and buffer overflows may be deterrable in the future. The result of trapping security attacks in the kernel will most likely be a panic before the exploit can occur. Currently we only see 1 exploit here to trap this way, amounting to 1.7%.

The IBM Stack Smash Protector can be ported into the kernel.

PaX already contains some code to apply proper memory protections in kernel memory; however, this is a future goal and is not yet fully functional.

Of the first 55 USNs, 5.4% are kernel exploits. In contrast, of the first 60, 10% are kernel exploits. Only one of these exploits is actually a buffer overflow based exploit.

Exploits in the kernel can not be protected against proactively in most cases. Even when they can, the protection reduces intrusion to a DoS amounting to a complete takedown of the entire system. This makes kernel exploits, even as the smallest percentage, the largest threat. Rigorous auditing of the Linux kernel source code must be done continuously by volunteer audit groups, even when a subset of exploits can be trapped in the kernel. There is no other acceptable way to deal with these exploits than to actively and aggressively find and fix them.

In total, 81.7% of security alerts contain security holes which can be covered with the most obvious methods. Most if not all privilege escallation using these can be prevented regardless of programmer error, reducing the vulnerability to a simple Denial of Service (crash). This rough calculation is a comparison of affected USNs versus unaffected ones, but does not consider USNs with multiple vulnerabilities as higher weight. A more comprehensive analysis is needed.

Line Noise

Here's some extra stuff to consider.

Access Control

For those vulnerabilities left active, containment should be appropriate. The efforts to implement an SELinux policy for Ubuntu should continue; an appropriate policy to properly sandbox each start-up service and give sysadmin_t to root logins using login/su may be workably transparent to home users, since root would act as expected. Compromises could still do damage; but the SELinux policy would constrict that damage, in the same way that the DAC constricts a compromise in a normal user account. For example, apache/mod_php may be compromised and used to deface hosted user pages or a hosted web site; however, it cannot destroy anything in /usr or /lib or /bin or /sbin, and so cannot deploy a rootkit.

Within the constrictions, compromises may still be disasterous. This depends highly on the implementation and the policy. If the implementation requires the compromised service to interact with a database of medical data or credit card info, a serious leak or destruction of Confidential Information could occur. A worst case scenario would be access through a process with write access to medical data, which could be a life-threatening compromise. Still, a proper MAC policy may be able to protect such data when other countermeasures can not, such as when a neighboring process in the same account but with a different job is compromised, yet has no access to that particular set of data.

The sudo program is a special case; compromise of a no-password sudo user or an account which has sudo caching the password would be hazardous, and so the security implications of allowing sudo to get sysadmin_t at all should be examined. Users can always sudo bash and then activate sysadmin_t.

The implementation of an SELinux policy is something that needs serious consideration. When installing foreign programs, there may be no policy for them; in such a case, they may be unusable by anyone. Thus, SELinux should be an option, and an easy to disable one from a documented security administrator account, or from root on a non-SELinux kernel. A boot option with "enforcing=0" or "selinux=0" should disable it as well; although including such an option should be optional.

Boot Loader Control

Grub can handle md5 passwords. The option to set a password to prevent booting such entries and to prevent command line editing in grub would be good as well. If memory serves, a grub entry will halt at a "lock" command and demand a password to continue. Thus:

The above will disable the 'e' (edit entry) and 'o' (open new entry) commands in grub, forcing a user to use one of the existing entries. It will also prevent the user from booting with SELinux in softmode or disabled. A user would need to use the 'p' command and then enter the proper password to enable these features.