AppArmor is a Mandatory Access Control (MAC) system based on the Linux Security Modules (LSM) interface. In practice, the kernel asks AppArmor before each system call to determine if a process is authorized to perform that operation. Through this mechanism, AppArmor confines a program to a limited set of resources.
To make AppArmor work, we must have certain kernel options enabled:
CONFIG_SECURITY_APPARMOR=y
CONFIG_AUDIT=y
CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1
CONFIG_DEFAULT_SECURITY_APPARMOR=y
We install the user-lands:
In this example, we will apply an AppArmor profile to the PHP FPM, thus limiting the actions allowed to the PHP code.
Apache and PHP will be compiled as follows:
PHP_TARGETS="php7-2"
PHP_INI_VERSION="production"
www-servers/apache threads
dev-lang/php apache2 berkdb bzip2 cli crypt ctype curl curlwrappers exif fileinfo filter ftp gd gdbm hash iconv imap intl json mysql mysqli nls odbc pdo phar posix readline session simplexml soap sockets sqlite ssl sysvipc threads tokenizer unicode xml xmlreader xmlrpc xmlwriter zip zlib threads fpm cgi truetype bcmath ldap pcntl
We compile PHP:
We configure FPM:
listen = /var/run/php7.2-fpm.sock
listen.owner = apache
listen.group = apache
user = apache
group = apache
We restart the service:
We create a test vhost:
<VirtualHost *:80>
ServerAdmin sys@alfaexploit.com
DocumentRoot /var/www/test
ServerName www.test.com
ErrorLog /var/log/apache2/test.error_log
CustomLog /var/log/apache2/test.access_log combined
DirectoryIndex index.php index.htm index.html
AddHandler application/x-httpd-php .php .php5 .phtml
AddHandler application/x-httpd-php-source .phps
<FilesMatch ".php$">
SetHandler "proxy:unix:///var/run/php7.2-fpm.sock|fcgi://localhost/"
</FilesMatch>
<Directory "/var/www/test">
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
We create the docroot directory and apply ACLs so that the apache user can read and write to it:
chown -R kr0m:kr0m /var/www/test
setfacl -dR -m u:apache:rwX -m u:kr0m:rwX /var/www/test
setfacl -R -m u:apache:rwX -m u:kr0m:rwX /var/www/test
We apply the changes:
We program a small form with a text field, the content of which will be saved in a file:
<body>
<form action="/writeFile.php" method="post">
Code: <input type="text" name="code" style="width: 1024px;"><br>
<input type="submit" value="Submit">
</form>
</body>
<?php
$fichero = 'file.php';
file_put_contents($fichero, $_POST["code"]);
?>
To test it, we will upload a small webshell, access the website, and paste the following code into the text field:
http://www.test.com/
Code:
<?php echo shell_exec($_GETcmd.' 2>&1'); ?>
We check if it worked using curl:
uid=81(apache) gid=81(apache) groups=81(apache)
Before generating the apparmor profile, we stop it:
We start saving the operations performed by FPM by generating the profile:
We navigate through the website to log the calls.
We perform typical FPM tasks:
/etc/init.d/php-fpm stop
/etc/init.d/php-fpm start
/etc/init.d/php-fpm status
We press S
Updating AppArmor profiles in /etc/apparmor.d.
It will ask us if we want to include the indicated ACLs, in the following style:
[1 - signal send set=term peer=unconfined,]
(A)llow / [(D)eny] / (I)gnore / Audi(t) / Abo(r)t / (F)inish
When finished, press F
Check that a new profile exists:
-rw------- 1 root root 190 nov 7 15:38 usr.lib64.php7.2.bin.php-fpm
By default, it puts profiles on us, but we only want to limit FPM:
find -type f -maxdepth 1 -exec aa-disable {} ;
Start apparmor and enable the profile to apply:
aa-enforce /etc/apparmor.d/usr.lib64.php7.2.bin.php-fpm
Check the status:
1 profiles are in enforce mode.
/usr/lib64/php7.2/bin/php-fpm
Add apparmor to the boot:
Now if we try to write the file to the hard drive:
Nov 7 16:34:31 NZXT48 kernel: [62029.240917] audit: type=1400 audit(1541604871.745:525): apparmor=“DENIED” operation=“open” profile="/usr/lib64/php7.2/bin/php-fpm" name="/var/www/test/file.php" pid=705 comm=“php-fpm” requested_mask=“wc” denied_mask=“wc” fsuid=81 ouid=81
No file has actually been generated:
total 20
drwxrwxr-x+ 2 kr0m kr0m 4096 nov 7 16:34 .
drwxr-xr-x 9 apache root 4096 nov 7 13:44 ..
-rw-rw-r–+ 1 kr0m kr0m 176 nov 7 13:49 index.php
-rw-rw-r–+ 1 kr0m kr0m 79 nov 7 13:51 writeFile.php
NOTE: If the profile already exists, it is better to manually delete it and regenerate it with aa-genprof.