Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2026-76070 — Recherche originale et PoC non destructif pour un débordement de tampon de pile du mot de passe décodé en Base64, avant authentification, dans login.cgi de Netis NC63. | Kitploit
Outils/GitHubGitHub/ozcanpng/cve-2026-76070
Sécurité des Systèmes EmbarquésSécurité IoTAnalyse des VulnérabilitésExploitationRétro-ingénierieAnalyse de MicrologicielExploitation de Binaires
GitHubozcanpng/cve-2026-76070

CVE-2026-76070

Recherche originale et PoC non destructif pour un débordement de tampon de pile du mot de passe décodé en Base64, avant authentification, dans login.cgi de Netis NC63.

Voir le dépôt
1il y a 4 joursPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

CVE-2026-76070 : Débordement de tampon de pile non authentifié avant authentification via mot de passe décodé en Base64 dans login.cgi du Netis NC63, conduisant à une exécution de code à distance (RCE)

Chercheur : Özcan Ersan (@ozcanpng)

État de la divulgation

  • CVE : CVE-2026-76070
  • Vendeur : Netis Systems Co., Ltd.
  • Produit : Routeur Netis NC63 Wireless AC1200
  • Micrologiciel testé : NC63_V3.0.0.3327
  • Composant concerné : /bin/netis.cgi
  • Point d'accès : POST /cgi-bin/login.cgi
  • Paramètre : password encodé en Base64
  • Authentification : aucune ; le décodage dangereux a lieu avant la comparaison des identifiants
  • Architecture : MIPS32r2 little-endian, ABI o32, uClibc
  • Classe de vulnérabilité : débordement de tampon de pile avec contrôle de l'adresse de retour sauvegardée
  • Validation : CGI de production à hachage original dans un environnement d'exécution QEMU en mode utilisateur isolé
  • État de l'enregistrement CVE à la préparation : assigné ; détails de l'enregistrement CNA en attente de saisie

Résumé exécutif

Le gestionnaire de connexion public du micrologiciel Netis NC63 V3.0.0.3327 récupère le paramètre password contrôlé par l'attaquant et le décode avec la routine Base64 personnalisée FUN_00402bd4. L'appelant fournit un tampon de pile local de 64 octets mais ne transmet pas sa capacité au décodeur. Le décodeur déduit son travail de l'entrée encodée et écrit des octets décodés sans vérifier la fin de la destination.

L'adresse de retour MIPS sauvegardée se trouve à 136 octets du début du tampon décodé. Des tests dynamiques contre le CGI de production à hachage original ont confirmé :

  1. qu'un motif de 140 octets B décodés produit un défaut à 0x42424242 ;
  2. que le remplacement du ra sauvegardé par 0x0041a2e0 provoque une seconde entrée observée dans le gestionnaire de connexion, prouvant le contrôle du compteur ordinal ; et
  3. qu'un test isolé d'observation uniquement atteint l'appel direct à system() du binaire d'origine avec une valeur a0 MIPS choisie par l'attaquant. Le /bin/sh de remplacement a journalisé /bin/sh -c NC63_RCE_PROOF et n'a exécuté aucune commande.

La preuve de concept (PoC) publique de ce dépôt s'arrête délibérément à un motif de plantage. Elle ne contient ni chaîne de retour, ni shellcode, ni commande, ni shell inverse, ni persistance.

Intégrité de l'artefact concerné

root@kitploit:~
193f6a5e2ce65972b1805bf076f8d3521379a8441c8aaeb5ad0ba174bbee0792  netis_NC63_V3.0.0.3327.bin
23faa747b7d2f067aa5431bcc227ceca97a7977cf3e7c372f715cbba57f9209b  squashfs-root/bin/boa
eb298774c27070dc595fefcabb4e8c12a46cb5f4fd08f91c3ca92282c3a289a2  squashfs-root/bin/netis.cgi

La copie de /bin/netis.cgi testée dynamiquement a la même empreinte SHA-256 que l'exécutable extrait du vendeur.

Hachages d'origine et d'exécution

Surface d'attaque et état de l'authentification

Le frontal du vendeur envoie le mot de passe au point d'accès public encodé en Base64 :

