Skip to content

Why the attacks on Debian and Savannah were possible (and more will follow)

Thursday, 4 December 2003  |  Tjansen

In the last two weeks servers of Debian, Savannah and Gentoo have been compromised, as you probably noticed. And they won't be the last ones. Many people brag about the security of free software, but I have never seen a single technical reason why free server systems should be more secure. The only reason why there are fewer worms is that there's more fragmentation and the users are more experienced. It's easier for a worm to spread when 50% of the Internet's computer are binary compatible rather than only 0.1%. But when an attacker wants to attack a specific server, a Linux or OpenBSD server is not more secure than a Windows or MacOS server. This year there were exploits in the Linux kernel, Apache, OpenSSL, thttpd, MySQL, Samba, CVS, OpenLDAP, ProFTPd, Sendmail, PostgreSQL, Kerberos, rsync, CUPS, lsh and OpenSSH. Most of these exploits can be used by an attacker even without having an account on the server. In other words, you will hardly find a single server that has not been vulnerable for some time this year. Even worse, it's highly unlikely that those were the last exploits to be found, so you are still vulnerable after patching them. It's just a matter of time until an attacker finds the exploits.

So what can be done against it?

Right now the only strategy seems to patch the vulnerable package as soon as possible. This certainly improves security, but there is still a window for attackers in the time frame between the public discovery of the exploit and the time the system is actually patched. Even if all patches are applied immediately, they do not help when the exploit is only known to the attacker, like the Linux kernel root exploit used for the Debian hack.

The only way to solve it is to prevent the servers from having exploitable bugs. To achieve this you need to look at the root of most vulnerabilities: bad memory management and buffer overflows. While there are also some other types of bugs, the overwhelming majority of fatal vulnerabilities is caused by error-prone low-level memory management that is used in most free software - including all the packages mentioned above. They occur mostly in software written in C and, when you not making use of higher level tools, in C++. Higher level languages like Java, C# and most scripting languages make buffer overflows either impossible or very rare.

There are several approaches to make buffer overflows harder to exploit. Projects like PaX protect you from many overflow types, but not all. It has been tried to make the stack non-executable. Windows 2003 and OpenBSD are adding extra code that detects when the stack is overwritten. The problem is that there is a large number of ways to use a buffer overflow, and so far all protection mechanisms can be defeated. They can solve the problem for a short time, but as soon as one of them is in widespread use hackers will certainly find a way to circumvent it.

Another solution could be running insecure C code in a virtual machine, like valgrind does. That would kill all performance advantages of C, but at least it would be secure.

Otherwise there is only one conclusion, as ridiculous it may sound: all the C software needs to be rewritten. Experience shows that even security-conscious projects like OpenSSL and OpenSSH are not able to produce C code without a yearly remote exploit. So if you want a program without exploits, you need to rewrite it. It is almost impossible to write secure, complex code in plain C. The only way to do this would be to refrain from using pointers and arrays, and to use secured functions for all low level operations. C should be banned for everything but the most low-level tasks, and algorithms that are relatively straightforward and performance-critical. The risks of C++ are somewhat similar, with the important exception that C++ makes it very comfortable to avoid pointers and arrays. With the right core-library it is easy to write code that is as secure as Java, as long as you do not use the low-level operations that C++ inherited from C. And the problem is not limited to servers. Network clients are security critical, because they may connect to a compromised server. All applications that load files are critical, because the user may have acquired the files from an untrusted source (or someone sent the file using the identity from a trusted person). Today there's hardly any non-trivial application that can not be used to attack the system. And many of these applications will be written by inexperienced developers, or developers who do not think about security while writing the application.

Right now it seems like the only way to make free software truly secure is to (re-)write it in higher-level languages that make it easy to write secure code and difficult to write vulnerabilities.