Esta pagina se ve mejor con JavaScript habilitado

AppArmor

 ·  🎃 kr0m

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:

emerge -av sys-apps/apparmor sec-policy/apparmor-profiles sys-apps/apparmor-utils

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:

vi /etc/make.conf

PHP_TARGETS="php7-2"
PHP_INI_VERSION="production"
vi /etc/portage/package.use/apache
www-servers/apache threads
vi /etc/portage/package.use/php
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:

emerge -av www-servers/apache dev-lang/php

Configuramos FPM:

vi /etc/php/fpm-php7.2/fpm.d/www.conf

listen = /var/run/php7.2-fpm.sock
listen.owner = apache
listen.group = apache
user = apache
group = apache

Reiniciamos el servicio:

/etc/init.d/php-fpm restart

Creamos un vhost de pruebas:

vi /etc/apache2/vhosts.d/test.conf

<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:

mkdir /var/www/test
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:

/etc/init.d/apache2 restart

Programamos un pequeño formulario con un campo de texto, el contenido de dicho campo se guardará en un fichero:

vi /var/www/test/index.php

<body>
  <form action="/writeFile.php" method="post">
    Code: <input type="text" name="code" style="width: 1024px;"><br>
    <input type="submit" value="Submit">
  </form>
</body>
vi /var/www/test/writeFile.php
<?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:

/etc/init.d/apparmor stop

Comenzamos a guardar las operaciones realizadas por FPM generando el perfil:

aa-genprof /usr/bin/php-fpm

Navegamos por la web para que logee las llamadas.
Realizamos tareas típicas de fpm:

/etc/init.d/php-fpm restart
/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:

ls -la /etc/apparmor.d/

-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:

cd /etc/apparmor.d
find -type f -maxdepth 1 -exec aa-disable {} ;

Arrancamos apparmor y habilitamos el perfil a aplicar:

/etc/init.d/apparmor start
aa-enforce /etc/apparmor.d/usr.lib64.php7.2.bin.php-fpm

Consultamos el estado:

apparmor_status

1 profiles are in enforce mode.
 /usr/lib64/php7.2/bin/php-fpm

Añadimos apparmor al arranque:

rc-update add apparmor boot

Ahora si intentamos escribir el fichero en el disco duro:

tail -f /var/log/messages
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:

ls -la /var/www/test/
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.

Si te ha gustado el artículo puedes invitarme a un RedBull aquí