A secure program must minimize privileges to reduce the likelihood of a bug being converted into a security flaw. This article discusses how to minimize privileges by minimizing the privileged modules, the privileges granted, and the effective time of the privilege. The article discusses not only some traditional UNIX-like privilege mechanisms, but also newer mechanisms such as FreeBSD's Jail (), Linux security Module (Linux modules,lsm) framework, and security-enhanced Linux (SELinux).
March 3, 2003, Internet security Systems a warning about a serious vulnerability in Sendmail. All e-mail messages are transmitted through the Mail transfer agent, mail transfer Agent,mta, and Sendmail is the most popular MTA, so this warning affects many organizations around the world. The problem is that, in the usual configuration, an email message with a "from", "to" or "CC" domain is carefully set, allowing the sender to control any machine that is running Sendmail in full (root). More seriously, the general firewall will not be able to protect its internal machines from this attack.
The immediate cause of this vulnerability is that a security detection of Sendmail is flawed and a buffer overflow can occur. However, an important factor is that Sendmail is often installed as a single "Setuid root" program that has full control over the system that runs it. In this way, any flaw in the Sendmail can allow the attacker to directly control the entire system.
Is this design necessary? No, Wietse Venema's Postfix is a common MTA that you can match. Similar to Sendmail,postfix will do a lot of security checks, however, in order to minimize privileges, Postfix is designed as a set of modules. As a result, Postfix is generally considered to be a more secure program than Sendmail. This article discusses how to minimize privileges, and you can apply the same ideas to your programs.
The basics of minimizing privileges
The actual application of the program will be flawed. It's not what we want, but it does. Complex requirements, scheduling pressures, and changes in the environment make it less likely that practical, bug-free programs will be available. Even those programs that are formally proven to be correct through complex and precise techniques can also be flawed. Why? One reason is that validation must make many assumptions, and often these assumptions are not entirely correct. In any case, most programs are not rigorously tested for a variety of reasons. Moreover, even if there is no defect today (unlikely), changes in maintenance or changes in the environment may introduce defects. So, to deal with the actual problem, we have to somehow develop secure programs, even though we have bugs in our programs.
Despite these flaws, the most important way to secure programming is to minimize privileges. Privilege is only allowed to do things that not everyone can do. In a UNIX-like system, the privilege of having a "root" user, another user, or a member of a group is the most common type of privilege. Some systems allow you to grant the privilege of reading or writing specific files. However, in any case, minimize the privilege:
Grant privileges only to parts of the program that require privileges
Grant only the specific privileges that are absolutely necessary
Limit the validity of a privilege to an absolute minimum of time that can be valid
These are actually goals, not absolute. Your infrastructure, such as your operating system or virtual machines, may make it difficult to do this strictly, or it can be complicated to do so, and lead to more bugs when you try to do it strictly. However, the closer you are to these goals, the less likely it is that the defect will lead to security problems. Even if a flaw causes a security problem, the severity of the security problems it causes may be lower. Also, if you can make sure that only a small number of programs have specific privileges, you can use a lot of extra time to make sure that part is protected against attacks. This idea is not new; Saltzer and Schroeder's excellent 1975 paper discusses the principle of security, explicitly minimizing privileges as a principle (see resources). Some ideas are timeless, such as minimizing privileges.
The next sections will discuss these goals in turn, including how to implement them in UNIX-like systems. We will then discuss some of the special mechanisms available in FreeBSD and Linux, including the discussion of the NSA's security-enhanced Linux (SELinux).
Minimizing privileged Modules
As mentioned earlier, only some of the programs that require privileges are applied with privileges. This means that when you design your program, try to break the program into separate parts so that only small, independent parts require specific privileges.
If the different parts must be running at the same time, use the process (not the thread) in the UNIX-like system. Threads share their security privileges, and problematic threads may interfere with all other threads in the process. When writing a privileged part, it is being attacked as another program: one day it will be possible! Make sure that the privileged part is only doing as few things as possible; limited functionality means more difficult to exploit.
A common approach is to create extremely restrictive command line tools that have specific privileges, such as setuid or Setgid. The UNIX passwd command is an example of a command-line tool with specific privileges to modify a password (setuid root), but all it can do is modify the password. A variety of GUI tools can then require passwd to make actual changes. If possible, avoid creating setuid or Setgid programs as completely as possible, because it is difficult to ensure that you are actually protecting all input. However, sometimes you need to create a setuid/setgid program, so minimize and limit the program whenever you want.
There are a lot of other ways. For example, you can have a small "server" process with specific privileges, that server only allows specific requests, and only after confirming that the requester is allowed to make a request. Another common approach is to start a program with privileges, which then derive a second process that discards all privileges, and the process does most of the work.
Be careful how these modules communicate with each other. On many UNIX-like systems, command line values and environments can be seen by other users, so it's not a good way to send data confidentially between processes. The pipe is competent, but careful avoidance of deadlocks (a simple request/response protocol that can be refreshed at both ends) is possible.