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/martinclauss/exim-rce-cve-2018-6789
Analyse des VulnérabilitésExploitationDébogueursApprentissage et ÉducationExploitation de BinairesLabs et Pratique
GitHubmartinclauss/exim-rce-cve-2018-6789

exim-rce-cve-2018-6789

Ce dépôt fournit un environnement d'apprentissage pour comprendre comment fonctionne un exploit RCE Exim pour CVE-2018-6789.

Voir le dépôt
1172il y a 1 moisPas 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

Environnement d'apprentissage pour Exim RCE (CVE-2018-6789)

Description

Ceci est un ensemble de fichiers, scripts, notes, ... permettant de mettre en place un environnement pour étudier l'Exim RCE (CVE-2018-6789). Il peut être utilisé pour déboguer Exim, écrire des exploits, tracer les appels de fonction d'Exim, découvrir la gestion mémoire personnalisée d'Exim (storeblocks), comprendre le fonctionnement d'un exploit réel, ...

Il ne doit être utilisé qu'à des fins académiques !

Prérequis

  • Vagrant avec libvirt/KVM (le plugin vagrant-libvirt)
  • Docker (uniquement si vous décidez d'exécuter Docker sur votre hôte et non dans la VM Vagrant)

Installation

Téléchargez le code source d'Exim en exécutant

root@kitploit:~
$ git submodule update --init

VM

Un Vagrantfile se trouve dans le répertoire racine. Il utilise comme fournisseur de virtualisation. La box est tirée directement du miroir de Fedora via car les téléchargements depuis Vagrant Cloud sont actuellement cassés (migration HCP) ; Fedora ne publie que des boxes libvirt et VirtualBox là-bas (pas de VMware), et un direct est spécifique au fournisseur, donc cette configuration cible uniquement libvirt.

libvirt
box_url
box_url
root@kitploit:~
# -*- mode: ruby -*-
# vi: set ft=ruby :

memory = 8192 # en MiB
cpus = 4

Vagrant.configure("2") do |config|
  # Les téléchargements depuis Vagrant Cloud sont cassés ; tirer la box du miroir Fedora
  config.vm.box = "fedora-44-cloud-base"
  config.vm.box_url = "https://download.fedoraproject.org/pub/fedora/linux/releases/44/Cloud/x86_64/images/Fedora-Cloud-Base-Vagrant-libvirt-44-1.7.x86_64.vagrant.libvirt.box"

  config.vm.provider "libvirt" do |lv|
    lv.memory = memory
    lv.cpus = cpus
  end

  config.vm.provision "shell", inline: <<-SHELL
  	/vagrant/scripts/setup_vm.sh
  SHELL
end

Vous pouvez modifier la configuration comme vous le souhaitez, mais gardez à l'esprit que, par exemple, le script setup_vm.sh utilise dnf pour installer les paquets. Si vous voulez utiliser Ubuntu, vous devez remplacer les lignes dnf install par apt-get install et ajuster les noms de paquets en conséquence. Cependant, rien ne garantit que l'installation fonctionnera correctement.

Lorsque vous êtes satisfait de votre configuration, exécutez simplement :

root@kitploit:~
$ vagrant up

pour configurer la machine, puis

root@kitploit:~
$ vagrant ssh

pour vous y connecter. Si vous ne savez pas comment utiliser Vagrant, jetez un œil ici : https://www.vagrantup.com/intro/getting-started/

Conteneur Docker

Vagrant mappe le répertoire courant (c'est-à-dire le dépôt que vous venez de cloner) en tant que répertoire partagé vers /vagrant. Pour créer et exécuter l'image Docker pour Exim, entrez les commandes suivantes dans votre VM (vagrant ssh)

root@kitploit:~
[vagrant@localhost ~]$ cd /vagrant
[vagrant@localhost vagrant]$ ./scripts/reset_docker.sh

La première fois prendra beaucoup plus de temps car Exim sera compilé à partir des sources. Si vous modifiez des scripts de débogage ou d'autres fichiers qui seront copiés dans le conteneur Docker, vous pouvez toujours utiliser ./scripts/reset_docker.sh pour reconstruire l'image Docker. Bien sûr, vous pouvez aussi simplement extraire les lignes nécessaires du script et les exécuter comme des commandes individuelles.

Quand tout est terminé, vous devriez voir une console root :

root@kitploit:~
Successfully tagged exim:latest
787f310ef922a1e519cf8bb47f1c4fed5f510da705e7ceefd48f160c980e969c
root@787f310ef922:/opt#

Les chaînes bizarres peuvent être différentes sur votre machine, mais vous êtes maintenant dans un conteneur Docker Debian fonctionnant dans une VM Fedora sur votre machine hôte.

Utilisation de la VM et du conteneur

Tout d'abord, vous pouvez créer deux sessions SSH avec vagrant ssh dans deux fenêtres de terminal. L'une peut être utilisée pour exécuter des exploits et interagir avec Exim via SMTP. L'autre est utilisée pour démarrer, exécuter, déboguer, ... Exim dans le conteneur Docker. L'ASLR est désactivé dans la VM afin que vous puissiez définir des points d'arrêt fiables qui ne changent pas pendant les sessions de débogage.

Exemple de session :

Premier terminal :

root@kitploit:~
$ vagrant ssh
[vagrant@localhost vagrant]$

Deuxième terminal :

root@kitploit:~
$ vagrant ssh
[vagrant@localhost vagrant]$ cd /vagrant
[vagrant@localhost vagrant]$ ./scripts/reset_docker.sh
...
# maintenant vous êtes à l'intérieur du conteneur Docker Debian
root@99296cf63016:/opt# ./run_exim.sh
root@99296cf63016:/opt# ./attach_exim.sh

Le script run_exim.sh se termine et Exim s'exécute en arrière-plan. Le script ./attach_exim.sh devrait attacher gdb au processus du démon Exim en cours et vous donner un résultat comme celui-ci :

root@kitploit:~
...
pwndbg: loaded 170 commands. Type pwndbg [filter] for a list.
pwndbg: created $rebase, $ida gdb functions (can be used with print/break)

Attaching to process 14
Reading symbols from /usr/exim/bin/exim-4.89_1-1-fc6d6586-XX-1...done.
...
0x00007ffff6b7f5e3 in __select_nocancel () at ../sysdeps/unix/syscall-template.S:84
84	../sysdeps/unix/syscall-template.S: No such file or directory.
Breakpoint 1 at 0x5555555c03d2: file smtp_in.c, line 1762.
Breakpoint 2 at 0x5555555c051d: file smtp_in.c, line 1884.
Breakpoint 3 at 0x55555556a2c8: file base64.c, line 154.
Breakpoint 4 at 0x5555555c6aca: file smtp_in.c, line 3690.

Exim est en cours d'exécution et attend les requêtes. Les points d'arrêt définis proviennent du fichier debugging/breakpoints. Vous pouvez utiliser Ctrl+C pour interrompre le processus et donner le contrôle à gdb. Vous pouvez également exécuter l'un des scripts d'exploit fournis pour tester si tout fonctionne comme prévu :

Premier terminal :

root@kitploit:~
[vagrant@localhost ~]$ cd /vagrant/sploits/
[vagrant@localhost sploits]$ ./sploit_0.py
[+] Opening connection to localhost on port 25: Done

Deuxième terminal :

root@kitploit:~
Thread 2.1 "exim" hit Breakpoint 2, smtp_reset (reset_point=reset_point@entry=0x555555843078) at smtp_in.c:1884
1884	{
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
──────────────────────────────────────────────[ REGISTERS ]───────────────────────────────────────────────
 RAX  0x555555843078 ◂— 0x0
 RBX  0x0
 RCX  0x555555824b40 (store_last_get) —▸ 0x555555843078 ◂— 0x0
 RDX  0x555555820b30 (yield_length) ◂— 0x15800001c38
 RDI  0x555555843078 ◂— 0x0
 RSI  0x0
 R8   0x3
 R9   0x52
 R10  0x73
 R11  0x246
 R12  0x5555555ec7fa ◂— 'daemon.c'
 R13  0x555555843078 ◂— 0x0
 R14  0x0
 R15  0x0
 RBP  0x5555555ee3db ◂— and    byte ptr [rax], ah /* '  %s\n' */
 RSP  0x7ffffffbe528 —▸ 0x5555555c31d1 (smtp_setup_msg+67) ◂— mov    dword ptr [rip + 0x260b6d], 0
 RIP  0x5555555c051d (smtp_reset) ◂— push   rbp
────────────────────────────────────────────────[ DISASM ]────────────────────────────────────────────────
 ► 0x5555555c051d <smtp_reset>       push   rbp
   0x5555555c051e <smtp_reset+1>     push   rbx
   0x5555555c051f <smtp_reset+2>     sub    rsp, 8
   0x5555555c0523 <smtp_reset+6>     mov    rbp, rdi
   0x5555555c0526 <smtp_reset+9>     mov    qword ptr [rip + 0x263657], 0 <0x555555823b88>
   0x5555555c0531 <smtp_reset+20>    mov    dword ptr [rip + 0x263645], 0 <0x555555823b80>
   0x5555555c053b <smtp_reset+30>    mov    dword ptr [rip + 0x26364f], 0 <0x555555823b94>
   0x5555555c0545 <smtp_reset+40>    mov    dword ptr [rip + 0x263699], 0 <0x555555823be8>
   0x5555555c054f <smtp_reset+50>    mov    dword ptr [rip + 0x263687], 0 <0x555555823be0>
   0x5555555c0559 <smtp_reset+60>    mov    dword ptr [rip + 0x263679], 0 <0x555555823bdc>
   0x5555555c0563 <smtp_reset+70>    mov    dword ptr [rip + 0x263677], 0 <0x555555823be4>
────────────────────────────────────────────[ SOURCE (CODE) ]─────────────────────────────────────────────
In file: /opt/exim/src/src/smtp_in.c
   1879 Returns:    nothing
   1880 */
   1881
   1882 static void
   1883 smtp_reset(void *reset_point)
 ► 1884 {
   1885 recipients_list = NULL;
   1886 rcpt_count = rcpt_defer_count = rcpt_fail_count =
   1887   raw_recipients_count = recipients_count = recipients_list_max = 0;
   1888 cancel_cutthrough_connection("smtp reset");
   1889 message_linecount = 0;
────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────
00:0000│ rsp  0x7ffffffbe528 —▸ 0x5555555c31d1 (smtp_setup_msg+67) ◂— mov    dword ptr [rip + 0x260b6d], 0
01:0008│      0x7ffffffbe530 —▸ 0x7ffffffbe600 ◂— 0x0
02:0010│      0x7ffffffbe538 —▸ 0x7ffffffbe540 —▸ 0x555555605f1a ◂— add    byte ptr [rip + 0x25203a73], ah
03:0018│      0x7ffffffbe540 —▸ 0x555555605f1a ◂— add    byte ptr [rip + 0x25203a73], ah
04:0020│      0x7ffffffbe548 —▸ 0x555555843078 ◂— 0x0
05:0028│      0x7ffffffbe550 ◂— 0x0
06:0030│      0x7ffffffbe558 —▸ 0x7ffff6b7f5e3 (__select_nocancel+10) ◂— cmp    rax, -0xfff
07:0038│      0x7ffffffbe560 ◂— 0x7ffffffbe560
──────────────────────────────────────────────[ BACKTRACE ]───────────────────────────────────────────────
 ► f 0     5555555c051d smtp_reset
   f 1     5555555c31d1 smtp_setup_msg+67
   f 2     55555556de43 daemon_go+10909
   f 3     55555556de43 daemon_go+10909
   f 4     555555583ca5 main+21601
   f 5     7ffff6abe2e1 __libc_start_main+241
──────────────────────────────────────────────────────────────────────────────────────────────────────────
Breakpoint smtp_reset
pwndbg>

Vous pouvez supprimer tous les points d'arrêt avec d et continuer avec c pour laisser le script sploit_0.py s'exécuter jusqu'à sa fin :

Deuxième terminal :

root@kitploit:~
Breakpoint smtp_reset
pwndbg> d
pwndbg> c
Continuing.
[Inferior 2 (process 42) exited with code 01]

Premier terminal :

root@kitploit:~
...
220 787f310ef922 ESMTP Exim 4.89_1-1-fc6d6586-XX Mon, 02 Mar 2020 14:47:24 +0000
250-787f310ef922 Hello test.example.org [172.17.0.1]
250-SIZE 52428800
250-8BITMIME
250-PIPELINING
250-AUTH PLAIN
250-CHUNKING
250-PRDR
250 HELP

501 Invalid base64 data
[*] Closed connection to localhost port 25

Si le processus fils que vous venez de déboguer (auquel vous vous êtes attaché) se termine (par exemple [Inferior 2 (process 42) exited with code 01]), vous pouvez quitter gdb et relancer ./attach_exim.sh.

Scripts GDB

Sous debugging, vous trouverez quelques scripts qui peuvent être utiles. L'un des scripts est showmem.py. Il vous permet d'inspecter les storeblocks d'Exim et les chunks de tas correspondants. Vous pouvez l'exécuter dans gdb avec la commande smem :

root@kitploit:~
pwndbg> smem
...
[SHOWMEM]: 0x5555558402b0: heap chunk of size 0x000004b0 (used) / data:
[SHOWMEM]: 0x555555840760: heap chunk of size 0x00000030 (used) / data: /lib/x86_64-linux-gnu
[SHOWMEM]: 0x555555840790: heap chunk of size 0x00000050 (used) / data: ...UUU
[SHOWMEM]: 0x5555558407e0: heap chunk of size 0x000000e0 (used) / data:
[SHOWMEM]: 0x5555558408c0: heap chunk of size 0x00000370 (free) / data: .~....
[SHOWMEM]: 0x555555840c30: heap chunk of size 0x00000040 (used) / data:
[SHOWMEM]: 0x555555840c70: heap chunk of size 0x00002020 (used) / data:
[SHOWMEM]:   0x555555840c80: storeblock of size 0x00002000      / data:
[SHOWMEM]: 0x555555842c90: heap chunk of size 0x00002020 (used) / data:
[SHOWMEM]:   0x555555842ca0: storeblock of size 0x00002000      / data: root
[SHOWMEM]: 0x555555844cb0: heap chunk of size 0x00008010 (used) / data:
[SHOWMEM]: 0x55555584ccc0: heap chunk of size 0x00002010 (used) / data:
[SHOWMEM]: 0x55555584ecd0: heap chunk of size 0x00001010 (used) / data: 220 99296cf63016 ESMTP Exim 4.89_1-1-fc6d6586-XX M
[SHOWMEM]: 0x55555584fce0: heap chunk of size 0x0001d320 (free) / data:

Les régions mémoire en retrait sont les storeblocks, les autres régions sont des chunks de tas (glibc). Actuellement, il s'agit d'une approximation car je n'ai pas recoupé les chunks utilisés avec les listes libres de glibc, donc il peut y avoir quelques indications erronées de blocs utilisés/libres. Vous pouvez toujours utiliser les commandes bins, heap, ... de pwndbg comme source d'information supplémentaire !

Remarque : Avec libvirt / KVM, le dossier /vagrant est synchronisé via rsync, donc après avoir modifié des fichiers sur l'hôte, exécutez vagrant rsync (ou laissez vagrant rsync-auto en cours) pour copier vos modifications dans la VM avant de reconstruire le conteneur.

Structure

root@kitploit:~
.
├── debugging                # Scripts liés à GDB
│   ├── breakpoints
│   ├── gdbinit
│   ├── showmem.py
│   └── trace.py
├── Dockerfile               # Dockerfile pour construire et déboguer Exim
├── Exim                     # Code source de la version vulnérable d'Exim
├── exim_code_backup         # Sauvegarde du code source vulnérable d'Exim
│   └── exim-fc6d65867e82009a6e0671771728d41d3423a790.zip
├── exim_files               # Fichiers Exim patchés pour construire Exim correctement
│   ├── configure
│   ├── eximon.conf
│   ├── Makefile
│   └── Makefile-Linux
├── README.md
├── scripts                  # Scripts d'aide pour déboguer Exim
│   ├── attach_exim.sh
│   ├── reset_docker.sh
│   ├── run_exim.sh
│   └── setup_vm.sh
├── sploits                  # Scripts d'exploit incrémentaux et un script pour trouver l'octet 0xf1
│   ├── exim_0xf1.py
│   ├── smtp.py
│   ├── sploit_0.py
│   ├── sploit_1.py
│   ├── sploit_2.py
│   ├── sploit_3.py
│   ├── sploit_4.py
│   ├── sploit_5.py
│   ├── sploit_6.py
│   ├── sploit_7.py
│   ├── sploit_8.py
│   ├── sploit_9.py
│   └── sploit_10.py
└── Vagrantfile              # Vagrantfile pour créer la VM qui héberge le conteneur Docker

Scripts d'exploit

Les scripts d'exploit se trouvent sous sploits. Ils sont construits de manière incrémentale pour faciliter la compréhension des différentes étapes. Ils sont presque identiques aux étapes fournies par @straightblast426 sur medium.com.

sploit_10.py est le script final qui devrait démontrer la RCE en un seul script. Ce script ne lance pas de shell inverse mais crée un fichier sous /tmp. Vous pouvez le modifier en éditant la ligne suivante :

root@kitploit:~
cmd = '/bin/bash -c "touch /tmp/pwned"'

Veuillez noter que le script sploit_10.py fourni n'est pas la seule façon d'exploiter la vulnérabilité. Il existe, par exemple, d'autres façons d'organiser le tas !

Limitations

Le grooming est sensible à l'environnement : gardez host_lookup = désactivé (une recherche DNS inverse du nom du client pollue le tas que l'exploit organise) et le conteneur sur debian:bullseye (le grooming ne survit que dans la glibc 2.31 de Debian, pas celle d'Ubuntu ou de bookworm). Cela signifie également que ce dépôt ne fonctionnera (tel quel) que tant qu'il existe une distribution disponible fournissant glibc 2.31 (publiée pour la première fois en 2020) !

Le pointeur next sera modifié avec une adresse constante précédemment connue (qui devrait également fonctionner pour vous si vous utilisez la configuration identique). Si vous lancez cet exploit contre une autre instance d'Exim en cours d'exécution, il ne fonctionnera pas (les chances sont très faibles). Vous pourriez contourner l'ASLR avec un peu de brute-force. Cela fonctionne assez bien car Exim se duplique (clone) pour traiter les requêtes des clients. Cela signifie que la disposition globale de la mémoire reste la même et que vous avez une chance réaliste de brute-forcer le pointeur next. Si vous ne savez pas ce qu'est le pointeur next, vous devriez d'abord lire les références.

Si vous construisez exim légèrement différemment, l'emplacement du pointeur next peut être différent. Vous devez trouver l'adresse du storeblock qui contient acl_smtp_rcpt. Suivez ces étapes et ajustez le pointeur dans les fichiers sploit_xx.py respectifs :

root@kitploit:~
# connectez-vous à la VM avec : vagrant ssh
./run_exim.sh
./attach_exim.sh

# pwndbg démarre, puis Ctrl-C
pwndbg> smem
[SHOWMEM]: 0x55555562e6b0: heap chunk of size 0x00002020 (used) / data: .2cUUU
[SHOWMEM]:   0x55555562e6c0: storeblock of size 0x00002000      / data: /usr/exim/configure
...

Le storeblock à l'adresse 0x55555562e6c0 contient également acl_smtp_rcpt :

root@kitploit:~
pwndbg> p acl_smtp_rcpt
$1 = (uschar *) 0x55555562e7f0 "acl_check_rcpt"

Donc, dans les scripts d'exploit, remplacez-le par l'adresse affichée avec la commande smem :

root@kitploit:~
# ...
# adresse du storeblock des chaînes ACL (pas le chunk)
address_of_acl_storeblock = 0x55555562E6C0
# ...

Références

  • https://devco.re/blog/2018/03/06/exim-off-by-one-RCE-exploiting-CVE-2018-6789-en/ (sauvegarde)
  • https://medium.com/@straightblast426/my-poc-walk-through-for-cve-2018-6789-2e402e4ff588 (sauvegarde)
Télécharger l’outil