FlawOpen

flawopen.com/Teardowns/cve-2023-6246-glibc-syslog-heap-buffer-overflow

● CVE-2023-6246 · CVSS 7.8 · Alta
Investigación · FlawOpen

CVE-2023-6246: overflow de heap en syslog de glibc

CVE-2023-6246 es un overflow de heap en syslog de glibc por un encabezado largo. Actualiza el paquete glibc corregido de tu distribución.

💡 Explicación en Lenguaje Sencillo (ELI5)

Imagina a un empleado que mide un paquete y su etiqueta con una regla corta. La etiqueta no cabe, así que el cálculo no registra el espacio necesario. Pide entonces una caja diminuta e intenta imprimir en ella toda la etiqueta y el contenido. En glibc, un encabezado syslog largo podía dejar sin calcular el tamaño requerido y hacer que el registrador reservara muy poca memoria en el heap.

Conceptos Clave y Términos

glibc
La GNU C Library proporciona funciones centrales del runtime C que usan la mayoría de los programas Linux.
__vsyslog_internal()
Implementación interna de glibc usada por syslog() y vsyslog() para formatear el mensaje y su SYSLOG_HEADER antes de enviarlo al registrador del sistema.
SYSLOG_HEADER
Prefijo de prioridad e identificación que se formatea antes del mensaje syslog. Puede incluir el nombre del programa o un identificador pasado a openlog().
Heap-based buffer overflow (CWE-122)
Una escritura supera el límite de un búfer asignado en el heap. Aquí fallaba el cálculo cuando el encabezado con un nombre largo no cabía en el búfer fijo inicial.

Mapeos de marcos

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

Análisis de Causa Raíz

El aviso de glibc explica que __vsyslog_internal() no actualizaba el tamaño requerido al generar un SYSLOG_HEADER con un nombre de programa largo. En el código vulnerable, la longitud del encabezado l podía ser igual o superior al búfer de pila de 1.024 bytes, por lo que se omitía la rama que formateaba el cuerpo y establecía bufsize. La asignación posterior en el heap usaba un tamaño sin definir o igual a cero y luego escribía el encabezado y el mensaje en un espacio insuficiente. Qualys indica que el nombre largo puede proceder del basename de un argv[0] controlado por quien llama o de un identificador openlog() de más de 1.024 bytes; un programa setuid vulnerable que registre por esta ruta puede convertirlo en un problema de seguridad. Qualys demostró una elevación local de privilegios mediante su en Fedora 38. El riesgo depende del acceso local, la configuración y la ruta de llamada; no es un exploit remoto genérico de syslog.

Flujo de Ataque Paso a Paso

Paso 1

Condición local

Un proceso local debe llegar a syslog() o vsyslog() a través de un programa que use glibc afectada. El impacto de seguridad requiere un llamador privilegiado y una ruta que no sustituya el prefijo del nombre del programa por un identificador seguro y acotado.

Paso 2

Encabezado largo

El encabezado supera el búfer inicial|El SYSLOG_HEADER incluye un nombre de programa largo (__progname, derivado del basename de argv[0]) o un identificador largo de openlog(). Qualys indica que el valor debe superar 1.024 bytes.

Paso 3

Cálculo incompleto

Se omite la rama que calcula el tamaño|Cuando el encabezado no cabe en el búfer de pila de 1.024 bytes, el código vulnerable omite la rama que calcula bufsize. La ruta de asignación en el heap queda sin espacio suficiente para el encabezado y el mensaje formateado.

Paso 4

Impacto en memoria

La escritura supera la asignación|El registrador escribe el encabezado y el mensaje en un búfer demasiado pequeño y corrompe memoria del heap. Qualys demostró elevación local mediante su en Fedora 38; no extrapoles el mismo alcance a todas las aplicaciones o distribuciones.

Código Fuente: Vulnerable vs. Seguro

La rama anterior dejaba bufsize en cero si el encabezado no cabía en el búfer de pila, por lo que la reserva en el heap podía ser insuficiente. La corrección marca ese búfer como inutilizable, lo usa para medir el cuerpo, registra l + vl y continúa por la ruta de asignación existente con el tamaño requerido. Son extractos concretos de upstream, no funciones completas independientes.

Fragmento de origen: misc/syslog.c

IMPLEMENTACIÓN VULNERABLE
/* Fragmento específico de misc/syslog.c anterior al commit 6bd0e4efcc78. */
char bufs[1024];
char *buf = NULL;
size_t bufsize = 0;
...
if (0 <= l && l < sizeof bufs)
  {
    va_list apc;
    va_copy (apc, ap);
    int vl = __vsnprintf_internal (bufs + l, sizeof bufs - l, fmt, apc,
                                   mode_flags);
    if (0 <= vl && vl < sizeof bufs - l)
      buf = bufs;
    bufsize = l + vl;
    va_end (apc);
  }
/* Un encabezado largo omite la rama anterior que establece el tamaño. */
PARCHE SEGURO Y ROBUSTO
/* Fragmento específico de misc/syslog.c posterior al commit 6bd0e4efcc78. */
char bufs[1024];
char *buf = bufs;
size_t bufsize;
...
if (0 <= l && l < sizeof bufs)
  {
    pos = bufs + l;
    len = sizeof (bufs) - l;
  }
else
  {
    buf = NULL;
    pos = bufs;
    len = sizeof (bufs);
  }
vl = __vsnprintf_internal (pos, len, fmt, apc, mode_flags);
if (!(0 <= vl && vl < len))
  buf = NULL;
bufsize = l + vl;

Lista de Verificación de Seguridad para Ingeniería

Fuentes