Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
exim-rce-cve-2018-6789 — Este repositorio proporciona un entorno de aprendizaje para entender cómo funciona un exploit de RCE en Exim para CVE-2018-6789. | Kitploit
Herramientas/GitHubGitHub/martinclauss/exim-rce-cve-2018-6789
Análisis de VulnerabilidadesExplotaciónDepuradoresAprendizaje y EducaciónExplotación de BinariosLabs y Práctica
GitHubmartinclauss/exim-rce-cve-2018-6789

exim-rce-cve-2018-6789

Este repositorio proporciona un entorno de aprendizaje para entender cómo funciona un exploit de RCE en Exim para CVE-2018-6789.

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir
Ver Repositorio
117hace 1 mesAún no revisado

Entorno de aprendizaje de Exim RCE (CVE-2018-6789)

Descripción

Este es un conjunto de archivos, scripts, notas, ... para configurar un entorno en el que investigar el RCE de Exim (CVE-2018-6789). Puede utilizarse para depurar Exim, escribir exploits, rastrear llamadas a funciones de Exim, aprender sobre la gestión de memoria personalizada de Exim (storeblocks), descubrir cómo funciona un exploit del mundo real, ...

¡Solo debe utilizarse con fines académicos!

Requisitos

  • Vagrant con libvirt/KVM (el plugin vagrant-libvirt)
  • Docker (solo si decides ejecutar Docker en tu máquina anfitriona y no dentro de la VM de Vagrant)

Configuración

Descarga el código fuente de Exim ejecutando

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

VM

Hay un Vagrantfile en el directorio raíz. Utiliza libvirt como proveedor de virtualización. La box se descarga directamente del mirror de Fedora mediante box_url porque las descargas de Vagrant Cloud están actualmente rotas (migración a HCP); Fedora solo publica boxes de libvirt y VirtualBox allí (no de VMware), y un box_url directo es específico del proveedor, por lo que esta configuración está dirigida únicamente a libvirt.

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

memory = 8192 # in MiB
cpus = 4

Vagrant.configure("2") do |config|
  # Vagrant Cloud downloads are broken; pull the box from Fedora's mirror
  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

Puedes cambiar la configuración como quieras, pero ten en cuenta que, por ejemplo, el script setup_vm.sh utiliza dnf para instalar paquetes. Si quieres usar Ubuntu debes reemplazar las líneas dnf install por apt-get install y ajustar los nombres de los paquetes en consecuencia. Sin embargo, no hay garantía de que la configuración funcione correctamente.

Cuando estés satisfecho con tu configuración, simplemente ejecuta:

root@kitploit:~
$ vagrant up

para preparar la máquina y, después:

root@kitploit:~
$ vagrant ssh

para conectarte a ella. Si no sabes cómo usar Vagrant, échale un vistazo aquí: https://www.vagrantup.com/intro/getting-started/

Contenedor Docker

Vagrant mapea el directorio actual (es decir, el repositorio que acabas de clonar) como un directorio compartido en /vagrant. Para crear y ejecutar la imagen Docker de Exim introduce los siguientes comandos dentro de tu VM (vagrant ssh)

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

La primera vez tardará mucho más porque Exim se compilará desde el código fuente. Si modificas scripts de depuración u otros archivos que se copiarán dentro del contenedor Docker, siempre puedes usar ./scripts/reset_docker.sh para reconstruir la imagen Docker. Por supuesto, también puedes extraer las líneas necesarias del script y ejecutarlas como comandos individuales.

Cuando todo esté listo deberías ver una consola de root:

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

Las cadenas extrañas pueden verse diferentes en tu máquina, pero ahora estás dentro de un contenedor Docker de Debian ejecutándose en una VM de Fedora sobre tu máquina anfitriona.

Uso de la VM y del contenedor

Primero, puedes crear dos sesiones SSH con vagrant ssh en dos ventanas de terminal. Una se puede usar para ejecutar exploits e interactuar con Exim a través de SMTP. La otra se usa para iniciar, ejecutar, depurar, ... Exim dentro del contenedor Docker. ASLR está deshabilitado en la VM, por lo que puedes establecer breakpoints fiables que no cambien durante las sesiones de depuración.

Ejemplo de sesión:

Primer terminal:

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

Segundo terminal:

root@kitploit:~
$ vagrant ssh
[vagrant@localhost vagrant]$ cd /vagrant
[vagrant@localhost vagrant]$ ./scripts/reset_docker.sh
...
# now you are inside the Debian Docker container
root@99296cf63016:/opt# ./run_exim.sh
root@99296cf63016:/opt# ./attach_exim.sh

El script run_exim.sh termina y Exim se ejecuta en segundo plano. El script ./attach_exim.sh debería adjuntar gdb al proceso demonio de Exim en ejecución y mostrarte una salida como esta:

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 ejecución y esperando peticiones. Los breakpoints que se han establecido provienen del archivo debugging/breakpoints. Puedes usar Ctrl+C para interrumpir el proceso y dar el control a gdb. También podrías ejecutar uno de los scripts de exploit proporcionados para comprobar si todo funciona como se espera:

