Introducing AppArmor: How to work with the security module by examples

AppArmor Introducing

AppArmor is an LSM based on the MAC model that confines applications to a limited set of resources. AppArmor uses an ACM based on security profiles that have been loaded into the kernel. Each profile contains a collection of rules for accessing various system resources. AppArmor can be configured to either enforce access control or just complain about access control violations.

AppArmor proactively protects applications and operating system resources from internal and external threats, including zero-day attacks, by preventing both known and unknown vulnerabilities from being exploited.

AppArmor has been built into the mainline Linux kernel since version 2.6.36 and is currently shipped with Ubuntu, Debian, OpenSUSE, and similar distributions.

In the following sections we'll use an Ubuntu 20.04 environment to showcase a few practical examples with AppArmor. Most of the related command-line utilities will work the same on any platform with AppArmor installed.

Working with AppArmor

AppArmor command-line utilities usually require superuser privileges.

The following command checks the current status of AppArmor:

sudo aa-status

Here's an excerpt from the command's output:

Getting the status of AppArmor

Figure 1 – Getting the status of AppArmor

The aa-status (or apparmor_status) command provides a full list of the currently loaded AppArmor profiles (not shown in the preceding excerpt). We'll examine AppArmor profiles next.

Introducing AppArmor profiles

With AppArmor, processes are confined (or restricted) by profiles. AppArmor profiles are loaded upon system start and run either in enforce mode or complain mode. We'll explain these modes next.

Enforce mode

AppArmor prevents applications running in enforce mode from performing restricted actions. Access violations are signaled with log entries in syslog. Ubuntu, by default, loads the application profiles in enforce mode.

Complain mode

Applications running in complain mode can take restricted actions, while AppArmor creates a log entry for the related violation. complain mode is ideal for testing AppArmor profiles. Potential errors or access violations can be caught and fixed before switching the profiles to enforce mode.

With these introductory notes in mind, let's create a simple application with an AppArmor profile.

Creating a profile

In this section, we'll create a simple application guarded by AppArmor. We hope this exercise will help you get a sensible idea of the inner workings of AppArmor. Let's name this application appackt. We'll make it a simple script that creates a file, writes to it, and then deletes the file. The goal is to have AppArmor prevent our app from accessing any other paths in the local system. To try and make some sense of this, think of it as trivial log recycling.

Here's the appackt script, and please pardon the thrifty implementation:

The appackt script Figure 2 – The appackt script

We are assuming that the log directory already exists at the same location as the script:

mkdir ./log

Let's make the script executable and run it:

chmod a+x appackt

./appackt

The output is as follows:

 The output of the appackt script

Figure 3 – The output of the appackt script

Now, let's work on guarding and enforcing our script with AppArmor. Before we start, we need to install the apparmor-utils package – the AppArmor toolset:

sudo apt-get install -y apparmor-utils

We'll use a couple of tools to help create the profile:

  • aa-genprof: Generates an AppArmor security profile
  • aa-logprof: Updates an AppArmor security profile

We use aa-genprof to monitor our application at runtime and have AppArmor learn about it. In the process, we'll be prompted to acknowledge and choose the behavior that's required in specific circumstances.

Once the profile has been created, we'll use the aa-logprof utility to make further adjustments while testing in complain mode, should any violations occur.

Let's start with aa-genprof. We need two terminals: one for the aa-genprof monitoring session (in terminal 1) and the other for running our script (in terminal 2).

We will start with terminal 1 and run the following command:

sudo aa-genprof ./appackt

There is a first prompt waiting for us. Next, while the prompt in terminal 1 is waiting, we will switch to terminal 2 and run the following command:

./appackt

Now, we must go back to terminal 1 and answer the prompts sent by aa-genprof, as follows:

Prompt 1 – Waiting to scan

This prompt asks to scan the system log for AppArmor events in order to detect possible complaints (violations).

Answer: S (Scan):

Prompt 1 – Waiting to scan with aa-genprof

Figure 4 – Prompt 1 – Waiting to scan with aa-genprof

Let's look at the next prompt.

Prompt 2 – Execute permissions for /usr/bin/bash

This prompt requests execute permissions for the process (/usr/bin/bash) running our app.

Answer: I (Inherit):

Prompt 2 – Execute permissions for /usr/bin/bash 

Figure 5 – Prompt 2 – Execute permissions for /usr/bin/bash

Let's look at the next prompt.

Prompt 3 – Read/write permissions to /dev/tty

This prompt requests read/write permissions for the app to control the terminal (/dev/tty).

Answer: A (Allow):

 Prompt 3 – Read/write permissions to /dev/tty

Figure 6 – Prompt 3 – Read/write permissions to /dev/tty

Now, let's look at the final prompt.

Prompt 4 – save changes

The prompt is asking to save or review the changes.

Answer: S (Save):

Prompt 4 – Save changes 

Figure 7 – Prompt 4 – Save changes

At this point, we have finished scanning with aa-genprof, and we can answer with F (Finish) to the last prompt. Our app (appackt) is now enforced by AppArmor in complain mode (by default). If we try to run our script, we'll get the following output:

 The first run of appackt with AppArmor confined

 Figure 8 – The first run of appackt with AppArmor confined

As the output suggests, things are not quite right yet. This is where the aa-logprof tool comes to the rescue. For the rest of the steps, we only need one terminal window.

Let's run the aa-logprof command to further tune our appackt security profile:

sudo aa-logprof

We'll get several prompts again, similar to the previous ones, asking for further permissions needed by our script, namely for the touch, cat, and rm commands. The prompts alternate between Inherit and Allow answers, where appropriate. We won't go into the details here due to space. By now, you should have a general idea about these prompts and their meaning. It's always recommended, though, to ponder upon the permissions asked for and act accordingly.