root@kitploit:~
obj.password = base64encode(utf16to8(password));
request({
    url: "/cgi-bin/login.cgi",
    data: obj
});

Le champ HTML utilise maxlength="63", mais il ne s'agit que d'une restriction côté navigateur. Un client HTTP direct peut soumettre une valeur encodée plus grande.

Requête frontale et limite côté client uniquement

login.cgi est nécessairement accessible avant l'authentification. Le décodage dangereux a lieu avant que le mot de passe décodé ne soit comparé au mot de passe administrateur configuré. Aucune session valide, aucun en-tête Cookie, ni en-tête Authorization, ni mot de passe correct n'est requis.

Traçage de la source au puits

root@kitploit:~
Client HTTP non authentifié
  |
  | POST /cgi-bin/login.cgi
  | password=<Base64 contrôlée par l'attaquant>
  v
/bin/netis.cgi : FUN_0041a2e0
  |
  | get_request_param("password")
  v
FUN_00402bd4(tampon_pile_décodé, mot_de_passe_encodé)
  |
  | aucun argument de capacité de destination
  | la sortie décodée dépasse 64 octets
  v
s8 sauvegardé au décalage décodé 132
ra sauvegardé au décalage décodé 136
  |
  v
PC MIPS choisi par l'attaquant

Code vulnérable

Pseudo-code dérivé de Ghidra, avec des noms normalisés pour la lisibilité :

root@kitploit:~
int login_cgi(void *request)
{
    char decoded[64];
    char stored[68];
    char *password;

    memset(decoded, 0, 64);
    memset(stored, 0, 64);
    password = get_request_param(request, "password");
    if (password != NULL)
        FUN_00402bd4(decoded, password); /* aucun argument de capacité */

    apmib_get(0x15e, stored);
    if (strcmp(decoded, stored) == 0)
        printf("[\"SUCCESS\"]");
    else {
        system("echo 0 >/tmp/boa_auth");
        printf("[\"%d\"]", 0x15);
    }
    return 0;
}

Gestionnaire de connexion vulnérable

Le décodeur à FUN_00402bd4 ne reçoit que des pointeurs de destination et de source. Sa boucle avance le pointeur de destination et stocke jusqu'à trois octets décodés pour chaque groupe de quatre symboles Base64. Aucune comparaison ne vérifie la destination par rapport à decoded + 64.

Boucle d'écriture du décodeur Base64 personnalisé

Base64 est la transformation d'entrée, pas le défaut sous-jacent. La cause racine est l'inadéquation entre la longueur décodée contrôlée par l'attaquant et une destination de taille fixe dont la capacité n'est jamais appliquée. Pour une entrée avec rembourrage ordinaire, quatre caractères encodés représentent jusqu'à trois octets décodés ; les vérifications côté serveur doivent donc calculer et valider la taille décodée avant d'écrire.

Analyse de la corruption de la pile

FUN_0041a2e0 commence à 0x0041a2e0 et crée une trame de 0xa8 octets :

root@kitploit:~
0041a2e0  addiu sp,sp,-168
0041a2e4  sw    ra,164(sp)
0041a2e8  sw    s8,160(sp)
0041a2ec  move  s8,sp

La destination décodée commence à s8+0x1c ; s8 sauvegardé et ra sauvegardé sont à s8+0xa0 et s8+0xa4 :

root@kitploit:~
decoded[64]  s8+0x1c   décalage décodé 0
s8 sauvegardé  s8+0xa0  décalage décodé 132
ra sauvegardé  s8+0xa4  décalage décodé 136

La distance exacte de l'adresse de retour est 0xa4 - 0x1c = 0x88, soit 136 octets.

Trame de pile et décalage du ra sauvegardé

Vérification dynamique

Écrasement de l'adresse de retour sauvegardée

Un motif de 140 octets B décodés a remplacé l'adresse de retour sauvegardée de quatre octets :

root@kitploit:~
--- SIGSEGV {si_signo=SIGSEGV, si_code=1, si_addr=0x42424242} ---
qemu: uncaught target signal 11 (Segmentation fault)