Primer terminal:

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

Segundo 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>

Puedes eliminar todos los breakpoints con d y continuar con c para dejar que el script sploit_0.py se ejecute hasta que termine:

Segundo terminal:

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

Primer 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 el proceso hijo que acabas de depurar (al que te adjuntaste) termina (p. ej. [Inferior 2 (process 42) exited with code 01]), puedes salir de gdb y ejecutar ./attach_exim.sh de nuevo.

Scripts de GDB

En debugging puedes encontrar algunos scripts que podrían ser útiles. Uno de ellos es showmem.py. Te permite inspeccionar los storeblocks de Exim y los chunks de heap correspondientes. Puedes ejecutarlo dentro de gdb con el comando 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:

Las regiones de memoria indentadas son los storeblocks; las demás regiones son chunks de heap (glibc). Actualmente esto es una aproximación, ya que no he contrastado los chunks en uso con las listas libres de glibc, por lo que puede haber algunas indicaciones incorrectas de bloques usados/libres. ¡Siempre puedes usar los comandos bins, heap, ... de pwndbg como fuente adicional de información!

Nota: con libvirt / KVM la carpeta /vagrant se sincroniza mediante rsync, así que después de editar archivos en el host ejecuta vagrant rsync (o mantén vagrant rsync-auto en ejecución) para copiar tus cambios en la VM antes de reconstruir el contenedor.

Estructura

root@kitploit:~
.
├── debugging                # GDB related scripts
│   ├── breakpoints
│   ├── gdbinit
│   ├── showmem.py
│   └── trace.py
├── Dockerfile               # Dockerfile to build and debug Exim
├── Exim                     # Source code for the vulnerable Exim version
├── exim_code_backup         # backup of the Exim's vulnerable source code
│   └── exim-fc6d65867e82009a6e0671771728d41d3423a790.zip
├── exim_files               # Patched Exim files to build Exim correctly
│   ├── configure
│   ├── eximon.conf
│   ├── Makefile
│   └── Makefile-Linux
├── README.md
├── scripts                  # Helper scripts to debug Exim
│   ├── attach_exim.sh
│   ├── reset_docker.sh
│   ├── run_exim.sh
│   └── setup_vm.sh
├── sploits                  # Incremental exploit scripts and a script to find the 0xf1 byte
│   ├── 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 to create the VM that hosts the Docker container

Scripts de exploit

Los scripts de exploit se encuentran en sploits. Están construidos de forma incremental para que sea más fácil entender los distintos pasos. Son casi idénticos a los pasos proporcionados por @straightblast426 en medium.com.

sploit_10.py es el script final que debería demostrar el RCE en un solo script. Este script no lanza una reverse shell, sino que crea un archivo en /tmp. Puedes modificarlo editando la siguiente línea:

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

Ten en cuenta que el script sploit_10.py proporcionado no es la única forma de explotar la vulnerabilidad. ¡Hay, por ejemplo, otras formas de organizar el heap!

Limitaciones

El grooming es sensible al entorno: mantén host_lookup = deshabilitado (un nombre de cliente de DNS inverso contamina el heap que el exploit prepara) y el contenedor en debian:bullseye (el grooming solo sobrevive con la glibc 2.31 de Debian, no con la de Ubuntu ni con la de bookworm). Esto también significa que este repositorio solo funcionará (tal cual) mientras exista una distribución que proporcione glibc 2.31 (publicada por primera vez en 2020)!

El puntero next se modificará con una dirección conocida de antemano (que también debería funcionarte si usas la configuración idéntica). Si lanzaras este exploit contra otra instancia de Exim en ejecución, no funcionaría (las probabilidades son muy pequeñas). Podrías evadir ASLR con algo de fuerza bruta. Esto funciona bastante bien porque Exim hace fork (clone) de sí mismo para gestionar las peticiones de los clientes. Eso significa que la disposición general de la memoria permanece igual y tienes una oportunidad realista de forzar por fuerza bruta el puntero next. Si no sabes qué es el puntero next, deberías leer primero las referencias.

Si compilas exim de forma ligeramente diferente, la ubicación del puntero next puede ser diferente. Tienes que encontrar la dirección del storeblock que contiene acl_smtp_rcpt. Sigue estos pasos y ajusta el puntero en los archivos sploit_xx.py correspondientes:

root@kitploit:~
# connect to VM with: vagrant ssh
./run_exim.sh
./attach_exim.sh

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

El storeblock con dirección 0x55555562e6c0 también contiene acl_smtp_rcpt:

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

Así que en los scripts de exploit, reemplázala con la dirección que muestra el comando smem:

root@kitploit:~
# ...
# address of the ACL strings storeblock (not the chunk)
address_of_acl_storeblock = 0x55555562E6C0
# ...

Referencias

  • https://devco.re/blog/2018/03/06/exim-off-by-one-RCE-exploiting-CVE-2018-6789-en/ (backup)
  • https://medium.com/@straightblast426/my-poc-walk-through-for-cve-2018-6789-2e402e4ff588 (backup)
Descargar herramienta