Medusa DS9 Security System
Authors: Marek Zelem, Milan Pikula and Martin Ockajak
E-mail (mailing list): email@example.com
Price: Free, released under GNU GPL
Reviewer: Robert Dobozy
Imagine a perfectly secured Linux box. With the newest patches, with Tripwire running every night, with log analyzer connected to another computer using a serial line which will call you by phone when something suspicious occurs—sounds good? Now imagine a new bug in Sendmail or ftpd, hundreds of relatively unknown users using many better- or worse-written setuid programs. Hmmm. Can you sleep well? You can say, “I have monitoring scripts, so I'll be informed by phone when somebody gains root access.” But you could just cry when some stupid vandal immediately executes rm -fr /. It's too late, especially if you are away and cannot sit in front of your computer and have a look at what happened. Or you can say, “I'm making a regular backup of my system, so I'll restore it.”
Making backups is a laudable activity, but will you restore every week, when every week somebody finds a new bug before you can fix it? Well, it seems you have to disconnect your computer from the Internet, shut it down and pray your data will be safe. No, don't panic! I have something for you. Its name is Medusa DS9. It's not a panacea, it's not perfect, but it is a very interesting piece of software.
In the Slovak language, “medusa” means “jellyfish”. Like jellyfish, Medusa can sting an enemy with its tentacles. In Greek mythology, Medusa was one of the three Gorgon monsters. Anybody who got a glimpse of her face became petrified. Medusa is a security system which can extend the overall security of your Linux system. Medusa consists of two parts. The first is a set of small patches to the Linux kernel, and the second is a user-space security dæmon (authorization server) called Constable.
You may ask, “Why do I need a security system such as Medusa?” The answer depends on many factors. If you have a machine at home, you'll probably not need it. If you have a well-known and frequently used Internet server, you may have use for it. Why? Because the UNIX security scheme seems to be insufficient nowadays. Yes, it's really simple (like the whole UNIX principle), but it has many limitations. Just to mention two of them: you have no system rights at all as an ordinary user, and all rights to the whole system as root. So, when somebody breaks in using any network dæmon, he can do anything he likes inside, e.g., graphics subsystem or low-level disk operations.
Another problem connected with this is that any program which wants to use a socket with a number less than 1024 must have root privileges. In those ancient days of 4.1aBSD systems, this seemed to be a good idea; now, when combined with the limitations of BSD TCP/IP stack and buffer overflow problems, our computers are living in hard times. While Medusa cannot change those things, it tries to eliminate their impact.
The basic idea behind Medusa is really simple. Before execution of certain operations, the kernel asks the authorization server (Constable) for confirmation. The authorization server then permits, forbids or changes the operation. The authorization server and kernel talk to each other through the special device: /dev/medusa. In this way, an administrator can create his own security model, which can complete or override the original UNIX model. I have told you the principle is simple; however, the actual implementation is a bit complicated. If you are interested in how, see Resources.
In 1995, the authors of Medusa were administrators of university machines. Since there were many users, someone often cracked a machine and used it as a base for nasty activities. Instead of taking part in a never-ending race with crackers and their exploits, they decided to achieve better security in a different way. In 1996, an ancient preliminary version, old Medusa, was born. After more development, a new generation called Medusa DS9 appeared in July 1998.
Constable is driven by its configuration file, which is usually /usr/local/etc/constable.conf. Here you can specify all the security settings you need. This configuration file can be considered a simple program. It has functions, conditions, events, blocks, etc., and is very similar to C. Constable is event-driven. When any event (syscall, VFS operation, signal) occurs, an appropriate action is executed. In the first example, we will protect one file against deletion. The Constable configuration is in Listing 1. Now, when someone tries to delete this file, Medusa returns the messages shown at the bottom of Listing 1. Hmmm; it seems as though the /tmp/delme file is undeletable, even by root.
Of course, it's not too useful to have one undeletable file. So, have a look at Listing 2, in which we will set a booby trap for every non-root user who tries to run the ifconfig program. This configuration is still not too useful, but does show how you can redirect execution of any program to something else. Thus, you can protect some sensitive programs against execution by some users. You can also redirect any file operation (access, unlink, read) to another file. For example, users who are coming to one machine from the network can have a different passwd and shadow file than local users.
In order to make Medusa really usable, we have to go deeper inside its functionality and configuration. Medusa uses the concept of virtual spaces. That means you can assign any process or file (inode) to one or more virtual spaces. Processes in one virtual space cannot see, change or influence processes or files in another virtual space. So, you can quite easily separate a few critical parts of your system from other parts. For example, you can have your Sendmail and FTP dæmons in virtual space number one and other system-critical files (such as the /etc directory, kernel and user home directories) in virtual space number two. Even if somebody exploits the FTP dæmon, he can do nothing, other than look at ftpd configuration files and the content of your public FTP directory if Medusa is properly configured.
In Listing 3, we will create two virtual spaces, one for the whole file system and another for the /tmp directory. Then we will protect the file /tmp/delme against deletion. When somebody tries to delete this file, he will be “fired” from the /tmp virtual space and will not be able to access any file in the /tmp directory or its subdirectories (even if they are mounted from another disk). This example can easily be modified to disallow this user from seeing the entire file system (by setting vss to 0). Keyword vss changes the virtual space a process can see. Virtual-space variables are usually modified by numbers in binary format (0b) which sets individual bits of those variables (10 binary is 2 in decimal). As you can see from the listing, you can make comments as in C programming using // or /* */ characters.
Except for virtual spaces, information on operations, which have to be confirmed by the security dæmon, can be stored for each process and file. Actions for a file can be access, creation or deletion; for a process, they can be fork, exec, signals and so on. For operations you don't care about, the control system works the same as without Medusa installed. For operations you want to control (such as unlink in the first example), the system asks the security dæmon. Now we will monitor and control execution of suid programs, as shown in Listing 4. We will disallow execution of suid programs (like su and ping) for users who connect using the TELNET protocol. It can be easily modified to control ssh connections too, so a locally logged-in user can su to root, for example.
You can now ask, “What if somebody does write and compile his own TELNET dæmon?” The answer is, of course, that this configuration of Constable will allow him to run suid programs. To be 100% sure, you can monitor system calls. It can be done by keyword to syscall. In the variable action, there is a syscall number stored (102 is socketcall), and in variables trace1 to trace5 there are parameters specified for this syscall. This configuration (see Listing 5) monitors every process that starts to use a network because the socketcall, syscall 102, must be used to do it, either with incoming or outgoing connections. The lpeek keyword reads data from the given address (trace2, the second socketcall parameter) and stores it into the variable $x. This example also shows the usage of user-defined variables. When a network connection is used, a function named doit will be called. If another syscall is called, the trace for this syscall is switched off. By default, the trace is switched on for all syscalls. To switch it off, you can use the trace_off keyword.
We are now coming to the most advanced feature of Medusa. You can force execution of any code in the context of any program. To simplify that process, there is a special library called Mlibc developed and included with Medusa. Mlibc (which stands for Medusa or Mini libc) is a small library, providing declaration of many standard functions, structures, macros and constants. When you link your “force” code with Mlibc, you'll get a program which can be executed inside a controlled process, as if it were compiled as an integral part of it. In Listings 6 and 7, we forced execution of the exit function when any program tried to delete our well-known /tmp/delme file. The principle is simple; first, we will compile the “force” code (exitme.c) using
gcc -O2 -c -o exitme.o exitme.c
Then we will link it with Mlibc:
ld -r -o exitme exitme.o mlibc.oAfter that, we will force execution of this code in the Constable configuration file in the event of unlinking of the /tmp/delme file.
Remember, don't use these to create your own impregnable Linux castle. They are truly just examples.
Among other nice features, Medusa knows and supports POSIX capabilities, so you can monitor and alter capabilities according to your needs.