Linux and Security: Mission Impossible? -

Linux and Security: Mission Impossible?

The use of Linux in systems requiring high levels of security has been a frequent topic of controversy. Supporters have claimed that Linux's open source approach improves security due to exposure to an enormous, worldwide community of developers and users.

Detractors have maintained that the complexity and architecture of Linux make it unsuitable for high criticality applications. With a lifetime of over 15 years, there are now plenty of public statistics with which to analyze Linux security.

Linux in Government Security Systems
Some powerful organizations have sided with the supporters. Linux is the trusted operating system in HP's NetTop [1], the IBM Trusted Thin Client [2], and the General Dynamics Trusted Virtual Environment (TVE) – a product of NSA's High Assurance Platform (HAP) program [3].

All of these products are designed to consolidate computers used by government personnel to access classified and unclassified networks. The specialized computer provides multiple “virtual” desktops and is trusted to protect sensitive information.

In order to prepare it better it for the task of becoming the “touching point” between physically distinct networks, Linux was enhanced by the NSA's National Information Assurance Research Laboratory with additional security controls, known as Security-Enhanced Linux (SELinux)[4]. The SELinux extensions have been adopted by the Linux community and these systems.

Along with their investment in Linux, these military suppliers have made forceful claims about the trustworthiness of these products. According to General Dynamics, the TVE provides “high robustness” and a “quantum leap in the way military and government security levels are accessed.” [5]

It is interesting to note, however, that the NSA's developers were careful not to claim suitability for high criticality systems, stating that SELinux is “very unlikely by itself to meet any interesting definition of secure system.”[6] Furthermore, the SELinux effort has included “no work focused upon increasing the assurance of Linux itself.” [7]

Vulnerabilities in Linux
While many discussions about the security of Linux have been clouded by hyperbole and commercial agendas, a number of independent resources, many published by the Linux community, are painting a more complete, unbiased picture about Linux security.

In the first release of Linux 2.6 (2.6.0), the Linux kernel consisted of more than 5 million lines of code.10 In 2.6.30, that number has grown to over 11 million lines.[8]

In addition, Linux development follows general commercial practices, not compliant with any stringent safety or security standard. While Linux's open source exposure has enabled it to achieve a low defect rate relative to most commercial software, the size of the kernel assures a large dose of flaws. In 2004, an automated static analysis tool discovered almost 1,000 bugs in the Linux kernel.[9]

NIST and the DHS National Security Cyber Division publish a catalog, the National Vulnerability Database (NVD), of security defects in commercial software products. As of August 16, 2009, a search on Linux yields 1288 entries, 457 of which are considered “High Severity.”[10]

134 high severity vulnerabilities are associated with the Linux kernel. The NVD reports 91, 77, and 87 Linux kernel vulnerabilities for each of the years 2006, 2007, and 2008, respectively[11].

It is statistically assured that a similar number will be found in future years, implying that numerous vulnerabilities exist in today's shipping version. These numbers of course do not account for unreported defects.

Some critical software components gain assurance over time. This occurs when the software is relatively simple, changes very little (except perhaps for bug fixes), and is deployed for a long period of time in a variety of environments.

The Linux kernel, however, undergoes continuous modification, including in the field (e.g. over-the-air patching). The latest major version of Linux, 2.6, has changed more rapidly than previous versions and regularly undergoes major modifications to the “stable branch” of the kernel.[12]

As an example, Linux developer Greg Kroah-Hartman reported that the 2.6.24 kernel saw approximately 5,000 lines of code added per day during a three month period, prompting his lament, “It's fricken scarily amazing that things are still working at all”[13]

The rate of change has been accelerating. Kroah-Hartman reported that over 12,000 lines of code were added per day on average during the 2.6.30 development cycle[14]. Since 2005, the Linux kernel has been modified by over 5000 different people [15], at a rate which now exceeds 6 changes per hour.[16]

Another good example was provided by Jim Ready, founder of Linux vendor Montavista, who discussed NVD defect CVE-2006-1528 which was patched in Linux version 2.6.13. In order to get the bug fix in a supported release, a user running 2.6.10 would have been forced to take in 846,233 new lines of code (representing the changes between 2.6.10 and 2.6.13) [17].

