Skip to content
KitploitKITPLOIT
OutilsExploitsBlog
Log in
Soumettre
OutilsExploitsBlog
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-2018-6789 — Exploit pour CVE-2018-6789, un débordement de tampon de tas dans le décodage base64 d'Exim, permettant l'exécution de code à distance via le chevauchement de blocs et la manipulation de chaînes ACL. | Kitploit
Outils/GitHubGitHub/beraphin/cve-2018-6789
Analyse des VulnérabilitésExploitationCTFApprentissage et ÉducationExploitation de BinairesLabs et Pratique
GitHubberaphin/cve-2018-6789

CVE-2018-6789

Exploit pour CVE-2018-6789, un débordement de tampon de tas dans le décodage base64 d'Exim, permettant l'exécution de code à distance via le chevauchement de blocs et la manipulation de chaînes ACL.

Voir le dépôt
315il y a 6 ansPas 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-2018-6789

Configuration de l'environnement

Installer les dépendances

apt-get install gcc net-tools vim gdb python wget git make procps libpcre3-dev libdb-dev libxt-dev libxaw7-dev

Télécharger une ancienne version de exim

wget ftp://mirror.easyname.at/exim-ftp/exim/exim4/old/exim-4.89.tar.gz
tar -xvzf ./exim-4.89.tar.gz
cd ./exim-4.89
cp src/EDITME Local/Makefile
cp exim_monitor/EDITME Local/eximon.conf

Modifier ensuite Local/Makefile Pour plus de commodité, tous les répertoires pointent vers le répertoire courant

BIN_DIRECTORY=/home/zzx/EVA/cve-2018-6789/exim-4.89/bin
CONFIGURE_FILE=/home/zzx/EVA/cve-2018-6789/exim-4.89/configure
SPOOL_DIRECTORY=/home/zzx/EVA/cve-2018-6789/exim-4.89/exim
EXIM_USER=zzx
AUTH_PLAINTEXT=yes
AUTH_CRAM_MD5=yes
AUTH_TLS=yes

Cela facilite le débogage Puis compiler et installer

make install

Modifier ./configure, le remplacer directement par le contenu ci-dessous

acl_smtp_mail=acl_check_mail
acl_smtp_data=acl_check_data
begin acl
acl_check_mail:
  .ifdef CHECK_MAIL_HELO_ISSUED
  deny
    message = no HELO given before MAIL command
    condition = ${if def:sender_helo_name {no}{yes}}
  .endif

  accept

acl_check_data:
  accept

begin authenticators
fixed_cram:
  driver = cram_md5
  public_name = CRAM-MD5
  server_secret = ${if eq{$auth1}{ph10}{secret}fail}
  server_set_id = $auth1

Exécution

./bin/exim -bd -d-receive

Analyse de la vulnérabilité

Tout d'abord, analyser le patch dans base64.c : 1 où result est le buffer de stockage du résultat du décodage base64, obtenu par la fonction store_get On peut remarquer que le calcul de size avant le patch est problématique : lorsque size est dans la plage 4n~4n+3, la longueur calculée de size est égale, mais lors du décodage d'un paramètre qui n'est pas un multiple de 4, b64decode décode un ou deux octets supplémentaires

Par exemple, envoyons directement

auth_md5('Hf'*42)

size=0x40
Répartition mémoire :

pwndbg> hexdump 0x711d60 0x50
+0000 0x711d60  1d f1 df 1d  f1 df 1d f1  df 1d f1 df  1d f1 df 1d  │....│....│....│....│
+0010 0x711d70  f1 df 1d f1  df 1d f1 df  1d f1 df 1d  f1 df 1d f1  │....│....│....│....│
+0020 0x711d80  df 1d f1 df  1d f1 df 1d  f1 df 1d f1  df 1d f1 df  │....│....│....│....│
+0030 0x711d90  1d f1 df 1d  f1 df 1d f1  df 1d f1 df  1d f1 df 00  │....│....│....│....│
+0040 0x711da0  20 61 61 61  61 61 61 61  61 61 61 61  61 61 61 61  │.aaa│aaaa│aaaa│aaaa│

Essayons à nouveau

auth_md5('Hf'*42+'HfH')

size=0x40

pwndbg> hexdump 0x711d60 0x50
+0000 0x711d60  1d f1 df 1d  f1 df 1d f1  df 1d f1 df  1d f1 df 1d  │....│....│....│....│
+0010 0x711d70  f1 df 1d f1  df 1d f1 df  1d f1 df 1d  f1 df 1d f1  │....│....│....│....│
+0020 0x711d80  df 1d f1 df  1d f1 df 1d  f1 df 1d f1  df 1d f1 df  │....│....│....│....│
+0030 0x711d90  1d f1 df 1d  f1 df 1d f1  df 1d f1 df  1d f1 df 1d  │....│....│....│....│
+0040 0x711da0  f1 61 61 61  61 61 61 61  61 61 61 61  61 61 61 61  │.aaa│aaaa│aaaa│aaaa│

