Applies to openSUSE Leap 42.3

25 Profiling Your Web Applications Using ChangeHat

An AppArmor® profile represents the security policy for an individual program instance or process. It applies to an executable program, but if a portion of the program needs different access permissions than other portions, the program can change hats to use a different security context, distinctive from the access of the main program. This is known as a hat or subprofile.

ChangeHat enables programs to change to or from a hat within an AppArmor profile. It enables you to define security at a finer level than the process. This feature requires that each application be made ChangeHat-aware, meaning that it is modified to make a request to the AppArmor module to switch security domains at specific times during the application execution. One example of a ChangeHat-aware application is the Apache Web server.

A profile can have an arbitrary number of subprofiles, but there are only two levels: a subprofile cannot have further child profiles. A subprofile is written as a separate profile. Its name consists of the name of the containing profile followed by the subprofile name, separated by a ^.

Subprofiles are either stored in the same file as the parent profile, or in a separate file. The latter case is recommended on sites with many hats—it allows the policy caching to handle changes at the per hat level. If all the hats are in the same file as the parent profile, then the parent profile and all hats must be recompiled.

An external subprofile that is going to be used as a hat, must begin with the word hat or the ^ character.

The following two subprofiles cannot be used as a hat:

/foo//bar { }

or

profile /foo//bar { }

While the following two are treated as hats:

^/foo//bar { }

or

hat /foo//bar { } # this syntax is not highlighted in vim

Note that the security of hats is considerably weaker than that of full profiles. Using certain types of bugs in a program, an attacker may be able to escape from a hat into the containing profile. This is because the security of hats is determined by a secret key handled by the containing process, and the code running in the hat must not have access to the key. Thus, change_hat is most useful with application servers, where a language interpreter (such as PERL, PHP, or Java) is isolating pieces of code such that they do not have direct access to the memory of the containing process.

The rest of this chapter describes using change_hat with Apache, to contain Web server components run using mod_perl and mod_php. Similar approaches can be used with any application server by providing an application module similar to the mod_apparmor described next in Section 25.1.2, “Location and Directory Directives”.

Tip
Tip: For More Information

For more information, see the change_hat man page.

25.1 Configuring Apache for mod_apparmor

AppArmor provides a mod_apparmor module (package apache2-mod-apparmor) for the Apache program. This module makes the Apache Web server ChangeHat aware. Install it along with Apache.

When Apache is ChangeHat-aware, it checks for the following customized AppArmor security profiles in the order given for every URI request that it receives.

  • URI-specific hat. For example, ^www_app_name/templates/classic/images/bar_left.gif

  • DEFAULT_URI

  • HANDLING_UNTRUSTED_INPUT

Note
Note: Apache Configuration

If you install apache2-mod-apparmor, make sure the module is enabled, and then restart Apache by executing the following command:

a2enmod apparmor && sudo systemctl reload apache2

Apache is configured by placing directives in plain text configuration files. The main configuration file is usually /etc/apache2/httpd.conf. When you compile Apache, you can indicate the location of this file. Directives can be placed in any of these configuration files to alter the way Apache behaves. When you make changes to the main configuration files, you need to reload Apache with sudo systemctl reload apache2, so the changes are recognized.

25.1.1 Virtual Host Directives

<VirtualHost> and </VirtualHost> directives are used to enclose a group of directives that will apply only to a particular virtual host. For more information on Apache virtual host directives, refer to http://httpd.apache.org/docs/2.4/en/mod/core.html#virtualhost.

The ChangeHat-specific configuration keyword is AADefaultHatName. It is used similarly to AAHatName, for example, AADefaultHatName My_Funky_Default_Hat.

It allows you to specify a default hat to be used for virtual hosts and other Apache server directives, so that you can have different defaults for different virtual hosts. This can be overridden by the AAHatName directive and is checked for only if there is not a matching AAHatName or hat named by the URI. If the AADefaultHatName hat does not exist, it falls back to the DEFAULT_URI hat if it exists/

If none of those are matched, it goes back to the parent Apache hat.

25.1.2 Location and Directory Directives

Location and directory directives specify hat names in the program configuration file so the Apache calls the hat regarding its security. For Apache, you can find documentation about the location and directory directives at http://httpd.apache.org/docs/2.4/en/sections.html.

The location directive example below specifies that, for a given location, mod_apparmor should use a specific hat:

<Location /foo/>
  AAHatName MY_HAT_NAME
</Location>

This tries to use MY_HAT_NAME for any URI beginning with /foo/ (/foo/, /foo/bar, /foo/cgi/path/blah_blah/blah, etc.).

The directory directive works similarly to the location directive, except it refers to a path in the file system as in the following example:

<Directory "/srv/www/www.example.org/docs">
  # Note lack of trailing slash
  AAHatName example.org
