Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
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
CVE-2018-6789 — Exploit para CVE-2018-6789, un desbordamiento de búfer en el montón en la decodificación base64 de Exim, que logra ejecución remota de código mediante la superposición de fragmentos y la manipulación de cadenas ACL. | Kitploit
Herramientas/GitHubGitHub/beraphin/cve-2018-6789
Análisis de VulnerabilidadesExplotaciónCTFAprendizaje y EducaciónExplotación de BinariosLabs y Práctica
GitHubberaphin/cve-2018-6789

CVE-2018-6789

Exploit para CVE-2018-6789, un desbordamiento de búfer en el montón en la decodificación base64 de Exim, que logra ejecución remota de código mediante la superposición de fragmentos y la manipulación de cadenas ACL.

Ver Repositorio
316hace 6 añosAún no revisado

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

CVE-2018-6789

Configuración del entorno

Instalar dependencias

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

Descargar una versión antigua 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

Luego modificar Local/Makefile Para mayor comodidad, todas las rutas apuntan al directorio actual

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

Esto facilita la depuración Luego compilar e instalar

make install

Modificar ./configure, sobrescribir con el siguiente contenido

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

Ejecución

./bin/exim -bd -d-receive

Análisis de la vulnerabilidad

Primero, analicemos el parche en base64.c: 1 Donde result es el buffer donde se almacena el resultado de la decodificación base64, obtenido mediante la función store_get. Se puede observar que el cálculo de size antes del parche es incorrecto. Cuando size está en el rango de 4n~4n+3, el tamaño calculado es igual, pero b64decode, al decodificar parámetros que no son múltiplos de 4, decodifica uno o dos bytes adicionales.

Por ejemplo, si enviamos directamente

auth_md5('Hf'*42)

size=0x40 Distribución de memoria resultante:

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│

Probemos de nuevo

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│

Se desbordan dos bytes

Mecanismo de gestión de memoria en Exim

Para mejorar el rendimiento, Exim implementa su propio mecanismo de gestión de memoria sobre el mecanismo de heap original. Actúa como un búfer intermedio entre el código y glibc, con el objetivo de reducir la cantidad de llamadas malloc y free. 2 Para Exim, un bloque de heap individual se denomina storeblock. Cada vez que se necesita, se divide en buffers de tamaño adecuado. Si un storeblock se agota, se solicita otro mediante malloc. Cada storeblock tiene una estructura simple de lista enlazada:

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

Las principales API para el uso del heap se encuentran en store.c:

store_get
store_release
store_extend
store_reset

store_get se utiliza para obtener un buffer. El código clave es el siguiente:

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);
...

Se puede observar que cada store_block solicitado tiene un tamaño mínimo de STORE_BLOCK_SIZE, es decir, 8192.

Por lo tanto, un store_block de 8192 bytes, más su cabecera y la cabecera del heap, tiene un tamaño total de 0x2020. 3

En Exim, cada vez que se ejecuta un comando enviado por el cliente, si el comando se ejecuta correctamente, se llama a store_reset para liberar la caché innecesaria y los store_block sobrantes. Aquí, "ejecución correcta" incluye que el formato del comando sea correcto, que el correo no contenga caracteres no válidos, etc. De lo contrario, no se llama a store_reset.

Estrategia de explotación

Esta vulnerabilidad es un clásico off-by-one (aunque en realidad puede desbordar dos bytes). Sin embargo, debido a la pequeña cantidad de bytes desbordados, no se pueden sobrescribir directamente estructuras sensibles en el heap. Por lo tanto, es necesario aprovechar algunas características de ptmalloc para amplificar el impacto de esta vulnerabilidad, convirtiéndola en un overflow o overlap de mayor alcance. Para las vulnerabilidades off-by-one, existe un método de explotación clásico: chunk enlarge -> chunk overlap. Se modifica el tamaño del chunk para agrandarlo y luego se falsifica una cabecera de chunk para evadir las comprobaciones de sanidad de glibc, logrando así la superposición de chunks y una cobertura más amplia.

El proceso principal aquí es: chunk enlarge -> chunk overlap -> corromper el puntero next en storeblock, y luego desencadenar store_reset para liberar un chunk arbitrario. Al solicitar este chunk nuevamente, se puede modificar su contenido (type confusion). Meh recomienda en su artículo modificar el bloque de heap donde reside la cadena ACL, ya que en el procesamiento de las cadenas ACL existe una funcionalidad de ejecución de comandos. Las cadenas ACL son muchas, pero la mayoría son NULL (posiblemente relacionado con el archivo de configuración). Aquí elijo la cadena acl_smtp_mail, cuya sintaxis para ejecutar comandos es:

${run{command}}

La distribución aproximada del heap es la siguiente: 4

El primer bloque de heap es el bloque obtenido de la decodificación base64, utilizado para el off-by-one. Por lo tanto, debe estar al final de un storeblock. Para mayor comodidad, aquí se solicita directamente un bloque de heap mayor a 0x2020 para almacenar el resultado de la decodificación base64. El segundo bloque es sender_helo_name, que se utiliza para sobrescribir el siguiente bloque. sender_helo_name no se almacena en un storeblock, sino que se asigna directamente mediante malloc:

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

Por lo tanto, su tamaño es arbitrario. El tercer bloque es otro bloque obtenido de la decodificación base64, utilizado principalmente para falsificar la cabecera y ser sobrescrito. Por lo tanto, debe estar al inicio de un storeblock. Por comodidad, también se solicita un tamaño de 0x2020.

Descargar herramienta