FlawOpen

flawopen.com/Teardowns/cve-2024-33066-qualcomm-wlan-log-redirection

● CVE-2024-33066 · CVSS 9.8 · Crítica
Investigación · FlawOpen

CVE-2024-33066: fallo de logs WLAN de Qualcomm

CVE-2024-33066 puede corromper memoria al redirigir logs a rutas elegidas en el WLAN Resource Manager de Qualcomm. Corregida en oct. de 2024.

💡 Explicación en Lenguaje Sencillo (ELI5)

Imagina la recepción de un hotel que deja que cualquiera llame y diga: «a partir de ahora, manda copias del libro de huéspedes a esta dirección». El recepcionista copia lo que le dictan en una ficha pequeña, aunque el texto se salga de la ficha y siga por el mostrador, y luego envía las copias adonde ponga, incluida la caja fuerte del director. La solución es aceptar solo una etiqueta corta que nombre un cajón del archivo.

Conceptos Clave y Términos

WLAN Resource Manager
El componente Wi-Fi citado en el aviso de Qualcomm sobre CVE-2024-33066. Funciona en las plataformas de red de Qualcomm, usadas en routers, sistemas mesh y puntos de acceso.
Chipsets IPQ / QCN
Familias de system-on-chip de red Wi-Fi de Qualcomm. La lista afectada incluye IPQ5332, IPQ8074A, IPQ9574, QCN9000 y las plataformas Immersive Home, no chipsets de móviles.
CWE-20
Validación de entrada incorrecta: el software confía en la entrada sin comprobar que tiene las propiedades de las que depende el código, como una longitud máxima o un directorio permitido.
Apertura relativa a un directorio
Abrir un fichero con openat() sobre un descriptor de directorio y con un nombre simple sin '/', de modo que el resultado no pueda quedar fuera de ese directorio.
Vector CVSS 3.1
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H: accesible por red, complejidad baja, sin privilegios ni interacción del usuario e impacto alto en las tres propiedades (puntuación 9.8).

Mapeos de marcos

  • Referencia CWE para la debilidad descrita en esta guía: CWE-20

Análisis de Causa Raíz

El aviso de Qualcomm solo dice que el WLAN Resource Manager sufría corrupción de memoria "while redirecting log file to any file location with any file name" (CWE-20). El destino enviado con una petición de redirección de registros se usaba sin comprobar su longitud ni adónde apuntaba. El código de abajo modela ese fallo de validación; es ilustrativo y no es código fuente de Qualcomm.

Flujo de Ataque Paso a Paso

Paso 1

1. Llega una petición de redirección de registros

El WLAN Resource Manager acepta una petición para enviar su salida de registro a otro sitio. El vector CVSS (AV:N/PR:N/UI:N) califica el fallo como accesible por red, sin privilegios ni interacción del usuario.

Paso 2

2. Se acepta cualquier ubicación y cualquier nombre

Según la descripción de Qualcomm, la redirección funcionaba hacia cualquier ubicación y con cualquier nombre de fichero: no se comprobaba ni la longitud del destino pedido ni adónde apuntaba.

Paso 3

3. La entrada sin comprobar corrompe la memoria

En el modelo de abajo, un nombre más largo que el búfer fijo de la ruta lo desborda (strcpy), y cualquier ruta, incluidos ficheros de configuración, puede abrirse para escritura. Qualcomm no ha publicado cuál de estos casos se daba en su código.

Paso 4

4. Impacto y estado

CVSS 3.1 califica como alto el impacto en confidencialidad, integridad y disponibilidad (9.8). Qualcomm entregó la corrección a los fabricantes en su boletín de octubre de 2024; el triaje de CISA no registra explotación conocida.

Código Fuente: Vulnerable vs. Seguro

Modelo ilustrativo de la clase de vulnerabilidad, no es código de Qualcomm. El manejador reforzado acota la entrada con strnlen antes de tocarla, solo acepta un nombre corto de un conjunto fijo de caracteres (sin '/' ni '.' inicial) y lo abre con openat() respecto a un directorio de registros elegido al arrancar, con O_NOFOLLOW para que un enlace simbólico plantado no desvíe la escritura. Quien llama puede elegir el nombre del fichero, pero nunca la ubicación, y la entrada demasiado larga se rechaza en lugar de copiarse.

IMPLEMENTACIÓN VULNERABLE
#include <fcntl.h>
#include <string.h>

#define LOG_PATH_MAX 64

struct rm_log_cfg {
    char path[LOG_PATH_MAX];
    int fd;
};

/* Gestiona una solicitud de «redirección de registro»; `requested` procede del cuerpo de la solicitud. */
int rm_set_log_destination(struct rm_log_cfg *cfg, const char *requested)
{
    strcpy(cfg->path, requested);   /* sin comprobar la longitud: una entrada larga desborda path[] */
    cfg->fd = open(cfg->path, O_WRONLY | O_CREAT | O_APPEND, 0644);  /* cualquier ubicación */
    return cfg->fd < 0 ? -1 : 0;
}
PARCHE SEGURO Y ROBUSTO
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>

#define LOG_NAME_MAX 32

struct rm_log_cfg {
    int dir_fd;                /* directorio de registros fijo, abierto una vez al iniciar */
    char name[LOG_NAME_MAX];
    int fd;
};

static int valid_log_name(const char *name, size_t len)
{
    if (len == 0 || len >= LOG_NAME_MAX || name[0] == '.')
        return 0;
    for (size_t i = 0; i < len; i++) {
        char c = name[i];
        int ok = (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') ||
                 c == '-' || c == '_' || c == '.';
        if (!ok)
            return 0;          /* rechaza '/', por lo que el nombre no puede salir de dir_fd */
    }
    return 1;
}

int rm_set_log_destination(struct rm_log_cfg *cfg, const char *requested)
{
    size_t len = strnlen(requested, LOG_NAME_MAX);
    if (!valid_log_name(requested, len))
        return -EINVAL;

    int fd = openat(cfg->dir_fd, requested,
                    O_WRONLY | O_CREAT | O_APPEND | O_NOFOLLOW | O_CLOEXEC, 0600);
    if (fd < 0)
        return -errno;

    memcpy(cfg->name, requested, len + 1);
    if (cfg->fd >= 0)
        close(cfg->fd);
    cfg->fd = fd;
    return 0;
}

Lista de Verificación de Seguridad para Ingeniería

Fuentes