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.