Paranoid Penguin - An Introduction to Novell AppArmor
In my article “Security Features in SUSE 10” (LJ, April 2006), I described Novell AppArmor, a partial implementation of mandatory access controls (MACs) that is now part of SUSE Linux. Since that writing, Novell has released the source code of AppArmor under the GPL. It's entirely possible that in the near future, AppArmor will be ported to other Linux distributions that support Linux security modules.
This is great news. In my opinion, AppArmor represents a major step forward in making MAC technology a feasible option for system administrators who want strong security controls but don't have the time or patience to configure and maintain a complicated “trusted OS” such as SELinux.
This month, I introduce the concept of mandatory access controls, describe the difference between Novell AppArmor and NSA SELinux, and show you how to get started with AppArmor on your SUSE systems.
The easiest way to describe mandatory access controls is to contrast it with discretionary access controls (DACs). Most general-purpose operating systems use a DAC security model, in which the owner of a given system resource (file, directory and so forth) can set whatever access permissions on that resource they like. Stringent security controls, in general, are optional.
By contrast, a computer with MAC has a global security policy to which all users of the system are subject. A user who creates a file on a MAC system generally may not set access controls on that file that are weaker than the controls dictated by the system security policy.
Most DAC implementations have several major problems, emphatically including both Windows and Linux (except SELinux). First and most obvious is that, as with any scenario involving human beings, making any type of work optional all but ensures that work won't get done very often. It takes work to use careful security settings consistently, even in a DAC system.
Another problem with DAC is that DAC-based OSes tend to have a “winner take all” security model, in which the only way to get anything important done on the system is through the superuser account (root in Linux/UNIX, Administrator in Windows). Wholly compromising a system using such a security model is generally a simple matter of hijacking some process on that system that runs with root/Administrator privileges.
On a MAC-based system, however, the only thing the superuser account is used for is maintaining the global security policy. Day-to-day system administration is performed using accounts that lack the authority to change the global security policy. As a result, it's impossible to compromise the entire system by attacking any one process. (Attacks on the superuser account are still possible, however; for example, by booting the system into single-user mode from its physical console.)
If mandatory access controls are superior to DACs, why aren't they ubiquitous? Unfortunately, although MAC schemes have been available on various platforms over the years, they traditionally have been much more complicated to configure and maintain than DAC-based operating systems. Creating an effective global security policy requires detailed knowledge of the precise (intended) behavior of every application on the system. Furthermore, the more restrictive the security controls are on a given system, the less convenient that system becomes for its users to use.
AppArmor isn't the first mandatory access control scheme for Linux, nor is it the most comprehensive. It shares DNA, so to speak, with SELinux, a project of the US National Security Agency. (The shared DNA is the Linux Security Modules, which provide kernel support for MAC.)
SELinux is a bundle of kernel modules and user-space configuration tools that implement three different types of MAC:
Type enforcement (TE): associates a security “label” with every system object.
Role-based access controls (RBACs): define particular actions and contexts in which system objects may be involved.
Multi-level security (MLS): defines access controls against objects based on data classification (sensitivity).
In SELinux, all three types of access controls (TE, RBAC and MLS) are applied across the entire operating system. This requires major system applications to be SELinux-aware wherever possible, and it also requires extensive setup by a knowledgeable system administrator (that is, one who has carefully researched SELinux). On the one hand, SELinux is truly comprehensive. On the other hand, configuring it is a fairly major undertaking.
Novell AppArmor has a more modest objective: to restrict the behavior of selected applications in a very granular but targeted way. In focusing on applications (at the expense of roles and data classification), AppArmor is built on the assumption that the single biggest attack vector on most systems is application vulnerabilities. If the application's behavior is restricted, the behavior of any attacker who succeeds in exploiting some vulnerability in that application also will be restricted.
For example, suppose you're running a Web application that runs as user nobody and uses user input to update a local text file. On a typical system, if an attacker compromised that Web application, for example, by sending unexpected input, the attacker might succeed in gaining a remote shell with the privileges of nobody. If that Web application were protected by AppArmor, however, all the attacker would be able to do is alter that single text file. It wouldn't be possible for the attacker to spawn a remote shell (an unexpected action) or to read or write any other files.
Comprehensive? By no means. For non-AppArmor-protected applications, the usual (limited) user/group permissions still apply, no controls regarding data classification are provided, and normally, only a subset of applications on the system have AppArmor profiles.
For the most part, root is still root, and if you use root access in a sloppy or risky fashion, AppArmor generally won't protect you from yourself. But, if an AppArmor-protected application runs as root, and becomes compromised somehow, that application's access will be contained, root privileges notwithstanding, because those privileges are trumped by the AppArmor policy (which is enforced at the kernel level, courtesy of Linux security modules).
AppArmor is therefore only a partial implementation of mandatory access controls. But on networked systems, application security is arguably the single-most important area of concern, and that's what AppArmor zeros in on. What's more, AppArmor provides application security through an easy-to-use graphical user interface that is fully integrated with YaST. (GUI tools are now being developed for SELinux as well, but just how easy to use these are is open to debate.)
Still, I'm stopping well short of suggesting AppArmor is interchangeable with SELinux. If, for example, you run Linux in a multiuser environment (in which users have shell or database accounts) involving highly sensitive data, there really is no substitute for the comprehensive layers of access controls in SELinux.
Although AppArmor's open-source license hopefully will lead to ports on other Linux distributions, for the time being AppArmor is available only for SUSE Linux and SUSE Linux Enterprise. The rest of this article, therefore, is necessarily specific to SUSE. I'm scratching only the surface here. For detailed information on how to configure and use AppArmor, see the AppArmor Admin Guide Using Yast, whose path is /usr/share/doc/packages/subdomain-docs/ug_apparmor.pdf, provided you've installed SUSE's subdomain-docs package.
Note: prior to being acquired by Novell, AppArmor previously was called Immunix SubDomain. Many of AppArmor's filenames and package names still include the word subdomain.
AppArmor has its own YaST module, called Novell AppArmor (Figure 1). As you can see, most of the applets in this module deal with creating and managing AppArmor Profiles. Each application protected (confined) by AppArmor must have its own AppArmor profile. Profiles can be created manually or by using the Add Profile and Update Profile Wizards or with the Manually Add Profile applet.
The AppArmor control panel is used to enable and disable AppArmor and to enable, configure and disable AppArmor security event notification. Important note: any time you enable AppArmor manually, you must restart every AppArmor-protected application (simply rebooting is your safest bet). An application must start while AppArmor is already running in order to benefit from its protection. Obviously, if AppArmor is enabled at boot time, you don't need to worry about this.
Two types of applications are particularly important to protect: programs that run setuid root (that is, run with root's privileges) and network applications. AppArmor comes preconfigured with profiles for a variety of setuid-root programs and network applications, including Apache, ping, Firefox, Opera, Evolution, sshd, ld, Postfix, Squid and Ethereal.
Two Handy Commands
You can identify all the commands and dæmons on your system that are both owned by root and have their setuid bit set (that is, that run with a user ID of root no matter who actually executes them), with a single command:
find / -user root -perm -4000 -print
As with any other find / command, this takes a few minutes to complete, but the output hopefully will be a short list. In the Internet-connected era, it's very bad form indeed to set the setuid bit on any root-owned executable unless it's absolutely necessary, so modern versions of Linux distributions tend to be very sensible in this regard. Still, you may be surprised by what you find.
One more handy command, this one peculiar to AppArmor, is unconfined. When run without arguments from a command prompt, this command lists running network dæmons that are not protected by AppArmor. You must be root, and AppArmor must be enabled, for the unconfined command to work.
Figure 2 shows the ping default profiles. As you can see, it consists of #include statements that reference the contents of other profiles, access controls on POSIX capabilities (setuid, kill, sys_boot and so forth) and file access controls.
There's actually a fourth element that Web server profiles may contain—hat definitions. Figure 3 shows part of the profile for httpd2 (Apache 2). The entries at the top of the profile that begin [+] are hats. A hat is simply an embedded profile, a sub-profile, if you will. Only profiles for hat-aware applications can have hats, and even at that, you must have SUSE's libimmunix and mod-change-hat packages installed for hats to work.
The most common use of hats is for Web applications that are run without actually being part of httpd dæmons. Figure 4 shows the contents of just such a hat, corresponding to a guestbook application on my Web server. The index.php script referenced in Figure 4 mainly needs read access to some files, but it also needs to both read and write to the guestbook file itself (book.gb) and also Apache's access log (access_log).
If this seems confusing, don't worry. It's seldom necessary to create profiles (let alone hats) manually. On many systems, you won't need to create new profiles at all—periodically running the AppArmor Update Profile Wizard when things don't work as expected may suffice. This wizard scans /var/log/messages for AppArmor-generated error messages and allows you to update the corresponding AppArmor profiles accordingly (either to allow or continue to disallow the event that triggered each error). Where appropriate/applicable, Update Profile Wizard even will create new hats, again assuming you've installed the libimmunix and mod-change-hat packages.
If you need to create a new profile from scratch, there are several ways to do so, all explained in detail in the aforementioned Admin Guide Using YaST and also in the AppArmor Advanced User's Guide (/usr/share/doc/packages/subdomain-docs/adv-ug-apparmor.pdf). Here, however, is the easiest method:
Run the Add Profile Wizard, being sure to specify the full path to the program you want to protect when prompted for the application name. You will be prompted to run the program, during which time AppArmor runs in “learn” mode, and builds a profile by observing the application's behavior.
After the Add Profile Wizard closes, restart your application (if a dæmon) and test it as thoroughly as possible. If everything works properly, you're done.
If anything failed in the previous step, run the Update Profile Wizard. Based on your answers to the Wizard's prompts, the AppArmor profile you just created (plus any other applicable profiles) will be updated.
Repeat steps two and three until the application works the way it did before you created its AppArmor profile. This may take more than two iterations.
That's basically it! The excellent documents in /usr/share/doc/packages/subdomain-docs explain not only the above procedure, but also how to use the Add Profile Manually applet and even how to create profiles from scratch using your text editor of choice.
Before I close this month's column, I leave you with a couple observations based on my experiences tinkering with AppArmor over the past couple of months. First, I must stress the importance of having a healthy local logging facility. As you can see, AppArmor relies heavily on /var/log/messages not only for providing you with a good audit trail, but also for providing its own wizards with crucial configuration intelligence. Therefore, if you have a customized system logger, make sure that there's at least a symbolic link from /var/log/messages to wherever your subdomain messages end up.
For example, on my chrooted syslog-ng installation, my subdomain messages are written to /var/syslog-ng/var/log/messages. Before AppArmor would work properly on this system, I had to create a symbolic link from /var/log/messages to this location. I also had to edit /etc/logrotate.d/syslog so that the “real” messages file would be rotated when too large or old; otherwise, the symbolic link was destroyed by my logrotate cron job. (Obviously, I should have updated logrotate.d/syslog already, back when I configured syslog-ng—by the time I got around to this, /var/syslog-ng/var/log/messages had grown to an embarrassing and unwieldy size.)
Also, I should point out that, just like all of YaST's modules, you don't need to be running the X Window System to run the Novell AppArmor YaST applets. You shouldn't be running X on Internet-connected servers, both because it's almost never necessary and because X has a very rich history of so-called local privilege escalation vulnerabilities. It may seem tempting to ignore such vulnerabilities if you're worried about non-local attackers, but “local” is a usually a misnomer. If attackers gain shell access via, for example, a buffer-overflow attack against some network dæmon, they often can exploit so-called local privilege escalation vulnerabilities to promote themselves to root.
I hope you'll forgive me, therefore, for using attractive screenshots of the X version of YaST in this article—I assure you that the content and functionality is identical in the text-only versions of these applets.
Finally, a tip—in the course of repeatedly running the Update Profile Wizard to make my guestbook PHP script work, AppArmor for some reason forgot I'd dealt with two particular events in /var/log/messages and prompted me over and over about these two events. The problem went away when I manually deleted the corresponding lines in /var/log/messages, and I haven't experienced that particular anomaly since. The problem may have had more to do with my weird syslog-ng behavior than with anything in AppArmor, but I mention it in case you experience anything similar. AppArmor's log messages always contain the string SubDomain.
Mick Bauer (darth.elmo@wiremonkeys.org) is Network Security Architect for one of the US's largest banks. He is the author of the O'Reilly book Linux Server Security, 2nd edition (formerly called Building Secure Servers With Linux), an occasional presenter at information security conferences and composer of the “Network Engineering Polka”.