Défaut à l'adresse de retour choisie par l'attaquant

Contrôle du compteur ordinal

Une entrée distincte de 140 octets a défini ra sauvegardé à 0x0041a2e0. Le traçage CPU de QEMU a enregistré une première entrée ordinaire du gestionnaire suivie d'une seconde entrée avec s8=0x41414141 et ra=0x0041a2e0.

Seconde entrée contrôlée du gestionnaire

Limite de commande pour observation uniquement

Le binaire d'origine contient un jal system direct à 0x0041a3cc. Lors de la validation isolée privée, des instructions existantes à base fixe ont chargé un marqueur dans a0 et ont atteint cet appel. Un programme d'observation statique a été monté sur /bin/sh ; il a journalisé les arguments de l'interpréteur de commandes et n'a rien exécuté :

root@kitploit:~
argv[0]=</bin/sh>
argv[1]=<-c>
argv[2]=<NC63_RCE_PROOF>
CONTROLLED_MARKER_REACHED
PASS: a0 contrôlé par l'attaquant a atteint system() et argv de /bin/sh.
PASS: le garde a journalisé la requête et n'a exécuté aucune commande.

Cela démontre une primitive RCE dans le chemin de code de production isolé. Cela n'établit pas une fiabilité d'exploitation identique sur un routeur physique avec son noyau déployé et sa configuration de randomisation de la pile.

Contexte des privilèges et du durcissement binaire

La configuration Boa d'origine spécifie User root, Group root et un chemin CGI contenant /bin et /web/cgi-bin. L'exécutable de production a une base fixe (0x00400000), ne possède ni canari de pile ni RELRO, et déclare une pile GNU exécutable avec des segments RWX.

Configuration des privilèges Boa de production

État du durcissement binaire

PoC publique sécurisée

Le script inclus est en mode essai à blanc (dry-run) par défaut et ne génère qu'un corps de formulaire Base64 contenant 140 octets B après décodage :

root@kitploit:~
python3 poc/poc.py

L'envoi nécessite une cible autorisée explicite et --send :

root@kitploit:~
python3 poc/poc.py --target http://192.168.1.1 --send

L'envoi du motif peut faire planter le processus CGI. Utilisez-le uniquement dans un environnement autorisé et jetable. La PoC n'implémente pas la chaîne de validation RCE privée.

Impact

Une exploitation réussie peut exécuter du code ou des commandes choisis par l'attaquant dans le contexte de gestion du routeur. Dans la configuration Boa d'origine, ce contexte s'exécute en tant que root. Les conséquences potentielles incluent la divulgation de configuration et de secrets, la manipulation du DNS, du pare-feu et du routage, la redirection du trafic, l'interruption de service et la compromission totale de l'appareil.

Correctifs

  1. Remplacez le décodeur personnalisé par une API qui accepte la capacité de la destination.
  2. Rejetez toute entrée dont la longueur décodée calculée dépasse 63 octets, en réservant de l'espace pour un terminateur.
  3. Validez la longueur et la syntaxe Base64 côté serveur avant de décoder.
  4. Auditez chaque appelant de FUN_00402bd4.
  5. Recompilez avec des canaris de pile, PIE, NX et RELRO.
  6. Exécutez les processus CGI avec le moindre privilège.

Index des preuves

Voir evidence/README.md pour les captures d'écran et le mappage des traces. Les extraits Ghidra normalisés se trouvent dans attachments/decompiled-functions/.

Chronologie de divulgation

  • 2026-08-16 : découverte et validation isolée du binaire de production terminées.
  • Août 2026 : signalement à VulnCheck.
  • 2026-08-20 : VulnCheck a assigné CVE-2026-76070 et autorisé la divulgation publique.
  • 2026-08-20 : publication du dossier de divulgation publique.

Références

  • CVE-2026-76070
  • VulnCheck
  • Page d'assistance Netis NC63
  • CVE-2026-73673

Aucun routeur physique n'a été flashé. Aucune commande shell réelle, aucun shell inverse, aucune persistance, aucune connexion externe, aucun vol d'identifiants ni aucune opération destructive du micrologiciel n'a été utilisé.

Télécharger l’outil