On August 10, 2009, a memory leak in the SELinux security extensions was published in the NVD.[18] A few days later, five more vulnerabilities were published.

One of these, CVE-2009-2692, reports a severe kernel defect that can be trivially exploited by a user to take complete control of the system.[19] This vulnerability exists in every Linux operating system deployed over the past eight years.

CVE-2009-2692 – An Illustration of a Total Loss in Security
The following is a detailed description of the vulnerability. Readers who want to skip the details should proceed to the next section. Security researchers Tavis Ormandy and Julien Tinnes discovered a set of NULL function pointer dereferences in the Linux kernel.[20]

The function pointers come from Linux networking code. Linux uses a structure, called proto_ops, to hold a set of prototypical operations associated with network sockets. The implementations of each operation vary across socket families (e.g. AppleTalk, Bluetooth, Infrared, Stream Control Transmission Protocol for IPv6).

The function pointers associated with these operations are not consistently initialized nor validated at their kernel call sites. When a socket service call is executed by an application, the Linux kernel determines the proper proto_ops structure to use based on the socket type. The kernel executes the function pointer for the requested operation within this structure.

The following Linux kernel example shows a proto_ops pointer (the splice_read operation) that is NULL checked at the call site:

And here is an example where the same check is missing:

Another method used in Linux to avoid proto-ops NULL dereferences is to pre-initialize the pointer to a stub function. If the sendpage pointer in the above example is initialized to the Linux stub sock_no_sendpage, then the unprotected call above will execute the stub function and avoid the NULL deference. Many socket family proto-ops are initialized in this manner, for example, the one used for Infrared datagrams:

However, other instances are not properly initialized, for example the following Bluetooth Network Encapsulation Protocol (BNEP) proto-ops:

Thus, an attacker simply needs to invoke a sendpage operation on an open BNEP socket to force a NULL dereference.

Kernel NULL execution can have a variety of effects. For example, execution of the 0 page could cause the system to completely crash (a simple but total denial of service attack).

However, several unrelated flaws in the Linux kernel allow an attacker to inject arbitrary code into the kernel at address 0. In addition, as reported in NVD candidate CVE-2009-2695 and detailed by Red Hat[21], the SELinux extensions exacerbate the address 0 execution vulnerability.

The combination of NULL pointer and kernel code injection vulnerabilities enable an attacker to trivially take over complete control of the system by forcing the kernel to execute the attacker's code.

Several exploits of the Proto-ops flaw were immediately published ” simple programs that a Linux user could run to demonstrate total security failure[22]. The general flow of the exploit is as follows:

Linux has a “feature” which makes this exploit a bit easier: for improved system call performance, Linux keeps the user application's memory mappings enabled during system call servicing.

This precludes the need to perform manual address translation on service call parameters located in application memory. Thus, the application's memory page at address 0 becomes the kernel's page at address 0, and Attacker_code is automatically mapped and executable by the kernel.

While Linux fulfills the vision of its creators as a high performance general purpose operating system, it was never designed for the level of robustness demanded for high criticality systems.

This is no different from other general purpose operating systems. Imagine using Windows to run the flight control system in a modern airliner – an act that could give new meaning to the “blue screen of death”.

Solaris is another general purpose operating system that has been deployed for network consolidation (it is used in the military's DoDIIS Trusted Workstation). CVE-2007-0882 (high severity) describes an embarrassing defect in Solaris 10 and 11 which enables any attacker to login remotely, completely bypassing authentication.[24]

So, to be clear, while the statistics in this article are mostly aimed at Linux, the conclusions are common to large scale, general purpose software systems. I'm personally a big fan of Linux, using it daily on my desktop. But the facts are simply incontrovertible: right now, as things currently stand, using Linux in high criticality systems is mission impossible.

Online References
[7] Ibid.
[9] Greg Kroah-Hartman, Jonathan Corbet, Amanda McPherson; “Linuxkernel Development“; p. 3;
[11] term: Linux kernel )
[12] term: Linux kernel, usingvarious start/end dates )
[15] Kroah-Hartman, et al, , p. 6
[16] Ibid, p. 1
[17] Ibid, p. 4

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.