Zyxel GS1900 : RCE avant authentification exploitée en conditions réelles (CVE-2026-107441)
Les commutateurs Zyxel GS1900 antérieurs au correctif 3 de la version 2.90 acceptent une requête HTTP non authentifiée qui exécute des commandes root.
En bref
- Une écriture hors limites dans
dispatcher.cgidu commutateur GS1900 permet à un attaquant non authentifié d'exécuter des commandes du système d'exploitation en tant que root. Binarly a trouvé l'exploit dans la boîte à outils d'un acteur malveillant et l'a testé sur du matériel réel. - Dix modèles GS1900 exécutant un micrologiciel 2.90(xxx.2)C0 ou antérieur sont concernés. Zyxel a publié les versions corrigées 2.90(xxx.3)C0 le 22 octobre 2026, et son avis le 3 novembre 2026.
- Zyxel la note 8,8 High et Binarly 9,8 Critical sur CVSS v3.1. GreyNoise a observé 996 commutateurs exploités. CVE-2026-107441 n'est pas au catalogue KEV de la CISA au 4 novembre 2026 ; CVE-2026-7273 y figure depuis le 21 septembre 2026.
- Mettez à jour chaque modèle listé vers sa version 2.90(xxx.3)C0 dès maintenant. Aucune solution de contournement par configuration ne ferme la faille ; voir « Comment corriger ? » pour réduire l'exposition en attendant une fenêtre de maintenance.
Suis-je concerné ?
Toutes ces conditions doivent être réunies pour qu'un commutateur soit exposé :
- L'appareil est l'un des dix modèles GS1900 listés par Zyxel, avec un micrologiciel 2.90(xxx.2)C0 ou antérieur.
- L'interface d'administration web du commutateur est joignable depuis un réseau que l'attaquant peut utiliser. Zyxel décrit l'attaquant comme présent sur le réseau local et adjacent. Binarly affirme que l'exploit ne demande que la joignabilité HTTP du service d'administration, sans adjacence au niveau du protocole.
- Le micrologiciel 2.90(xxx.3)C0 de ce modèle n'est pas installé. La mise à jour 2.90(xxx.2)C0 de juin 2026 ne corrige pas cette faille.
Zyxel indique que les produits encore commercialisés qui n'apparaissent pas dans son avis ne sont pas concernés. L'avis liste chaque couple modèle et version.
| Modèle | Versions concernées | Version corrigée |
|---|---|---|
| GS1900-8 | 2.90(AAHH.2)C0 et antérieures | 2.90(AAHH.3)C0 |
| GS1900-8HP | 2.90(AAHI.2)C0 et antérieures | 2.90(AAHI.3)C0 |
| GS1900-10HP | 2.90(AAZI.2)C0 et antérieures | 2.90(AAZI.3)C0 |
| GS1900-16 | 2.90(AAHJ.2)C0 et antérieures | 2.90(AAHJ.3)C0 |
| GS1900-24 | 2.90(AAHL.2)C0 et antérieures | 2.90(AAHL.3)C0 |
| GS1900-24E | 2.90(AAHK.2)C0 et antérieures | 2.90(AAHK.3)C0 |
| GS1900-24EP | 2.90(ABTO.2)C0 et antérieures | 2.90(ABTO.3)C0 |
| GS1900-24HPv2 | 2.90(ABTP.2)C0 et antérieures | 2.90(ABTP.3)C0 |
| GS1900-48 | 2.90(AAHN.2)C0 et antérieures | 2.90(AAHN.3)C0 |
| GS1900-48HPv2 | 2.90(ABTQ.2)C0 et antérieures | 2.90(ABTQ.3)C0 |
Vérifiez ce que le commutateur exécute :
- Connectez-vous au configurateur web du commutateur. L'écran Getting Started affiche le Model Name et la Firmware Version, sous la forme d'une chaîne comme
2.90(AAHL.2)C0. - Comparez le modèle et la version avec la liste de l'avis. Pour les modèles listés, toute version antérieure à
.3)C0est concernée, y compris.2)C0,.1)C0et.0)C0. Seule une version terminée par.3)C0porte le correctif de novembre. - Le commutateur n'a pas de gestionnaire de paquets. Notez la version dans votre inventaire, car un même numéro de modèle peut exécuter plusieurs versions de micrologiciel.
Comment corriger ?
- Téléchargez le micrologiciel 2.90(xxx.3)C0 du modèle exact depuis la bibliothèque de téléchargements de Zyxel. Le suffixe propre au modèle compte : un GS1900-8 utilise AAHH, un GS1900-24 utilise AAHL, et ainsi de suite. L'avis du 3 novembre renvoie au tableau des modèles et à l'annonce de version.
- Dans le configurateur web, ouvrez Maintenance > Firmware Upgrade, choisissez HTTP, sélectionnez le fichier
.bixdu modèle et appliquez-le. Conservez la sauvegarde de configuration prise avant la mise à jour. - Après le redémarrage, revenez à Getting Started et vérifiez que la Firmware Version affiche la version
.3)C0. - Corrigez chaque modèle listé, pas seulement celui qui fait face à Internet. L'exploit demande la joignabilité de l'interface d'administration, et un VLAN d'administration plat offre cette joignabilité après n'importe quelle compromission.
Aucune solution de contournement du fournisseur ne ferme la faille. Si aucune fenêtre de maintenance n'est disponible, réduisez l'exposition en attendant :
- Placez l'interface d'administration dans un VLAN d'administration dédié.
- Limitez-y l'accès par des règles de pare-feu qui n'autorisent que les hôtes d'administration connus.
- Désactivez l'administration WAN et l'administration distante lorsque l'appareil propose ces options.
- Surveillez les changements de configuration et les redémarrages inattendus du commutateur.
Ces mesures réduisent seulement qui peut joindre le service vulnérable. Elles ne corrigent pas l'absence de contrôles de limites, et Zyxel n'a publié aucune configuration qui rende l'analyseur sûr. Un commutateur qui reste joignable reste exploitable.
Quelle est la cause racine ?
dispatcher.cgi est le programme CGI derrière les pages de configuration web du commutateur. Il s'exécute sous le serveur web Boa et analyse le corps d'une requête HTTP POST dans un tampon global nommé reqParameters. Le tampon fait 0x23000 octets, divisés en 140 emplacements de 1024 octets. Un second global, count, enregistre le nombre de paramètres analysés.
Binarly a décompilé le micrologiciel 2.90(AAHH.1)C0 et publié la boucle vulnérable. La copie n'a aucun contrôle de longueur et le compteur n'a aucune borne supérieure :
for ( pos = strchr(src, '&'); pos != nullptr; pos = strchr(pos + 1, '&') )
{
dest = &reqParameters[1024 * count];
memcpy(dest, src, pos - src);
dest[pos - src] = 0;
v10 = strchr(dest, '=');
if ( v10 != nullptr )
{
if ( v10[1] == '&' )
dest[512] = 0;
else
urlDecode(dest + 512, v10 + 1);
*v10 = 0;
}
src = pos + 1;
++count;
}
src est le corps de la requête et pos marque le prochain &. Pour chaque champ, la boucle calcule &reqParameters[1024 * count], copie tout jusqu'au séparateur et incrémente count. Un champ de plus de 1024 octets déborde de son emplacement. Rien ne vérifie que count reste sous 140.
Les deux globaux sont voisins dans la section .bss. La liste IDA de Binarly montre la disposition :
.bss:10003BC0 reqParameters: .space 0x23000
.bss:10026BC0 count: .space 4
Le 140e champ déclenche le débordement. Lorsque count vaut 139, la copie commence au dernier emplacement, reqParameters[1024 * 139], et un champ de 1028 octets écrit quatre octets après la fin du tampon. Ces quatre octets sont count. Un attaquant qui fournit une valeur 32 bits à cet endroit remplace le compteur de paramètres par un nombre arbitraire.
Après la boucle, un second bloc traite le dernier champ, qui n'a pas de & final. Il réutilise le count corrompu :
if ( -src < strlen(src) )
{
dest = &reqParameters[1024 * count];
len = strlen(src);
memcpy(dest, src, len);
dest[strlen(src)] = 0;
...
++count;
}
count est multiplié par 1024 dans une expression signée de 32 bits. Une valeur comme 0x013bffff fait déborder le produit vers un décalage négatif, et dest pointe avant reqParameters au lieu de l'intérieur. L'écriture atterrit dans la table des décalages globaux (GOT) du processus, la table des adresses de fonctions résolues. L'exploit choisit l'entrée de strcmp.
Le programme appelle ensuite web_util_paramVal_ret, qui parcourt le tableau de paramètres avec strcmp(reqParameters, param). Le premier paramètre, contrôlé par l'attaquant, est la commande à exécuter. Avec l'entrée strcmp remplacée par l'adresse de system, la comparaison devient system("id") et s'exécute avec les privilèges du processus CGI, que Binarly a validés comme root.
Un second mode d'exploit corrompt les registres sauvegardés et l'adresse de retour au lieu de la GOT. Il revient par un gadget de l'uClibc de l'appareil pour appeler system. Les deux modes corrompent le même compteur par la même copie non contrôlée. L'exploit capturé contient des adresses codées en dur pour les micrologiciels de 2.10 à 2.90 et cible d'abord le GS1900-24.
Comment la faille est-elle exploitée ?
- L'attaquant envoie une requête HTTP POST à
/cgi-bin/dispatcher.cgi. Le corps capturé contient un premier champ avec la commande, 139 séparateurs&, un champ de 1024 octets suivi immédiatement d'une valeur de compteur 32 bits, un séparateur et l'adresse que l'attaquant veut placer dans la GOT. web_util_initParaPairscopie chaque champ dansreqParameterssans contrôle de longueur. Le 140e champ déborde du dernier emplacement et écrasecountavec la valeur 32 bits.- Le bloc hors boucle calcule
&reqParameters[1024 * count]avec le compteur corrompu. La multiplication signée déborde, et la destination pointe avant le tampon global, sur l'entrée de la GOT choisie. - Le même bloc copie le dernier champ à cette adresse, en remplaçant l'entrée
strcmppar l'adresse desystem. web_util_paramVal_retappellestrcmpsur le premier paramètre. L'appel atteint désormaissystem, et le premier paramètre s'exécute en tant que root.
La requête n'a besoin d'aucune session, d'aucun identifiant et d'aucune interaction utilisateur. Binarly a testé l'exploit sur du matériel réel et sur des micrologiciels émulés, et a publié la disposition de la requête et les deux modes. L'échantillon capturé est un script Python obscurci avec PyArmor ; GreyNoise a désobfusqué le même script et retrouvé la même corruption du compteur de paramètres.
Comment se déroule l'attaque ?
Une seule requête HTTP non authentifiée corrompt le compteur de paramètres, redirige un pointeur de fonction dans la GOT et transforme la comparaison suivante en commande root.
Que peut faire un attaquant ?
Un attaquant qui joint l'interface web peut exécuter des commandes du système d'exploitation en tant que root sur le commutateur. Binarly a démontré l'exécution avec system("id") dans le processus CGI et validé le contexte de travail comme root. L'avis de Zyxel indique que la faille peut exécuter des commandes système par une requête HTTP forgée.
L'impact comprend la lecture et la modification de la configuration du commutateur. GreyNoise a observé un acteur extraire des données de configuration, des empreintes de mots de passe root et des informations réseau de 996 commutateurs dans 48 pays. Ces enregistrements donnent à un attaquant la topologie d'administration et une empreinte de mot de passe à attaquer hors ligne.
L'enregistrement CVE de Zyxel attribue un CVSS v3.1 de 8,8, CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H, car il traite l'attaque comme adjacente au réseau. Binarly évalue 9,8 Critical, CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H, car le service d'administration est en HTTP et toute route vers lui suffit.
Les conditions sont les mêmes que dans « Suis-je concerné ? » : joignabilité réseau de l'interface d'administration, aucune authentification et aucune interaction utilisateur. Zyxel décrit l'attaquant comme présent sur le réseau local et adjacent. Binarly évalue le vecteur d'attaque comme réseau, car le service est en HTTP et un routeur ou une règle NAT peut l'exposer au-delà du segment local.
Cet article sépare deux affirmations d'exploitation. GreyNoise a attribué l'activité d'août à CVE-2026-7273, la faille corrigée par Zyxel en juin. Binarly a constaté que l'exploit capturé cible la faille de l'analyseur ensuite nommée CVE-2026-107441.
Binarly a aussi constaté que les dix versions corrigées en juin restaient vulnérables. L'accès de l'acteur et le vol de données sont établis par GreyNoise. L'étiquette CVE visée par l'acteur importe moins que le fait que le correctif de juin n'a pas fermé le chemin.
Pourquoi le correctif fonctionne-t-il ?
Le correctif de novembre vérifie le compteur avant de calculer la destination et remplace la copie non bornée par un utilitaire borné. Binarly a publié la nouvelle boucle :
for ( pos = strchr(queries, '&'); pos != nullptr; pos = strchr(pos + 1, '&') )
{
dest = &reqParameters[1024 * counter];
if ( counter >= 140 ) // the global counter is checked before the copy
return 0;
web_util_paramCopy(&reqParameters[1024 * counter], 512, src, pos - src);
...
++counter;
}
Le test counter >= 140 s'exécute avant la copie, donc le 140e champ ne peut plus atteindre l'emplacement qui contient count. web_util_paramCopy limite chaque champ à 511 octets, donc un champ ne peut pas non plus déborder de son emplacement de 1024 octets. Les deux changements ferment les deux moitiés de la faille : la corruption du compteur et la copie non bornée.
Le correctif de juin ne le faisait pas. Il ajoutait ces contrôles :
if ( ++counter == 140 )
return 0;
...
if ( counter >= 141 )
counter = 140;
Le premier contrôle s'exécute après la copie qui corrompt counter. Une fois la valeur écrasée, le test d'égalité échoue et le bloc hors boucle s'exécute toujours. Le second contrôle ne fait que réinitialiser un compteur déjà utilisé pour calculer une destination. Binarly a testé les dix versions corrigées en juin le 28 septembre 2026 et les a toutes trouvées exploitables.
L'avis de Binarly recommande aussi d'activer Full RELRO pour rendre la GOT en lecture seule. L'avis de Zyxel ne précise pas si les nouvelles versions l'activent. Le correctif ferme la primitive d'écriture démontrée. Il ne rend pas la GOT immuable, donc traitez Full RELRO comme une défense en profondeur et non comme un substitut à la mise à jour.
Comment vérifier si j'ai été compromis ?
Le commutateur peut ne pas journaliser le corps de la requête POST qui déclenche la faille. Commencez par les logiciels malveillants et l'infrastructure de commande et contrôle, puis examinez ce que le commutateur contenait.
Binarly a publié les empreintes de la porte dérobée JITTERLY et du rootkit SIXZUT qu'elle dépose. Les valeurs SHA-256 de son avis et de son article sont :
- JITTERLY :
0f6e757e82c4d91df5bd249f775b9970b59dee42cc0dfe40f879d77fc16821c6,663a8088faca8e126a11648f5671fcf4eaf96435e10daf63a1d1b17d8385154c,82d072ab03d90c0131b06a576eadf2c986a51f0de986d50db4e49be01bf125cb. - SIXZUT :
295133156b6a7d95b9c92f832f49e35235f1fbd3906e75c9202ef4cd65d1018c,64677002011bc2e4bc642a4154a20fdb95620ebd0144b98fc60f917901ec8b92,728810b07e911b235f6450e784391e39f68819a0a5d209662162916ffea25146.
L'acteur a utilisé le domaine 981666[.]xyz avec ces hôtes :
p1.981666[.]xyz,p2.981666[.]xyz,p3.981666[.]xyz.s0.981666[.]xyzàs9.981666[.]xyz.
L'analyse de Binarly liste ces adresses IP : 104.223.65[.]148, 203.88.123[.]148, 104.225.153[.]141 et 166.88.227[.]181. Le logiciel malveillant utilisait les ports TCP 443, 6443, 8080, 8082, 5432 et 6379. Binarly a publié des règles YARA pour JITTERLY et SIXZUT dans son article.
Si un commutateur était joignable et non corrigé, supposez que la configuration et l'empreinte du mot de passe root ont été prises. Changez le mot de passe de l'administrateur local, les chaînes de communauté SNMP et tout secret RADIUS, TACACS+ ou VPN stocké dans la configuration.
Examinez les journaux du commutateur pour les changements de configuration, les nouveaux utilisateurs locaux et les redémarrages inattendus. Une tentative échouée peut ne laisser aucune trace sur l'appareil, donc l'absence d'entrée de journal ne prouve pas que le commutateur est intact.
Chronologie
Le premier correctif est sorti 140 jours avant l'avis qui l'a remplacé, et Binarly a trouvé les dix versions corrigées encore vulnérables 104 jours après ce premier correctif.
- 2026-06-16 : Zyxel publie l'avis CVE-2026-7273 et les versions corrigées 2.90(xxx.2)C0.
- 2026-08-17 : Vers cette date, GreyNoise observe un acteur extraire des données de 996 commutateurs GS1900 dans 48 pays.
- 2026-09-21 : La CISA ajoute CVE-2026-7273 au catalogue Known Exploited Vulnerabilities.
- 2026-09-28 : Binarly confirme que les dix versions annoncées comme correctifs de CVE-2026-7273 restent vulnérables.
- 2026-09-29 : Binarly notifie l'équipe de sécurité produit de Zyxel.
- 2026-10-11 : Zyxel confirme la nouvelle vulnérabilité et réserve CVE-2026-107441.
- 2026-10-22 : Zyxel publie le micrologiciel 2.90(xxx.3)C0 pour les dix modèles.
- 2026-11-03 : Zyxel publie son avis, Binarly publie BRLY-2026-057 et l'enregistrement CVE est publié.
FAQ
La mise à jour CVE-2026-7273 protège-t-elle un commutateur GS1900 ?
Non. La mise à jour 2.90(xxx.2)C0 du 16 juin 2026 ajoutait des contrôles après la copie vulnérable, et Binarly a trouvé les dix versions corrigées encore exploitables le 28 septembre 2026. Un commutateur a besoin de la version 2.90(xxx.3)C0.
CVE-2026-107441 figure-t-elle dans le catalogue KEV de la CISA ?
Non, au 4 novembre 2026, la nouvelle CVE ne figure pas dans le catalogue Known Exploited Vulnerabilities. L'ancienne CVE-2026-7273 y figure depuis le 21 septembre 2026, avec une échéance fédérale au 24 septembre 2026.
Quels modèles GS1900 sont concernés ?
Les dix modèles listés par Zyxel sont concernés en version 2.90(xxx.2)C0 et antérieure. Zyxel indique que les produits encore commercialisés qui n'apparaissent pas dans son avis ne sont pas concernés. Vérifiez donc le couple modèle et micrologiciel plutôt que le nom de la famille.
Les attaques en conditions réelles ont-elles utilisé CVE-2026-107441 ?
GreyNoise a rattaché l'activité d'août à CVE-2026-7273. Binarly a constaté que l'exploit capturé cible la faille du compteur de paramètres ensuite nommée CVE-2026-107441, et que le correctif de juin ne la bloquait pas. Les deux étiquettes décrivent le même analyseur, et le micrologiciel de novembre est la première version qui ferme le chemin démontré par Binarly.
Puis-je bloquer l'attaque en restreignant l'interface d'administration ?
Restreindre l'interface réduit qui peut joindre le service vulnérable, mais ne corrige pas l'absence de contrôles de limites. Zyxel n'a publié aucune solution de contournement qui rende l'analyseur sûr. Un commutateur qui reste joignable sur une interface reste exploitable, donc planifiez la mise à jour.
Le correctif est-il complet ?
Le correctif de novembre vérifie le compteur avant la copie et borne chaque champ à 511 octets, ce qui ferme les deux primitives d'écriture démontrées par Binarly. Binarly recommande aussi Full RELRO pour empêcher l'écrasement de la GOT. L'avis de Zyxel ne précise pas si les nouvelles versions l'activent, donc appliquez le micrologiciel et traitez RELRO comme un contrôle supplémentaire.
Trouver les commutateurs Zyxel GS1900 exposés avec Ostorlab
La découverte de surface d'attaque d'Ostorlab inventorie les interfaces d'administration exposées à Internet, y compris les équipements réseau, pour savoir quels commutateurs corriger en premier. Utilisez-la pour trouver les pages d'administration GS1900 que votre organisation expose avant un attaquant.
Références
- Zyxel, « Zyxel security advisory for out-of-bounds write vulnerability in GS1900 series switches » (3 novembre 2026). https://www.zyxel.com/global/en/support/security-advisories/zyxel-security-advisory-for-out-of-bounds-write-vulnerability-in-gs1900-series-switches-11-03-2026 (vérifié le 4 novembre 2026)
- Zyxel, « Zyxel security advisory for stack-based buffer overflow vulnerability in GS1900 series switches » (16 juin 2026). https://www.zyxel.com/global/en/support/security-advisories/zyxel-security-advisory-for-stack-based-buffer-overflow-vulnerability-in-gs1900-series-switches-06-16-2026 (vérifié le 4 novembre 2026)
- Binarly, « Pre-Auth RCE in Zyxel GS1900 Exploited in the Wild as a Zero-Day » (3 novembre 2026). https://www.binarly.io/blog/zyxel-gs1900-rce-cve-2026-107441 (vérifié le 4 novembre 2026)
- Binarly, « BRLY-2026-057: Out-of-bounds write vulnerability in Zyxel GS1900 switches » (3 novembre 2026). https://www.binarly.io/advisories/brly-2026-057 (vérifié le 4 novembre 2026)
- GreyNoise, « Open Season on Kapibala: Attacker Steals Over 18,000 Government Records Through WordPress Exploitation » (28 septembre 2026), section sur la campagne contre les ZyXEL GS1900 : 996 commutateurs dans 48 pays, attribuée à CVE-2026-7273. https://www.greynoise.io/blog/open-season-on-kapibala-attacker-steals-government-records-wordpress-exploitation (vérifié le 4 novembre 2026)
- CVE Program, « CVE-2026-107441 » (publié le 3 novembre 2026). https://www.cve.org/CVERecord?id=CVE-2026-107441 (vérifié le 4 novembre 2026)
- CVE Program, « CVE-2026-7273 » (publié le 16 juin 2026). https://www.cve.org/CVERecord?id=CVE-2026-7273 (vérifié le 4 novembre 2026)
- Zyxel, « GS1900 Series User's Guide, V2.90 edition 2 » (pages 61 et 242). https://download.zyxel.com/GS1900-8/user_guide/GS1900-8_V2.90_Ed2.pdf (vérifié le 4 novembre 2026)
- CISA, « Known Exploited Vulnerabilities Catalog » (flux vérifié le 4 novembre 2026). https://www.cisa.gov/known-exploited-vulnerabilities-catalog (vérifié le 4 novembre 2026)