Go to the first, previous, next, last section, table of contents.


Security

One of the design goals of MUSES is security. It is usually extremely difficult to prove the absence of bugs that a cracker might exploit: in order to be fully secure, a server should be running on a computer that is disconnected from any input source, welded shut inside a safe, and possibly switched off. Nevertheless, with proper design and implementation, it is possible to build a useful server that keeps the chances of intrusion low. The first half of this chapter describes how MUSES can improve the security of your server; the second half deals with the non-MUSES part of the server code.

The main security advantage of MUSES is that it centralizes network access. Only a few lines of code read data directly from the outside: the security-critical sections of the code are small and can be audited in a reasonable time. A program that reads incoming data in many different places is much more likely to contain an exploitable bug.

When MUSES reads data from the network, it automatically protects you from buffer overruns: it reads at most an amount of data sufficient to fill the current Connection's buffer. When the buffer is full, the current ReceiveHandler is asked to dispatch at least part of its contents; if the handler does not manage to remove any data, MUSES closes the connection. Your ReceiveHandler is told how many bytes remain to be read in the buffer; of course, it must not exceed that limit...

Many servers are meant to receive client commands as plain text, one line at a time. If this is the case, RH_LineSplitter can prove quite useful: it automatically divides incoming text into lines, and calls your LineHandler once per line. An attacker sending an extremely long line will not gain any advantage: the input will be silently split in multiple lines not exceeding the buffer size.

While the author did his best to make MUSES secure, there is no warranty about how well he succeeded. Moreover, using MUSES does not protect you from bugs in other parts of the system. Therefore, when designing a multi-user server, you should be aware of security issues; a few suggestions are given below.

First of all, write clean code. Spend your time making sanity checks and refining your design, rather than trying to overoptimize some part of the server that does not actually represent a performance bottleneck. If speed is a concern, remember that a simple implementation of a better algorithm is often faster than an optimized version of a suboptimal algorithm.

Code defensively. Do not assume things will always go as expected: make sure your assumptions are fulfilled. This is true, in particular, for network connections: someone might be sending deliberately malformed data to your server, in order to gain unauthorized access.

Even if you take measures to reduce the possibility of errors, bugs are always ready to slip in your code. In order to catch them early, use all the tools you have at your disposal. First of all, pay attention to any compiler warnings and fix them. Then, if possible, use a debugging tool to catch run-time errors: by linking your code to some library, or instrumenting it in some other way, you can be warned of memory access errors such as reading/writing past the end of a vector.

Unless it's really, really, really necessary, do not run a server as root: neither directly, nor by making the server suid root. Most of the times, this is an unneeded security hazard. If you really need root access for some operations, consider moving them to an external, smaller, suid-root executable, to be invoked only for those tasks. Or make the server drop root privileges via setuid() as soon as it does not need them any longer.

While not being as critical as root, personal accounts are not optimal for running servers either. A server running as "you" has the same rights as you do: it can read your personal files, mail them to someone else, replace or delete them... Ideally, the machine hosting your server should not contain any data the server does not need to access; in practice, running the server from a separate account is already a major security improvement.

Are you the only person that will run the server? Perhaps you will not run it as root, but someone else might. Consider making your server check the effective uid at startup; make it quit with a security warning if it detects it is being run with root privileges.

You might also want to chroot() your server to a "sandbox", instead of letting it access the entire file system. This might reduce the damage in case the server is compromised. On some systems, chroot() requires root privileges; you should of course drop them as soon as possible after using them.

This list of items does not exhaust the subject of server security: it is meant only as a minimal introduction. When designing an internet server, you should be aware of the current state of the art in computer security. MUSES can help you in some areas, but most of the responsibility is still yours.


Go to the first, previous, next, last section, table of contents.