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
Outils/GitHubGitHub/diegslva/cve-2010-4221-lab
Frameworks d'ExploitationAnalyse des VulnérabilitésExploitationRétro-ingénierieTests d'IntrusionApprentissage et ÉducationExploitation de BinairesLabs et Pratique
GitHubdiegslva/cve-2010-4221-lab

cve-2010-4221-lab

De l'exploit à l'exécution de code : exploit artisanal pour CVE-2010-4221 (débordement de pile TELNET IAC dans ProFTPD), avec le parcours complet guidé par les échecs documenté

Voir le dépôt
il y a 12h 14mPas 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-2010-4221 — Débordement de pile TELNET IAC dans ProFTPD : du patch au RCE

Un laboratoire entièrement reproductible et un exploit écrit à la main, basé sur des sockets brutes, pour CVE-2010-4221 — le débordement de pile pré-authentification dans pr_netio_telnet_gets() de ProFTPD — conçu comme exercice d'apprentissage en recherche de vulnérabilités et développement d'exploits.

Chaque échec est documenté. Le chemin idéal est un mensonge ; les détours sont la leçon.


Avis légal et éthique — à lire en premier

Ce dépôt est un artefact pédagogique. Il existe pour que les personnes qui ne peuvent pas se permettre un mentor ou une formation puissent apprendre comment un exploit de corruption mémoire naît réellement : d'un patch, à travers les échecs, jusqu'à une preuve de concept fonctionnelle dans un laboratoire qui vous appartient.

Le travail Red Team — la sécurité offensive réelle et professionnelle — se définit par un seul mot : autorisation. Tout ce qu'un professionnel fait se déroule dans le cadre d'un accord écrit : un document signé de règles d'engagement qui nomme le périmètre, les cibles, les techniques autorisées, la fenêtre temporelle et les personnes qui l'ont approuvé. Sans ce papier, les mêmes frappes clavier ne sont pas une profession — ce sont un crime dans pratiquement toutes les juridictions de la planète.