</Directory>

25.2 Managing ChangeHat-Aware Applications

In the previous section you learned about mod_apparmor and the way it helps you to secure a specific Web application. This section walks you through a real-life example of creating a hat for a Web application, and using AppArmor's change_hat feature to secure it. Note that this chapter focuses on AppArmor's command line tools, as YaST's AppArmor module has limited functionality.

25.2.1 With AppArmor's Command Line Tools

For illustration purposes, let us choose the Web application called Adminer (http://www.adminer.org/en/). It is a full-featured SQL database management tool written in PHP, yet consisting of a single PHP file. For Adminer to work, you need to set up an Apache Web server, PHP and its Apache module, and one of the database drivers available for PHP—MariaDB in this example. You can install the required packages with

zypper in apache2 apache2-mod_apparmor apache2-mod_php5 php5 php5-mysql

To set up the Web environment for running Adminer, follow these steps:

Procedure 25.1: Setting Up a Web Server Environment
  1. Make sure apparmor and php5 modules are enabled for Apache. To enable the modules in any case, use:

    a2enmod apparmor php5

    and then restart Apache with

    sudo systemctl restart apache2
  2. Make sure MariaDB is running. If unsure, restart it with

    sudo systemctl restart mysql
  3. Download Adminer from http://www.adminer.org, copy it to /srv/www/htdocs/adminer/, and rename it to adminer.php, so that its full path is /srv/www/htdocs/adminer/adminer.php.

  4. Test Adminer in your Web browser by entering http://localhost/adminer/adminer.php in its URI address field. If you installed Adminer to a remote server, replace localhost with the real host name of the server.

    Adminer Login Page
    Figure 25.1: Adminer Login Page
    Tip
    Tip

    If you encounter problems viewing the Adminer login page, try to look for help in the Apache error log /var/log/apache2/error.log. Another reason you cannot access the Web page may be that your Apache is already under AppArmor control and its AppArmor profile is too tight to permit viewing Adminer. Check it with aa-status, and if needed, set Apache temporarily in complain mode with

    aa-complain usr.sbin.httpd2-prefork

After the Web environment for Adminer is ready, you need to configure Apache's mod_apparmor, so that AppArmor can detect accesses to Adminer and change to the specific hat.

Procedure 25.2: Configuring mod_apparmor
  1. Apache has several configuration files under /etc/apache2/ and /etc/apache2/conf.d/. Choose your preferred one and open it in a text editor. In this example, the vim editor is used to create a new configuration file /etc/apache2/conf.d/apparmor.conf.

    vim /etc/apache2/conf.d/apparmor.conf
  2. Copy the following snippet into the edited file.

    <Directory /srv/www/htdocs/adminer>
      AAHatName adminer
    </Directory>

    It tells Apache to let AppArmor know about a change_hat event when the Web user accesses the directory /adminer (and any file/directory inside) in Apache's document root. Remember, we placed the adminer.php application there.

  3. Save the file, close the editor, and restart Apache with

    sudo systemctl restart apache2

Apache now knows about our Adminer and changing a hat for it. It is time to create the related hat for Adminer in the AppArmor configuration. If you do not have an AppArmor profile yet, create one before proceeding. Remember that if your Apache's main binary is /usr/sbin/httpd2-prefork, then the related profile is named /etc/apparmor.d/usr.sbin.httpd2-prefork.

Procedure 25.3: Creating a Hat for Adminer
  1. Open (or create one if it does not exist) the file /etc/apparmor.d/usr.sbin.httpd2-prefork in a text editor. Its contents should be similar to the following:

    #include <tunables/global>
    
    /usr/sbin/httpd2-prefork {
      #include <abstractions/apache2-common>
      #include <abstractions/base>
      #include <abstractions/php5>
    
      capability kill,
      capability setgid,
      capability setuid,
    
      /etc/apache2/** r,
      /run/httpd.pid rw,
      /usr/lib{,32,64}/apache2*/** mr,
      /var/log/apache2/** rw,
    
      ^DEFAULT_URI {
        #include <abstractions/apache2-common>
        /var/log/apache2/** rw,
      }
    
      ^HANDLING_UNTRUSTED_INPUT {
        #include <abstractions/apache2-common>
        /var/log/apache2/** w,
      }
    }
  2. Before the last closing curly bracket (}), insert the following section:

    ^adminer flags=(complain) {
    }

    Note the (complain) addition after the hat name—it tells AppArmor to leave the adminer hat in complain mode. That is because we need to learn the hat profile by accessing Adminer later on.

  3. Save the file, and then restart AppArmor, then Apache.

    systemctl reload apparmor apache2
  4. Check if the adminer hat really is in complain mode.

    # aa-status
    apparmor module is loaded.
    39 profiles are loaded.
    37 profiles are in enforce mode.
    [...]
       /usr/sbin/httpd2-prefork
       /usr/sbin/httpd2-prefork//DEFAULT_URI
       /usr/sbin/httpd2-prefork//HANDLING_UNTRUSTED_INPUT
    [...]
    2 profiles are in complain mode.
       /usr/bin/getopt
       /usr/sbin/httpd2-prefork//adminer
    [...]

    As we can see, the httpd2-prefork//adminer is loaded in complain mode.

Our last task is to find out the right set of rules for the adminer hat. That is why we set the adminer hat into complain mode—the logging facility collects useful information about the access requirements of adminer.php as we use it via the Web browser. aa-logprof then helps us with creating the hat's profile.

Procedure 25.4: Generating Rules for the adminer Hat
  1. Open Adminer in the Web browser. If you installed it locally, then the URI is http://localhost/adminer/adminer.php.

  2. Choose the database engine you want to use (MariaDB in our case), and log in to Adminer using the existing database user name and password. You do not need to specify the database name as you can do so after logging in. Perform any operations with Adminer you like—create a new database, create a new table for it, set user privileges, and so on.

  3. After the short testing of Adminer's user interface, switch back to console and examine the log for collected data.

    # aa-logprof
    Reading log entries from /var/log/messages.
    Updating AppArmor profiles in /etc/apparmor.d.
    Complain-mode changes:
    
    Profile:  /usr/sbin/httpd2-prefork^adminer
    Path:     /dev/urandom
    Mode:     r
    Severity: 3
    
      1 - #include <abstractions/apache2-common>
    [...]
     [8 - /dev/urandom]
    
    [(A)llow] / (D)eny / (G)lob / Glob w/(E)xt / (N)ew / Abo(r)t / (F)inish / (O)pts

    From the aa-logprof message, it is clear that our new adminer hat was correctly detected:

    Profile:  /usr/sbin/httpd2-prefork^adminer

    The aa-logprof command will ask you to pick the right rule for each discovered AppArmor event. Specify the one you want to use, and confirm with Allow. For more information on working with the aa-genprof and aa-logprof interface, see Section 24.7.3.8, “aa-genprof—Generating Profiles”.

    Tip
    Tip

    aa-logprof usually offers several valid rules for the examined event. Some are abstractions—predefined sets of rules affecting a specific common group of targets. Sometimes it is useful to include such an abstraction instead of a direct URI rule:

     1 - #include <abstractions/php5>
     [2 - /var/lib/php5/sess_3jdmii9cacj1e3jnahbtopajl7p064ai242]

    In the example above, it is recommended hitting 1 and confirming with A to allow the abstraction.

  4. After the last change, you will be asked to save the changed profile.

    The following local profiles were changed. Would you like to save them?
     [1 - /usr/sbin/httpd2-prefork]
    
     (S)ave Changes / [(V)iew Changes] / Abo(r)t

    Hit S to save the changes.

  5. Set the profile to enforce mode with aa-enforce

    aa-enforce usr.sbin.httpd2-prefork

    and check its status with aa-status

    # aa-status
    apparmor module is loaded.
    39 profiles are loaded.
    38 profiles are in enforce mode.
    [...]
       /usr/sbin/httpd2-prefork
       /usr/sbin/httpd2-prefork//DEFAULT_URI
       /usr/sbin/httpd2-prefork//HANDLING_UNTRUSTED_INPUT
       /usr/sbin/httpd2-prefork//adminer
    [...]

    As you can see, the //adminer hat jumped from complain to enforce mode.

  6. Try to run Adminer in the Web browser, and if you encounter problems running it, switch it to the complain mode, repeat the steps that previously did not work well, and update the profile with aa-logprof until you are satisfied with the application's functionality.

Note
Note: Hat and Parent Profile Relationship

The profile ^adminer is only available in the context of a process running under the parent profile usr.sbin.httpd2-prefork.

25.2.2 Adding Hats and Entries to Hats in YaST

When you use the Edit Profile dialog (for instructions, refer to Section 23.2, “Editing Profiles”) or when you add a new profile using Manually Add Profile (for instructions, refer to Section 23.1, “Manually Adding a Profile”), you are given the option of adding hats (subprofiles) to your AppArmor profiles. Add a ChangeHat subprofile from the AppArmor Profile Dialog window as in the following.

AppArmor profile dialog
  1. From the AppArmor Profile Dialog window, click Add Entry then select Hat. The EnterHat Name dialog opens:

    Enter hat name
  2. Enter the name of the hat to add to the AppArmor profile. The name is the URI that, when accessed, receives the permissions set in the hat.

  3. Click Create Hat. You are returned to the AppArmor Profile Dialog screen.

  4. After adding the new hat, click Done.