Many different types of programs may need to be secure programs (as the term is defined in this book). Some common types are:
Application programs used as viewers of remote data. Programs used as viewers (such as word processors or file format viewers) are often asked to view data sent remotely by an untrusted user (this request may be automatically invoked by a web browser). Clearly, the untrusted user’s input should not be allowed to cause the application to run arbitrary programs. It’s usually unwise to support initialization macros (run when the data is displayed); if you must, then you must create a secure sandbox (a complex and error-prone task that almost never succeeds, which is why you shouldn’t support macros in the first place). Be careful of issues such as buffer overflow, discussed in Chapter 6, which might allow an untrusted user to force the viewer to run an arbitrary program.
Application programs used by the administrator (root). Such programs shouldn’t trust information that can be controlled by non-administrators.
Local servers (also called daemons).
Network-accessible servers (sometimes called network daemons).
Web-based applications (including CGI scripts). These are a special case of network-accessible servers, but they’re so common they deserve their own category. Such programs are invoked indirectly via a web server, which filters out some attacks but nevertheless leaves many attacks that must be withstood.
Applets (i.e., programs downloaded to the client for automatic execution). This is something Java is especially famous for, though other languages (such as Python) support mobile code as well. There are several security viewpoints here; the implementer of the applet infrastructure on the client side has to make sure that the only operations allowed are “safe” ones, and the writer of an applet has to deal with the problem of hostile hosts (in other words, you can’t normally trust the client). There is some research attempting to deal with running applets on hostile hosts, but frankly I’m skeptical of the value of these approaches and this subject is exotic enough that I don’t cover it further here.
setuid/setgid programs. These programs are invoked by a local user and, when executed, are immediately granted the privileges of the program’s owner and/or owner’s group. In many ways these are the hardest programs to secure, because so many of their inputs are under the control of the untrusted user and some of those inputs are not obvious.
This book merges the issues of these different types of program into a single set. The disadvantage of this approach is that some of the issues identified here don’t apply to all types of programs. In particular, setuid/setgid programs have many surprising inputs and several of the guidelines here only apply to them. However, things are not so clear-cut, because a particular program may cut across these boundaries (e.g., a CGI script may be setuid or setgid, or be configured in a way that has the same effect), and some programs are divided into several executables each of which can be considered a different “type” of program. The advantage of considering all of these program types together is that we can consider all issues without trying to apply an inappropriate category to a program. As will be seen, many of the principles apply to all programs that need to be secured.
There is a slight bias in this book toward programs written in C, with some notes on other languages such as C++, Perl, PHP, Python, Ada95, and Java. This is because C is the most common language for implementing secure programs on Unix-like systems (other than CGI scripts, which tend to use languages such as Perl, PHP, or Python). Also, most other languages’ implementations call the C library. This is not to imply that C is somehow the “best” language for this purpose, and most of the principles described here apply regardless of the programming language used.