The ways of viruses in Linux

How Safe?


Some say an attack is looming, and others say we don't have to worry. What's the real story on viruses in Linux?

By Tomasz Kojm

Linux may not be as vulnerable as Windows, but if you think Linux viruses don't exist, you'd better think again. Virus writers have any number of possibilities for passing viruses into Linux, although the damage will be limited if you're careful and follow a few simple rules. In this article, I'll describe some examples of how Linux viruses work, and I'll give you some tips for keeping your system safe.

A Theoretical Linux Virus

Most Linux distributions come with gzexe, a small utility that compresses executable files and automatically uncompresses them when they're started. For example, you can copy /bin/date to /tmp and run gzexe /tmp/date to compress the executable file. The size of /bin/date and /tmp/date should differ, and the latter should be noticeably smaller. Now try to run both files. Do you notice any difference?

Every executable compressed with gzexe includes a special stub at the beginning of the file. When you open /tmp/date with your favorite editor, you will notice that the stub is just a plain shell script. Below the stub, there is binary data with the compressed executable. The shell code is responsible for decompressing the data into a temporary file and executing it. The whole process is transparent to the end user, and on fast computers, the delay in running compressed files is marginal.

Now think about a modified stub that does the following things before decompressing and running the original code:

This stub fits Wikipedia's definition of a virus as "a self-replicating program that spreads by inserting copies of itself into other executable code or documents"[1]. Let's call it Linux.Gzipper.

As this example shows, it is not a big challenge to write a simple Linux virus. It shouldn't be a surprise that virus writers can also use more sophisticated methods. The ELF (Executable and Linking) format of Linux executable files is very similar to the PE (Portable Executable) format used on Microsoft Windows and provides almost the same functionality. That means, virus writers can use many advanced infection techniques of the executable files they developed on Windows during the last decade. Of course, a number of ELF-infecting viruses already exist. In fact, some viruses can even infect both PE and ELF files. However, even the most advanced Linux viruses will face the same problem that our simple Gzipper faces: it's not that easy to damage a Linux system.

Native Anti-virus Protection

Virus writers exploit the fact that most users of commercial operating systems are accustomed to working at a highly privileged level that allows direct manipulation of critical resources for the system.

In Linux, and UNIX in general, it is a fundamental principle that one should only use the root account for administrative actions and never for regular work. As long as this rule is obeyed, most viruses can't do any harm globally because the mechanism of file permissions protects the system and the individual users' files. Of course, a virus can try to exploit security bugs in a target system to escalate privileges, but then, unpatched systems are open to other kinds of attacks, not just viruses.

Our theoretical Gzipper searches $PATH for writable executable files it could infect. When Gzipper is executed by an unprivileged user, it will only be able to infect executables owned or writable by this user, and in most cases, it will fail to spread out of the user's environment. Unfortunately, there are some "user friendly" Linux distributions that promote the bad model of a highly privileged single user, which opens a wide gate for virus attacks and allows the virus to infect core parts of the operating system. Such distributions can be called "virus friendly" as well as "user friendly."

The Many Faces of Linux

Another thing that makes it hard for viruses to spread is the number of Linux distributions and supported architectures, and the many technical differences between them. Of course, a binary virus compiled for the x86 architecture will not run on SPARC and vice versa. Even "portable" viruses written in script languages like Perl or shell may fail to run if they depend on elements that are not available on the victim's system.

Spreading Problems

Plain viruses, in contrast to worms, have no mechanism to replicate between computer systems. They can only spread along with the host file, contaminating other files in the process. These days, most Linux users and sysadmins only install software from their distributions or from official sources that are considered reliable. Additionally, official packages are usually digitally signed and can be verified before installation.

Unfortunately, even the best mechanisms cannot prevent human error.

In September 2005, the official Korean versions of Mozilla Suite 1.7.6 and Thunderbird 1.0.2 for Linux were found to be infected with the Linux.RST.B virus. The incident was very serious because the web browser is most often installed globally from the root account to make it available to all users on a system. Execution of the infected suite from a privileged account could allow the virus to easily infect system files. The Mozilla Foundation published a security advisory, telling Korean users who installed affected products to scan their systems with an anti-virus scanner[2].

Such incidents are still very marginal, but it's likely they will intensify in the future when more and more software becomes available in binary form from third party sites.

The Real Stuff

Computer viruses very often carry a payload, which is a special action they take after spreading. The payload of the Linux.Gzipper virus was to compress target files before infection. While in some cases even such potentially innocent payloads may cause a serious system malfunction, most of the real world viruses are not as nice as Gzipper.

The RST virus that infected the Mozilla Suite is one of the few Linux viruses seen in the wild and probably the most effective one. The first version of this virus was discovered in late 2001. The name stands for "Remote Shell Trojan." RST will try to infect executable files in the current directory, and if it has enough privileges, it will also infect the system files in /bin.

Listing 1 shows a directory with a number of clean files and one file infected with the virus. Running date.infected as an unprivileged user results in infection of executable files in the current directory (Listing 2). Additionally, the virus activates its payload and starts a backdoor server listening on the UDP socket (Listing 3). Now, an attacker with knowledge of a special protocol can control the backdoor and spawn a remote shell on the infected system.

