Apparmor es un sistema de control obligatorio de acceso («Mandatory Access Control» o «MAC») basado en la interfaz LSM (módulos de seguridad de Linux «Linux Security Modules»). En la práctica, el núcleo pregunta a AppArmor antes de cada llamada al sistema para saber si un proceso está autorizado a realizar dicha operación. A través de este mecanismo, Apparmor confina un programa a un conjunto limitado de recursos.
Para que apparmor funcione debemos tener habilitadas ciertas opciones del kernel:
CONFIG_SECURITY_APPARMOR=y
CONFIG_AUDIT=y
CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1
CONFIG_DEFAULT_SECURITY_APPARMOR=y
Instalamos las user-lands:
En este ejemplo aplicaremos un perfil apparmor sobre el FPM de php, de este modo limitaremos las acciones permitidas al código php.
Apache y php se compilarán del siguiente modo:
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
Compilamos php:
Configuramos FPM:
listen = /var/run/php7.2-fpm.sock
listen.owner = apache
listen.group = apache
user = apache
group = apache
Reiniciamos el servicio:
Creamos un vhost de pruebas:
<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>
Creamos el directorio docroot y aplicamos ACLs para que el usuario apache pueda leer y escribir en él:
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
Aplicamos los cambios:
Programamos un pequeño formulario con un campo de texto, el contenido de dicho campo se guardará en un fichero:
<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"]);
?>
Para hacer la prueba subiremos una pequeña webshell, accedemos a la web y pegamos en el campo de texto el código:
http://www.test.com/
Código:
<?php echo shell_exec($_GETcmd.' 2>&1'); ?>
Comprobamos mediante curl si ha funcionado:
uid=81(apache) gid=81(apache) groups=81(apache)
Antes de generar el perfil de apparmor lo paramos:
Comenzamos a guardar las operaciones realizadas por FPM generando el perfil:
Navegamos por la web para que logee las llamadas.
Realizamos tareas típicas de fpm:
/etc/init.d/php-fpm stop
/etc/init.d/php-fpm start
/etc/init.d/php-fpm status
Presionamos S
Updating AppArmor profiles in /etc/apparmor.d.
Nos preguntará si queremos meter las ACLs indicadas, del siguiente estilo:
[1 - signal send set=term peer=unconfined,]
(A)llow / [(D)eny] / (I)gnore / Audi(t) / Abo(r)t / (F)inish
Cuando termine, presionamos la F
Comprobamos que existe un nuevo perfil:
-rw------- 1 root root 190 nov 7 15:38 usr.lib64.php7.2.bin.php-fpm
Por defecto nos mete perfiles pero nosotros solo queremos limitar el FPM:
find -type f -maxdepth 1 -exec aa-disable {} ;
Arrancamos apparmor y habilitamos el perfil a aplicar:
aa-enforce /etc/apparmor.d/usr.lib64.php7.2.bin.php-fpm
Consultamos el estado:
1 profiles are in enforce mode.
/usr/lib64/php7.2/bin/php-fpm
Añadimos apparmor al arranque:
Ahora si intentamos escribir el fichero en el disco duro:
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
Efectivamente no se ha generado ningún fichero:
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
NOTA: Si ya existe el perfil es mejor borrarlo manualmente y regenerarlo con aa-genprof.