Voici donc le contrat pour ce dépôt, non négociable :

  • Exécutez ceci uniquement contre le laboratoire Docker fourni ou des systèmes qui vous appartiennent.
  • Jamais contre quoi que ce soit sans autorisation écrite et explicite.
  • Si vous apprenez : bienvenue, ceci a été construit pour vous.
  • Si vous cherchez une arme à utiliser contre autrui : fermez cet onglet. Cette faille date de 2010 ; elle ne vous apportera qu'un casier judiciaire.
  • Le métier vaut la peine d'être appris. Le métier ne vaut quelque chose qu'avec la discipline qui l'accompagne.


    La faille

    ProFTPD parle les séquences d'échappement TELNET sur le canal de contrôle FTP. En TELNET, 0xFF (IAC, « Interpret As Command ») est l'octet d'échappement ; un 0xFF littéral est envoyé comme 0xFF 0xFF.

    pr_netio_telnet_gets() copie les octets du client dans un buffer de pile (char buf[PR_DEFAULT_CMD_BUFSZ+1] de pr_cmd_read, 4104 octets avec MAXPATHLEN=4096 de glibc), en suivant l'espace restant dans buflen — un size_t, non signé.

    Le chemin vulnérable (1.3.3a, netio.c) :

    root@kitploit:~
    case TELNET_IAC:
      switch (cp) {
        ...
        default:
          *bp++ = TELNET_IAC;   // écriture #1
          buflen--;             // décrément #1
          telnet_mode = 0;
          break;
      }
      break;
    ...
    *bp++ = cp;                 // écriture #2
    buflen--;                   // décrément #2  <-- aucun contrôle entre les deux
    

    Deux écritures, deux décréments, aucun contrôle de zéro entre eux. Lorsque buflen vaut exactement 1, la paire le décrémente à 0, puis le fait passer sous zéro jusqu'à SIZE_MAX (18 quintillions). La boucle croit désormais que le buffer est infini et continue d'écrire des octets contrôlés par l'attaquant vers le haut de la pile — par-dessus les registres sauvegardés, le RBP sauvegardé et l'adresse de retour.

    Pré-authentification. La fonction s'exécute avant que USER/PASS ne soient jamais traités.

    Le patch

    Le correctif (commit 3cc69b8388, « Bug#3521 - Telnet IAC processing stack overflow », publié dans la 1.3.3c) fait douze lignes. Toute la frontière de sécurité est :

    root@kitploit:~
    if (buflen == 0) {
      break;
    }
    

    Voir patch.diff. Lire le patch vous indique où se trouvait la blessure — c'est cela, la compétence.

    Le laboratoire

    Le Dockerfile compile ProFTPD 1.3.3a à partir des sources historiques du snapshot Debian, délibérément non sécurisé (voilà à quoi ressemblait 2010) :

    • -fno-stack-protector — pas de canari
    • -z execstack — pile exécutable (pas de NX)
    • -no-pie — adresses binaires fixes
    • exécution sous gdb, qui désactive l'ASLR par défaut → pile déterministe
    root@kitploit:~
    docker build -t proftpd-133a .
    docker rm -f lab133 2>/dev/null
    docker run -d --name lab133 --cap-add SYS_PTRACE \
      --security-opt seccomp=unconfined -p 127.0.0.1:2122:21 \
      proftpd-133a sh -c 'gdb -batch -ex "set follow-fork-mode child" \
      -ex "run" -ex "continue" --args /usr/local/sbin/proftpd -n -d1 \
      > /tmp/gdb.txt 2>&1; sleep 600'
    python3 exploit.py
    

    Sortie attendue :

    root@kitploit:~
    [S] 220 ProFTPD 1.3.3a Server (lab-iac) ...
    [S] THE SERVER SAID: b'PWNED!!PWNED!!'
    

    (Le shellcode écrit sur les descripteurs 0, 1 et 2 car nous ne voulions pas dépendre de la connaissance de celui qui porte le canal de contrôle — deux d'entre eux répondent.)

    L'architecture de l'exploit

    root@kitploit:~
    "SITE " + NOP sled + shellcode + [inondation \xff\xff] + padding + [ret] + "\n"
     ^^^^^^^^^^^^^^^^^^^^                             ^^^^
     le shellcode vit DANS le buffer                la queue du débordement ne
     de commande — la région que personne            délivre QU'UNE adresse
     ne touche
    
    1. « SITE » maintient l'analyseur FTP en vie — la commande se traite proprement.
    2. Le shellcode est le contenu de la commande. Le buffer est l'endroit le plus sûr de la pile : après la lecture, seul buf[4102] est touché (NUL de troncature). Tout ce qui se trouve sous les variables locales vivantes du cadre est calme.
    3. L'inondation IAC conduit buflen au passage sous zéro (voir « Le voyage » pour le problème de parité).
    4. L'emplacement ret (buf + 4152) reçoit l'adresse du milieu du NOP sled. Lorsque pr_cmd_read atteint return 0 après l'analyse, le CPU atterrit dans le sled et glisse dans le shellcode.

    Cette architecture inversée — payload d'abord, inondation ensuite, adresse en dernier — a été validée contre le module Metasploit canonique (proftp_telnet_iac), qui utilise la même disposition. Leurs cibles avaient NX, ils avaient donc besoin d'une chaîne ROP avec un « quadruple déréférencement » du pointeur res ; notre laboratoire a une pile exécutable, donc un simple retour direct suffit.

    Le voyage (le véritable intérêt de ce dépôt)

    L'exploit final fait 60 lignes. Ce qu'il a coûté :

    1. Inondation \xff aveugle → rien. Le serveur a poliment fermé la session. Cause racine : buflen commence à 4102 (PAIR) et chaque paire IAC décrémente de 2 — il atterrit proprement sur 0, jamais sur 1. Le passage sous zéro nécessite une parité brisée. Leçon : lire la machine à états vaut mieux que d'arroser.

    2. Mauvaise taille de buffer. La première tentative calibrée supposait un buffer de 1024 octets. Le vrai fait MAXPATHLEN+8 = 4104 sous Linux/glibc. L'inondation s'est arrêtée 3 Ko avant la cible. Leçon : mesurez la cible, ne supposez pas la cible.

    3. Premier SIGSEGV. Le motif cyclique de Bruijn (Aa0Aa1...) a placé l' emplacement de retour à buf+4152, validé deux fois (calcul du cadre + décalage du motif). Leçon : le motif cyclique est un mètre ruban, pas un exploit.

    4. Contrôle de RIP. Régler l'emplacement à 0x4141414141414141 a fait planter l'instruction ret elle-même — x86-64 refuse les adresses non canoniques, et le défaut atterrit sur ret, avec notre valeur en attente dans la backtrace. Leçon : un crash sur ret avec votre valeur dans le cadre = contrôle.

    5. Shellcode au-dessus de l'emplacement ret → écrasé. 8 octets écrasés par un pointeur de tas (0x4d7838 — identifié plus tard comme l'allocation du pool cmd_rec). Les cadres de pile au-dessus de l'emplacement appartiennent à des fonctions qui continuent de travailler entre l'atterrissage et le détournement. Leçon : le débordement n'est pas la dernière écriture ; le programme continue de vivre sur la pile que vous venez de vandaliser.

    6. « Zone morte » sous l'emplacement → également griffonnée. Les propres variables locales de pr_cmd_read (cmd, buflen, cp) vivent juste là et continuent d'être stockées pendant l'analyse.

    7. Analyse médico-légale par point d'arrêt matériel. watch *(long*)ADDR dans gdb a transformé le mystère en caméra : chaque écriture à l'adresse écrasée, avec backtrace, dans l'ordre. Leçon : quand la question est « qui a écrit cette mémoire ? », la réponse est à une commande gdb.

    8. Lisez la référence, puis comprenez-la. Le module canonique a confirmé l'architecture inversée. Lire un autre exploit après avoir construit votre propre modèle mental est une étude ; avant, c'est de la copie.

    Leçons apprises

    • size_t ne devient jamais négatif — il devient gigantesque. Le passage sous zéro d'un compteur d'espace restant est un débordement de pile avec des étapes supplémentaires.
    • La parité est une arme. Lorsqu'une primitive décrémente de 2 en 2, vous contrôlez le passage sous zéro en contrôlant pair/impair, pas seulement la taille.
    • Les mauvais caractères sont une question de protocole. Notre shellcode évite \x0a (termine la lecture) et survit à \xff (échappement TELNET) par conception.
    • Les serveurs pré-fork pardonnent les crashs. L'enfant meurt, le parent continue d'accepter : tentatives infinies. L'ingénierie de fiabilité fait partie de l' exploit.
    • Mesurez et exploitez le même artefact. Une différence de 11 octets dans argv[0] (binaire de l'arborescence de compilation vs binaire installé) a décalé toute la pile de 0x40 et invalidé silencieusement un exploit parfait.
    • Le gestionnaire de signaux avoue. ProFTPD intercepte SIGSEGV et journalise « terminating (signal 11) » — la cible vous dit qu'elle est morte, même lorsque le noyau reste silencieux.

    Références

    • Commit du correctif : https://github.com/proftpd/proftpd/commit/3cc69b8388
    • CVE : https://nvd.nist.gov/vuln/detail/CVE-2010-4221
    • Module canonique : modules/exploits/linux/ftp/proftp_telnet_iac.rb (rapid7/metasploit-framework)
    • Laboratoire frère (bug logique, même démon) : CVE-2015-3306 mod_copy

    Auteur

    Construit par diegslva, apprenant en public — de « jamais écrit d'exploit » à RCE pré-authentification avec shellcode fait main, en une journée documentée. Si ce dépôt vous a appris quelque chose, transmettez-le.

    Télécharger l’outil