Listing 1: Start with an Infected File
01 testuser@testsystem:~/testfiles$ ls -l
02 total 727
03 -rwxr-xr-x  1 testuser testuser  49084 Sep  4 03:32 cp
04 -rw-r--r--  1 testuser testuser    651 Jul 28  2004 crontab
05 -rwxr-xr-x  1 testuser testuser  88038 Nov  6 17:51 date.infected
06 -rw-r--r--  1 testuser testuser   1489 Feb 10  2004 fam.conf
07 -rw-r--r--  1 testuser testuser    292 Jun 18 02:05 hosts
08 -rwxr-xr-x  1 testuser testuser  71996 Sep  4 03:32 ls
09 -rw-r--r--  1 testuser testuser   1426 Nov  6 01:44 passwd
10 testuser@testsystem:~/testfiles$ clamscan --no-summary
11 /home/testuser/testfiles/cp: OK
12 /home/testuser/testfiles/ls: OK
13 /home/testuser/testfiles/crontab: OK
14 /home/testuser/testfiles/hosts: OK
15 /home/testuser/testfiles/fam.conf: OK
16 /home/testuser/testfiles/date.infected: Linux.Rst.A FOUND
17 /home/testuser/testfiles/passwd: OK
Listing 2: Passing the Infection
01 testuser@testsystem:~/testfiles$ ./date.infected
02 Sun Nov  6 18:02:46 CET 2005
03 testuser@testsystem:~/testfiles$ ls -l
04 total 1010
05 -rwxr-xr-x  1 testuser testuser  97890 Nov  6 18:02 cp
06 -rw-r--r--  1 testuser testuser    651 Jul 28  2004 crontab
07 -rwxr-xr-x  1 testuser testuser  88038 Nov  6 17:51 date.infected
08 -rw-r--r--  1 testuser testuser   1489 Feb 10  2004 fam.conf
09 -rw-r--r--  1 testuser testuser    292 Jun 18 02:05 hosts
10 -rwxr-xr-x  1 testuser testuser 120802 Nov  6 18:02 ls
11 -rw-r--r--  1 testuser testuser   1426 Nov  6 01:44 passwd
12 testuser@testsystem:~/testfiles$ clamscan --no-summary
13 /home/testuser/testfiles/cp: Linux.Rst.A FOUND
14 /home/testuser/testfiles/ls: Linux.Rst.A FOUND
15 /home/testuser/testfiles/crontab: OK
16 /home/testuser/testfiles/hosts: OK
17 /home/testuser/testfiles/fam.conf: OK
18 /home/testuser/testfiles/date.infected: Linux.Rst.A FOUND
19 /home/testuser/testfiles/passwd: OK
Listing 3: Backdoor is Born
01 testuser@testsystem:~/testfiles$ ps aux
02 USER       PID %CPU %MEM    VSZ   RSS TTY    STAT START   TIME COMMAND
03 [...]
04 testuser 28000  0.0  0.1   2116   876 ?      S    18:02   0:00 ./date.infected
05 [...]
06 testuser@testsystem:~/testfiles$ netstat -upan
07 [...]
08 udp        0      0 0.0.0.0:5503            0.0.0.0:*                          28000/date.infected

There are not many Linux viruses, and most of them were not as successful as RST. However, some of the viruses that do exist implement very interesting infection techniques. Linux.Svat is an example of such a virus. Instead of direct infection, it attempts to modify the operating system to create infected files. Listing 4 shows the compilation process of a standard "Hello, World" program. Svat's idea is based on the design of the compiler. When GCC encounters an #include <file.h> macro, it first looks for the header file file.h in /usr/local/include and later in /usr/include, which is the directory where all important header files are installed. The stdio.h file is one of the most used header files.

Listing 4: Compiling Hello, World
01 testuser@testsystem:~/hello$ cat hello.c
02 #include <stdio.h>
03
04 int main(int argc, char **argv)
05 {
06     printf("Hello world!\n");
07     return 0;
08 }
09 testuser@testsystem:~/hello$ gcc hello.c -o hello1
10 testuser@testsystem:~/hello$ ./hello1
11 Hello world!
12 testuser@testsystem:~/hello$ ls -l
13 total 12
14 -rw-r--r--  1 testuser testuser  100 Nov  6 18:46 hello.c
15 -rwxr-xr-x  1 testuser testuser 7340 Nov  6 18:50 hello1

As shown in Listing 5, when the Linux.Svat infected file is run by root, it installs a new header file in /usr/local/include. The new stdio.h includes the original one and additionally redefines the system function close(), which now calls the virus routine virfunc() before closing file descriptors. The routine contains bugs and will cause a segmentation fault if it has no write access to the /usr/local/include directory - the sloppy code limits the virus's chances to replicate.

The infection routine will be included in every new compiled file that uses stdio.h. Because our example hello.c file doesn't call the close() function, the virus code in hello2 will never be activated.

Listing 5: Svat as root
01 root@testsystem:~/Svat# clamscan --no-summary
02 /home/root/Svat/svat: Linux.Svat.C FOUND
03 root@testsystem:~/Svat# ls -l /usr/local/include
04 total 0
05 root@testsystem:~/Svat# ./svat
06 Example file infected with Svat.
07 root@testsystem:~/Svat# ls -l /usr/local/include
08 total 16
09 -rw-r--r--  1 root root      14614 Nov  6 19:10 stdio.h

"Safe Hex" in Linux

The rules for protecting Linux against viruses in are similar to the rules for other systems:

  1. Never use the root account for regular work.
  1. Avoid running binary files of unknown origin. Check them with rootkit and virus scanners first.
  1. Carefully check every file before running it from the root account.
  1. Keep your operating system up to date. Regularly install official security updates.
  1. Secure your environment by using hard-to-guess passwords and other protections.
  1. Track changes in the system using file system integrity tools.
THE AUTHOR

Tomasz Kojm is a computer scientist and the project leader of Clam AntiVirus project. ClamAV is an Open Source (GPL) anti-virus toolkit for Unix and Linux that is widely used as a server-side email virus scanner.