We may have to run the aa-logprof command a couple of times because, with each iteration, new permissions will be discovered and addressed, depending on the child processes that are spawned by our script and so on. Eventually, the appackt script will run successfully.

During the iterative process described previously, we may end up with a few unknown or orphaned entries in the AppArmor database, which are artifacts of our previous attempts, to secure our application:

 Remnants of the iterative process

 Figure 9 – Remnants of the iterative process

They will all be named according to the path of or our application (/home/packt/appackt). We can clean up these entries with the following command:

sudo aa-remove-unknown

We can now verify that our app is indeed guarded with AppArmor:

sudo aa-status

The relevant excerpt from the output is as follows:

 appackt in complain mode

Figure 10 – appackt in complain mode

Our application (/home/packt/appackt) is shown, as expected, in complain mode. The other two are system application-related and are not relevant for us.

Next, we need to validate that our app complies with the security policies enforced by AppArmor. Let's edit the appackt script and change the LOG_FILE path in line 6 to the following:

LOG_FILE="./logs/appackt"

We have changed the output directory from log to logs. Let's create the logs directory and run our app:

mkdir logs

./appackt

The preceding output suggests that appackt is attempting to access a path outside the permitted boundaries by AppArmor, thus validating our profile:

 appackt acting outside security boundaries

 Figure 11 – appackt acting outside security boundaries

Let's revert the preceding changes and have the appackt script act normally. We are now ready to enforce our app by changing its profile mode with the following command:

sudo aa-enforce /home/packt/appackt

The output is as follows:

 Changing the appackt profile to enforce mode

Figure 12 – Changing the appackt profile to enforce mode

We can verify that our application is indeed running in enforce mode with the following command:

sudo aa-status

The relevant output is as follows:

 appackt running in enforce mode

Figure 13 – appackt running in enforce mode

If we wanted to make further adjustments to our application and then test it with the related changes, we would have to change the profile mode to complain and then reiterate the steps described earlier in this section. The following command sets the application profile to complain mode:

sudo aa-complain /home/packt/appackt

AppArmor profiles are plain text files stored in the /etc/apparmor.d/ directory. Creating or modifying AppArmor profiles usually involves manually editing the corresponding files or the procedure described in this section using the aa-genprof and aa-logprof tools.

Next, let's look at how to disable or enable AppArmor application profiles.

Disabling and enabling profiles

Sometimes, we may want to disable a problematic application profile while working on a better version. Here's how we do this.

First, we need to locate the application profile we want to disable (for example, appackt). The related file is in the /etc/apparmor.d/ directory, and it's named according to its full path, with dots (.) instead of slashes (/). In our case, the file is /etc/apparmor.d/home.packt.appackt.

To disable the profile, we must run the following commands:

sudo ln -s /etc/apparmor.d/home.packt.appackt /etc/apparmor.d/disable/

sudo apparmor_parser -R /etc/apparmor.d/home.packt.appackt

If we run the aa-status command, we won't see our appackt profile anymore. The related profile is still present in the filesystem, at /etc/apparmor.d/disable/home.packt.appackt:

 The disabled appackt profile

Figure 14 – The disabled appackt profile

In this situation, the appackt script is not enforced by any restrictions. To reenable the related security profile, we can run the following commands:

sudo rm /etc/apparmor.d/disable/home.packt.appackt

sudo apparmor_parser -r /etc/apparmor.d/home.packt.appackt

The appackt profile should now show up in the aa-status output as running in complain mode. We can bring it into enforce mode with the following:

sudo aa-enforce /home/packt/appackt

To disable or enable the profile, we used the apparmor_parser command, besides the related filesystem operations. This utility assists with loading (-r, --replace) or unloading (-R, --remove) security profiles to and from the kernel.

Deleting AppArmor security profiles is functionally equivalent to disabling them. We can also choose to remove the related file from the filesystem altogether. If we delete a profile without removing it from the kernel first (with apparmor_parser -R), we can use the aa-remove-unknown command to clean up orphaned entries.

Let's conclude our relatively brief study of AppArmor internals with some final thoughts.

Final considerations

Working with AppArmor is relatively easier than SELinux, especially when it comes to generating security policies or switching back and forth between permissive mode and non-permissive mode. SELinux can only toggle the permissive context for the entire system, while AppArmor does it at the application level. On the other hand, there might be no choice between the two, as some major Linux distributions either support one or the other. AppArmor is a prodigy of Debian, Ubuntu, and, recently, OpenSUSE, while SELinux runs on RHEL/CentOS. Theoretically, you can always try to port the related kernel modules across distros, but that's not a trivial task.

As a final note, we should reiterate that in the big picture of Linux security, SELinux and AppArmor are ACMs that act locally on a system, at the application level. When it comes to securing applications and computer systems from the outside world, firewalls come into play. We'll look at firewalls next.

Вас заинтересует / Intresting for you:

Managing SELinux policies: pra...
Managing SELinux policies: pra... 179 views Zero Cool Tue, 20 Jul 2021, 07:15:32
Choosing the right Linux distr...
Choosing the right Linux distr... 206 views Zero Cool Wed, 14 Jul 2021, 19:26:27
Understanding SELinux contexts...
Understanding SELinux contexts... 223 views Zero Cool Tue, 10 Aug 2021, 18:06:33
The /etc/passwd Linux File - F...
The /etc/passwd Linux File - F... 871 views Mike Sat, 06 Feb 2021, 19:19:50