Débordement de deux octets

Mécanisme de gestion mémoire d'Exim

Pour améliorer les performances, Exim implémente son propre mécanisme de gestion mémoire au-dessus de la gestion de tas existante. Il agit comme un tampon intermédiaire entre le code et glibc, dans le but de réduire le nombre d'appels à malloc et free 2 Pour Exim, un bloc de tas individuel est appelé storeblock. Chaque fois qu'un buffer de taille appropriée est nécessaire, il est découpé à l'intérieur du storeblock. Si un storeblock est épuisé, un nouveau storeblock est alloué via malloc. Pour chaque storeblock, sa structure est une simple liste chaînée :

/* Structure describing the beginning of each big block. */
typedef struct storeblock {
  struct storeblock *next;
  size_t length;
} storeblock;

Les principales API utilisées pour la manipulation du tas se trouvent dans store.c :

store_get
store_release
store_extend
store_reset

Parmi elles, store_get est utilisée pour obtenir un buffer. Voici le code clé :

128 void *
129 store_get_3(int size, const char *filename, int linenumber)
....
145   int length = (size <= STORE_BLOCK_SIZE)? STORE_BLOCK_SIZE : size;
...
161   /* If there was no free block, get a new one */
162 
163   if (!newblock)
164     {
165     pool_malloc += mlength;           /* Used in pools */
166     nonpool_malloc -= mlength;        /* Exclude from overall total */
167     newblock = store_malloc(mlength);
...

On voit que la longueur minimale d'un store_block demandé est STORE_BLOCK_SIZE, soit 8192

Donc un store_block de taille 8192, avec son en-tête de structure et l'en-tête du tas, a une taille totale de 0x2020 3

Lorsqu'Exim exécute une commande envoyée par le client, si la commande est exécutée avec succès, il appelle store_reset pour libérer les caches inutiles et les store_block supplémentaires. Ici, "exécutée avec succès" signifie que le format de la commande est correct, que l'adresse e-mail ne contient pas de caractères invalides, etc. Sinon, store_reset n'est pas appelé.

Stratégie d'exploitation

Cette vulnérabilité est un off-by-one classique (bien qu'en réalité on puisse déborder de deux octets), mais comme le nombre d'octets débordés est faible, il n'est pas possible de modifier directement des structures sensibles sur le tas. Il faut donc exploiter certaines propriétés de ptmalloc pour amplifier l'impact de cette vulnérabilité, en la transformant en un débordement plus large, ou en overlap. Pour les vulnérabilités off-by-one, il existe une technique classique : chunk enlarge -> chunk overlap. En modifiant la taille d'un chunk pour l'agrandir, puis en forgeant un en-tête de tas pour contourner les vérifications de cohérence de glibc, on obtient un recouvrement de chunks permettant un débordement plus large.

Le processus principal est : chunk enlarge -> chunk overlap -> corrompre le pointeur next dans le storeblock, puis déclencher store_reset pour libérer un chunk arbitraire. En réallouant ce chunk, on peut modifier son contenu (type confusion). meh recommande dans son article de modifier le chunk contenant la chaîne ACL, car le traitement des chaînes ACL inclut une fonction d'exécution de commandes. Il y a beaucoup de chaînes ACL, mais la plupart sont NULL (peut-être en rapport avec le fichier de configuration). J'ai choisi la chaîne acl_smtp_mail. La syntaxe pour exécuter une commande est :

${run{command}}

La disposition approximative du tas est la suivante : 4

Le premier chunk est celui obtenu par le décodage base64, utilisé pour le off-by-one. Il doit donc se trouver à la fin d'un storeblock. Pour simplifier, on alloue directement un chunk de taille supérieure à 0x2020 pour stocker le résultat du décodage base64. Le deuxième chunk est sender_helo_name, utilisé pour recouvrir le chunk suivant. sender_helo_name n'est pas stocké dans un storeblock, mais alloué directement via malloc :

1832 static BOOL
1833 check_helo(uschar *s)
1834 {
...
1884 if (yield) sender_helo_name = string_copy_malloc(start);

Sa taille est donc libre. Le troisième chunk est un autre chunk obtenu par décodage base64, principalement utilisé pour forger l'en-tête et être recouvert. Il doit donc se trouver au début d'un storeblock. Pour simplifier, on alloue également une taille de 0x2020.

Télécharger l’outil