flawopen.com/Teardowns/cve-2023-6246-glibc-syslog-heap-buffer-overflow
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.
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()yvsyslog()para formatear el mensaje y suSYSLOG_HEADERantes 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
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.
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.
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.
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
/* 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. */
/* 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
- ✓Actualiza glibc con el paquete corregido para tu distribución y versión; no deduzcas el estado del paquete solo por la versión upstream.
- ✓Verifica el aviso de tu distribución: las correcciones upstream son glibc 2.39, 2.38-42, 2.37-57 y 2.36-126.
- ✓Inventaría programas privilegiados que llamen a
syslog()ovsyslog()y comprueba si nombres controlados por el llamador o identificadoresopenlog()llegan al encabezado. - ✓Al implementar logging formateado, contabiliza el tamaño total del encabezado y el cuerpo aunque el búfer fijo inicial no alcance; añade una prueba con un nombre de programa largo y revisa la aritmética de la asignación.