Blog

Archive for diciembre, 2016

Cómo Debian solucionó el CVE-2016-1247, escalado de root por el log de NGINX

Introdución

Este artículo explora el exploit CVE-2016-1247, y cómo fue corregido por Debian y qué lecciones podemos extraer de él para incluso ir un poco más allá para proteger/asegurar sus sistemas.

Este artículo también aplica a CVE-2016-6664-5617, escalado root MySQL, que aunque no es una cuestión específica de Debian, es el mismo fallo conceptual en el wrapper mysql que permitió al autor del PoC (Dawid Golunski) crear un exploit funcional.

Cómo funciona el PoC de Dawid Golunski (CVE-2016-1247 antecedentes)

Recientemente Dawid Golunski (https://legalhackers.com/advisories/Nginx-Exploit-Deb-Root-PrivEsc-CVE-2016-1247.html) informó un PoC que escala sin problemas desde el usuario www-data (el usuario nginx por defecto) al la cuenta root completa. ¡Casi nada!

Revisando en detalle el bug reportado, reduciendo los pasos tomados por Dawid para romper el sistema, e ignorando algunos detalles por brevedad, éstos son los siguientes:

  1. Primero, el PoC comienza con la suposición (no muy complicada de conseguir) que se dispone del control de la cuenta www-data mediante el control de un fichero .php, cgi similar, una cuenta de administración WordPress a la web o un mecanismo similar que permita subir ficheros .php para ejecutar comandos arbitrarios.
  2. Desde ahí, Dawid descubrió que la rotación de log hecha por “logrotate” ajusta los siguientes permisos cada día que rota:
         /var/log/nginx/*.log
         create 0640 www-data adm

    Eso es, “logrotate” rotará y creará (este es el punto) un fichero vacío con los permisos www-data:adm. Parece inocuo, pero aquí está el detalle fatal.

  3. Desde ahí, el resto sólo es consecuencia: el PoC de Dawid borra el fichero /var/log/nginx/error.log y crea un enlace a /etc/ld.so.preload:
        rm /var/log/nginx/error.log
        ln -s /etc/ld.so.preload /var/log/nginx/error.log

    NOTA: para aquellos preguntándose, “¿pero para qué demonios es ese fichero?”

    Básicamente ese fichero permite configurar las “librerías” que serán “pre cargadas” antes de que otra librería lo sea antes de lanzar un binario.

    En esencia, este mecanismo permite “interceptar” símbolos/funciones para ser reemplazadas con el código que se desee. Puede ser usado como un mecanismo “para una solución externa” sin modificación de binario, pero, como todo mecanismo, puede ser utilizado para el mal.

    Para más información vea: http://man7.org/linux/man-pages/man8/ld.so.8.html

  4. Una vez que el PoC de Dawid crea ese enlace, ya solo resta esperar para el siguiente día para que la rotación de log ocurra y dejar que el propio sistema “abra la puerta para nosotros” através “de ajustar unos permisos www-data:adm” a /etc/ld.so.preload.

    NOTA: aquí es donde puede darle al play de “Carmina Buruana” para escucharlo de fondo

  5. Desde ahí, el PoC de Dawid crea una pequeña librería que es “precargada” y enlazada a cualquier binario cargado por su sistema, incluyendo código para detectar “cuando ejecuta como root”…y cuando lo haga, “Pumba!”, este código creará una copia con setuid de una shell para que el atacante pueda escalar sin clave.

Pero oiga, el artículo comenzó diciendo “cómo Debian corregió este problema”, ¿no?

Cierto, queríamos hacer un repaso de cómo el PoC funciona para entender mejor la corrección introducida y qué podemos aprender de ella.

Regresando a la solución, si mirando el “ChangeLog” de Debian, lo que han hecho es “asegurar” los permisos de log para que el directorio sea poseido por “root:adm” en lugar de “www-data:adm”:

https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=842295

    +  * debian/nginx-common.postinst:
    +    + CVE-2016-1247: Secure log file handling (owner & permissions)
    +      against privilege escalation attacks. /var/log/nginx is now owned
    +      by root:adm. Thanks ro Dawid Golunski for the report.
    +      Changing /var/log/nginx permissions effectively reopens #701112,
    +      since log files can be world-readable. This is a trade-off until
    +      a better log opening solution is implemented upstream (trac:376).
    +      (Closes: #842295)

Ciertamente, tener el directorio “/var/log/nginx” bajo los permisos de root:adm hace imposible que para www-data pueda borrar el fichero /var/log/nginx/error.log y hacer así que “logrotate” nos cree un fichero /etc/ld.so.preload poseido por www-data (que es la clave).

Sin embargo, ¿hay más lecciones que podamos aprender para asegurar mejor nuestro sistema para defenderse mejor para este tipo de ataques de rotación? Siga leyendo.

Cómo los servicios deberían gestionar los logs (consejos para desarrolladores y administradores)

Uno de los problemas de la configuración nginx es que no separa la gestión de los logs de la producción de los mismos. Al hacer que el servicio nginx gestione el log directamente en lugar de usar syslog hace que se cree un problema de permisos que no puede ser fácilmente solucionado/asegurado.

Si separa la gestión de los logs (de manera que syslog gestione todos los logs producidos por nginx), puede asegurar todos los logs (poseidos y accesibles para root:adm), rotarlos, etc, sin preocuparse de lo que puedan hacer los usuarios (en principio usuarios de privilegio bajo). Éstos solo podrán atacar los ficheros poseídos por ellos mismos (en principio sólo los ficheros de la web) que, además, no son rotados.

Vea https://nginx.org/en/docs/syslog.html (para comenzar a usar syslog en su configuración nginx)

El servicio nunca debería poseer el log
Así que una conclusión general que podemos extraer de esto es: nunca deje que el log sea poseído por el servicio que lo produce, de lo contrario, esto podrá ser usado para escalar usando el mismo mecanismo que el PoC de Dawid Gulonski.

Como ejemplo, lo siguiente es incorrecto:

   service-user:adm   640        # configuración mala/débil

…y una buena definición es:

  root:adm  640   # Esta es una buena/recomendada configuración porque impide al usuario
                  # borrar este log y crear un link a ficheros sensibles.

Pero espero, ¿qué hago con clamav, roundcube, mysql, dovecot (por nombrar algunos)?

Algunos servicios vienen con una configuración de paquete por defecto que no permite cambiar este log a “root:adm” debido a que el servicio necesita abrir y escribir a estos logs.

En cualquier caso, todos estos servicios PUEDEN ser configurados para usar syslog y usted debería considerar configurar su sistema para que lo hagan así.

De hecho, Dawid Golunski también descubrió “exáctamente” el mismo tipo de fallo en los paquetes de MySQL, donde el escalado a root vía log es posible (https://legalhackers.com/advisories/MySQL-Maria-Percona-RootPrivEsc-CVE-2016-6664-5617-Exploit.html ).

La configuración de gestión de log por defecto puede no ser buena
Este artículo pretende elevar la atención sobre la configuración por defecto de los logs. Las distribuciones Linux proporcionan una configuración por defecto pero aún así tiene que revisar cuidadósamente cómo el log es gestionado, rotado y poseído.

Primera conclusión: use siempre la separación de servicio para el log (si la seguridad es importante para usted)

Por este motivo es muy importante concentrar la gestión/reporte de log a syslog (o similar) para que pueda separar el servicio de la gestión de log (lo que soluciona todo este lío).

De nuevo, si hace que su servicio ejecute con un usuario de privilegio bajo (por ejemplo: mysql, www-data, clamav,…) y la gestión de logs está gestionada por un servicio independiente (rsyslog, por ejemplo), entonces podrá crear configuraciones de rotado que serán siempre seguras y “que no dependerán de fallos de wrappers o problemas en el empaquetamiento” que, al final, pueden ocasionar que al final se tomen decisiones controvertidas (más sobre esto después).

Segunda conclusión: ¿porqué esperar a que ocurra el problema?

Para evitar que mayores problemas ocurran y no puede controlar cómo el empaquetamiento es hecho, o cómo la supervisión de wrappers es escrita, etc, puede bloquear este tipo de ataques ejecutando lo siguiente:

   touch /etc/ld.so.preload
   chown root:root /etc/ld.so.preload 
   chmod 644 /etc/ld.so.preload        
   chattr +i /etc/ld.so.preload

De esta manera puede asegurarse que el fichero existe y no puede ser actualizado (incluso para el root! a no ser que el atacante ya posea la cuenta de root para quitar el flag +i).

Con este ajuste deshabilitará completamente el PoC de Dawid Golunski y hará más complicado que su sistema sea atacable por este tipo de técnicas de escalado por rotado de log.

Tercera conclusión: “logrotate” debe ser constantemente comprobado

El servicio “logrotate” es parte del esquema para atacar el sistema a través de la creación de configuraciones “débiles” que rotan usando usuarios de privilegios bajos como los siguientes (ejemplo Debian):

  /etc/logrotate.d/mysql-server:	create 640 mysql adm

Como se muestra en https://legalhackers.com/advisories/MySQL-Maria-Percona-RootPrivEsc-CVE-2016-6664-5617-Exploit.html, esta configuración puede ser explotada (escalado de log desde usuario mysql). Lo mejor es hacer que el servicio de MySQL use el syslog para gestionar todo el reportado de log y hacer que el propietario del log sea:

   /etc/logrotate.d/mysql-server:	create 640 root adm

Sabiendo esto, puede usar el siguiente comando para revisar aquellas configuraciones “logrotate” que puedan ser posibles brechas en su sistema:

   find /etc/logrotate.d /etc/logrotate.conf -type f -exec grep -H create {} \; | grep -v "create 640 root adm"

Cuarta conclusión: no puede escapar de esto

Puede que esté pensando “bien, pero esto es un tema interno..” o “puedo gestionarlo”. Quizás. En cualquier caso, veamos más detenidamente lo que “realmente” Debian hizo para corregir el error mirando el changlog:

  nginx-common (1.6.2-5+deb8u3) jessie-security; urgency=high

  In order to secure nginx against privilege escalation attacks, we are
  changing the way log file owners & permissions are handled so that www-data
  is not allowed to symlink a logfile. /var/log/nginx is now owned by root:adm
  and its permissions are changed to 0755. The package checks for such symlinks
  on existing installations and informs the admin using debconf.

  That unfortunately may come at a cost in terms of privacy. /var/log/nginx is
  now world-readable, and nginx hardcodes permissions of non-existing logs to
  0644. On systems running logrotate log files are private after the first
  logrotate run, since the new log files are created with 0640 permissions.

   -- Christos Trochalakis   Tue, 04 Oct 2016 15:20:33+0300

Eso es, Debian ha tomado el camino de limitar la creación de enlaces pero a costa de permitir que todos los usuarios puedan acceder al directorio de logs. De hecho, durante la instalación/actualización del parche, el paquete intenta detectar links de hacking que ya puedan existir:

  Template: nginx/log-symlinks
  Type: note
  _Description: Possible insecure nginx log files
    The following log files under /var/log/nginx directory are symlinks
    owned by www-data:
   .
   ${logfiles}
   .
   Since nginx 1.4.4-4 /var/log/nginx was owned by www-data. As a result
   www-data could symlink log files to sensitive locations, which in turn
   could lead to privilege escalation attacks. Although /var/log/nginx
   permissions are now fixed it is possible that such insecure links
   already exist. So, please make sure to check the above locations.

Como puede ver, “Sí”, la actualización de seguridad permite que todos los usuarios del sistema puedan acceder a estos logs y “sí”, la actualización no corrige los posibles hackings, tendrá que revisarlos de todas formas.

Esto puede ser interesante, pero para el alcance de este artículo, como puede ver, si no corrige la configuración de su sistema para “separar la gestión de logs de la producción del mismo” tendrá que tomar malas decisiones que de otro modo son fácilmente corregibles (y que no son la responsabilidad de Debian, por cierto).

Cómo Core-Admin gestiona y mitiga CVE-2016-1247 y CVE-2016-6664-5617

Con todos estos detalles explicados, Core-Admin hace dos cosas para migitar este tipo de atacaques de escalación a root mediante rotado de log:

  1. El comprobador “Renamed process” automáticamente asegura que el fichero /etc/ld.so.preload es protegido. También reporta cualquier cambio que ocurra en ese fichero.
  2. Tiene un comprobado de “log” que asegura que las configuraciones de “logrotate” estén funcionando y tengan declaraciones de propietario conocidas (o al menos aceptadas) que sean seguras, reportando cualquier configuración insegura que pueda conducir a problemas.

Posted in: Core-Admin, Debian, LogRotate, Seguridad

Leave a Comment (0) →