CACTI: Ejecución remota de código no autenticado

Cacti es una plataforma de código abierto basada en la web que proporciona un marco de gestión de fallas y monitoreo. Se ha descubierto una vulnerabilidad (CVE-2022-46169) que afecta a Cacti en las versiones 1.2.22 e inferiores, y tiene una puntuación CVSSv3 de 9,8 sobre 10.

En las versiones afectadas muestran una vulnerabilidad de inyección de comandos que permite a un usuario no autenticado ejecutar código arbitrario en un servidor que ejecuta una instancia de Cacti si cualquier dispositivo monitoreado utiliza una fuente de datos específica.

La vulnerabilidad existe debido a una autorización insuficiente dentro del «remote_agent.php» al manejar solicitudes HTTP con un encabezado HTTP «Forwarded-For» personalizado. Un atacante remoto no autenticado puede enviar una solicitud HTTP especialmente diseñada a la instancia afectada y ejecutar comandos arbitrarios del sistema operativo en el servidor.

El ataque se realiza por dos vulnerabilidades de código distintas.

1. Vulnerabilidad por omisión de autenticación

Una verificación de autorización basada en el nombre de host no se implementa de manera segura para la mayoría de las instalaciones de Cacti.

La vulnerabilidad reside en el script “remote_agent.php”, al cual solo los clientes autorizados deberían tener acceso.

La función “remote_client_authorized” recupera la dirección IP del cliente ($client_addr), la resuelve en el nombre de host correspondiente ($client_name) y verifica si la tabla “poller” contiene una entrada con este nombre de host.

En el archivo “cacti/lib/html_utility.php” encontramos la función “remote_client_authorized”. A continuación se muestra un fragmento de esta función:

En este fragmento de código se muestra la función “get_client_addr” que es la encargada de recuperar la dirección IP del cliente; podemos encontrar esta función en el archivo “cacti/lib/functions.php”.

Esta función tiene en cuenta una variedad de encabezados HTTP, los atacantes pueden controlar estos valores si no hay una instancia entre el cliente y el servidor web (es decir, un proxy inverso) que filtre estos encabezados HTTP.

La tabla “poller” contiene una entrada predeterminada con el nombre de host del servidor que ejecuta Cacti. Debido a esto, los atacantes pueden eludir la verificación de la función “remote_client_authorized”, por ejemplo, proporcionando el encabezado HTTP “X-Forwarded: <TARGET-IP>”. De esta forma, la función “get_client_addr” devuelve la dirección IP del servidor que ejecuta Cacti. La llamada a “gethostbyaddr” resuelve esta dirección IP en el nombre de host del servidor, que pasará la verificación del nombre de host de la tabla «poller» debido a la entrada predeterminada.

Esto permite que los atacantes no autenticados tengan acceso a la función “remote_agent.php”.

2. Vulnerabilidad por inyección de comando

La entrada de usuario no desinfectada se propaga a una cadena utilizada para ejecutar un comando externo.

El parámetro proporcionado por el usuario “poller_id” se propaga al primer parámetro “proc_open” sin desinfección. Esto introduce una vulnerabilidad de inyección de comandos en la función “poll_for_data”.

A continuación se muestra un fragmento del archivo “remote_agent.php”:

Los atacantes pueden activar la función vulnerable configurando el parámetro “action” en “polldata”. La función “poll_for_data” recupera los parámetros “host_id” y “poller_id”. Estos parámetros tienen una diferencia importante: el parámetro “host_id” proviene de “get_filter_request_var”, mientras que el parámetro “poller_id” proviene de “get_nfilter_request_var”, estas funciones se diferencian por el carácter “n”.

La función “get_filter_request_var” verifica que el parámetro recuperado es un número entero, mientra que la función “get_nfilter_request_var” se usa para recuperar el parámetro “poller_id” que permite cadenas arbitrarias.

Siguiendo el flujo de inyección, podemos ver que los elementos de “poller” se recuperan de la base de datos. Si la acción de uno de estos elementos se establece en “POLLER_ACTION_SCRIPT_PHP”, se emite la llamada vulnerable a “proc_open”.

Esto significa que los atacantes pueden aprovechar el parámetro “poller_id” para inyectar un comando arbitrario cuando existe un elemento con la acción «POLLER_ACTION_SCRIPT_PHP». Esto es muy probable en una instancia productiva porque esta acción la agregan algunas plantillas predefinidas como «Device – Uptime» o «Device – Polling Time».

El atacante debe proporcionar la identificación correspondiente para que la consulta de la base de datos devuelva dicho elemento. Dado que los identificadores están numerados en orden ascendente y se pueden enviar cientos de identificadores en una sola solicitud al proporcionar una matriz, los atacantes pueden descubrir fácilmente un identificador válido.

Recomendaciones

Se recomienda a los usuarios y administradores de las versiones de productos afectados que actualicen a la versión 1.2.23 de manera urgente.

Referencias