Skip to content
KitploitKITPLOIT
StrumentiExploitsBlog
Log in
Invia
StrumentiExploitsBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

FeedContattoPrivacy© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2020-28018 — Exploit per la Use-After-Free di Exim (CVE-2020-28018) che consente l'esecuzione remota di codice tramite primitive di corruzione della memoria, incluse lettura/scrittura arbitraria e leak dell'heap, con una catena opzionale di escalation dei privilegi locali. | Kitploit
Strumenti/GitHubGitHub/dorkerdevil/cve-2020-28018
Escalation di PrivilegiMemory ForensicsAnalisi delle VulnerabilitàExploitStrumento di Accesso RemotoSviluppo PayloadBinary Exploitation
GitHub

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi
dorkerdevil/cve-2020-28018

CVE-2020-28018

Exploit per la Use-After-Free di Exim (CVE-2020-28018) che consente l'esecuzione remota di codice tramite primitive di corruzione della memoria, incluse lettura/scrittura arbitraria e leak dell'heap, con una catena opzionale di escalation dei privilegi locali.

Vedi Repository
71125 anni faNon ancora revisionato

CVE-2020-28018: Use-after-free (UAF) in Exim che porta a RCE

Introduzione

Esiste una vulnerabilità Use-after-free (UAF) in tls-openssl.c che consente a un attaccante remoto non autenticato di corrompere i dati interni della memoria, portando infine all'esecuzione di codice remoto.

Primitive:

  • Perdita di memoria
  • Primitiva di lettura arbitraria
  • Primitiva di scrittura ovunque (Write-What-Where)

Utilizzando tutte queste primitive concatenate, è possibile bypassare completamente tutte le mitigazioni disponibili per gli exploit, ottenendo infine l'esecuzione di codice remoto come utente exim.

Questa vulnerabilità è stata rilasciata tra un'enorme lista di vulnerabilità; il rapporto ufficiale di Qualys concatena la Use-After-Free con CVE-2020-28008 per effettuare un escalation di privilegi locale (LPE) una volta ottenuta la RCE.

Prerequisiti

Exim deve essere configurato/compilato nel seguente modo:

  • TLS abilitato
  • OpenSSL utilizzato (invece di GnuTLS)
  • Exim è una delle versioni vulnerabili
  • X_PIPE_CONNECT disabilitato

Puoi usare lo script checker.py per verificare se un server remoto è in una versione vulnerabile e possiede alcuni requisiti necessari per essere sfruttabile.

[!] checker.py NON attiva la vulnerabilità, controlla solo la versione vulnerabile, verifica se PIPELINING e TLS sono abilitati. Questo significa che il checker non controlla la patch, quindi può generare falsi positivi.

Codice vulnerabile

Come già sappiamo, la vulnerabilità si trova in tls-openssl.c.

/*************************************************
*         Write bytes down TLS channel           *
*************************************************/

/*
Arguments:
  ct_ctx    client context pointer, or NULL for the one global server context
  buff      buffer of data
  len       number of bytes
  more	    further data expected soon

Returns:    the number of bytes after a successful write,
            -1 after a failed write

Used by both server-side and client-side TLS.
*/

int
tls_write(void * ct_ctx, const uschar *buff, size_t len, BOOL more)
{
int outbytes, error, left;
SSL * ssl = ct_ctx ? ((exim_openssl_client_tls_ctx *)ct_ctx)->ssl : server_ssl;
static gstring * corked = NULL;

DEBUG(D_tls) debug_printf("%s(%p, %lu%s)\n", __FUNCTION__,
  buff, (unsigned long)len, more ? ", more" : "");

/* Lacking a CORK or MSG_MORE facility (such as GnuTLS has) we copy data when
"more" is notified.  This hack is only ok if small amounts are involved AND only
one stream does it, in one context (i.e. no store reset).  Currently it is used
for the responses to the received SMTP MAIL , RCPT, DATA sequence, only. */
/*XXX + if PIPE_COMMAND, banner & ehlo-resp for smmtp-on-connect. Suspect there's
a store reset there. */

if (!ct_ctx && (more || corked))
  {
#ifdef EXPERIMENTAL_PIPE_CONNECT
  int save_pool = store_pool;
  store_pool = POOL_PERM;
#endif

  corked = string_catn(corked, buff, len);

#ifdef EXPERIMENTAL_PIPE_CONNECT
  store_pool = save_pool;
#endif

  if (more)
    return len;
  buff = CUS corked->s;
  len = corked->ptr;
  corked = NULL;
  }

for (left = len; left > 0;)
  {
  DEBUG(D_tls) debug_printf("SSL_write(%p, %p, %d)\n", ssl, buff, left);
  outbytes = SSL_write(ssl, CS buff, left);
  error = SSL_get_error(ssl, outbytes);
  DEBUG(D_tls) debug_printf("outbytes=%d error=%d\n", outbytes, error);
  switch (error)
    {
    case SSL_ERROR_SSL:
      ERR_error_string_n(ERR_get_error(), ssl_errstring, sizeof(ssl_errstring));
      log_write(0, LOG_MAIN, "TLS error (SSL_write): %s", ssl_errstring);
      return -1;

    case SSL_ERROR_NONE:
      left -= outbytes;
      buff += outbytes;
      break;

    case SSL_ERROR_ZERO_RETURN:
      log_write(0, LOG_MAIN, "SSL channel closed on write");
      return -1;

    case SSL_ERROR_SYSCALL:
      log_write(0, LOG_MAIN, "SSL_write: (from %s) syscall: %s",
	sender_fullhost ? sender_fullhost : US"<unknown>",
	strerror(errno));
      return -1;

    default:
      log_write(0, LOG_MAIN, "SSL_write error %d", error);
      return -1;
    }
  }
return len;
}

smtp_setup_msg() è la funzione principale che esegue la lettura del messaggio dal client.

In situazioni specifiche, viene chiamata smtp_reset(), che esegue una pulizia di tutti i buffer e i valori.

Ciò può accadere in situazioni come:

  • Viene ricevuto HELO/EHLO
  • Viene ricevuto STARTTLS
  • Viene ricevuto RSET
  • All'inizio di smtp_setup_msg()

Alla fine di smtp_reset(), viene eseguita una chiamata a store_reset().

store_reset è una macro che avvolge la funzione store_reset_3().

Le funzioni di store sono solo funzioni che gestiscono la memoria dinamica.

Exim utilizza un allocatore a pool su blocchi ricevuti da malloc.

C'è anche una funzionalità interessante che è un'implementazione di stringhe espandibili.

Struttura gstring:

typedef struct gstring {
  int   size;           /* Current capacity of string memory */
  int   ptr;            /* Offset at which to append further chars */
  uschar * s;           /* The string memory */
} gstring;

Quando serve più spazio per concatenare una nuova stringa, chiama gstring_grow().

Quella funzione prima prova a chiamare store_extend_3(), che tenta di estendere la memoria all'interno dello stesso blocco del pool.

Può essere utile quando la lunghezza dell'input non è nota, ma se dopo di esso è stata allocata altra memoria, non saremo in grado di estenderlo.

Poi gstring_grow() chiama store_newblock_3() che restituisce una nuova memoria e copia i byte già presenti in quella vecchia nella nuova.

Quindi il puntatore g->s viene ripristinato da gstring_catn().

Nella funzione tls_write(), possiamo vedere che c'è un BOOL chiamato more.

Indica se ci sono altri dati da copiare nel buffer della stringa prima di restituire i dati all'utente.

Se è così, il puntatore non viene azzerato.

Altrimenti, i dati contenuti nel buffer della stringa vengono restituiti all'utente.

Questa funzionalità apre alcuni modi interessanti per attivare una Use-After-Free.

Innanzitutto, il puntatore alla struttura gstring è memorizzato in una variabile statica, questo significa che nelle future chiamate a tls_write() saremo in grado di usarlo.

Come possiamo liberare il buffer e poi essere in grado di usarlo?

Dobbiamo fare in modo che smtp_setup_msg() chiami smtp_reset() dopo che uno dei nostri buffer è ancora in server_corked (non azzerato).

Dopo il reset, se chiamiamo tls_write() in qualche modo, il puntatore sarà ancora lì, permettendoci di usarlo dopo che la memoria è stata liberata.

smtp_reset() libera tutta la memoria di POOL_MAIN, in cui è contenuto il nostro buffer.

Attivazione della Use-After-Free

Per controllare la Use-After-Free dobbiamo prima inizializzare una nuova connessione.

Poiché vogliamo sfruttare tls_write(), dobbiamo prima avviare una nuova sessione TLS.

Quindi per prima cosa inviamo un comando EHLO, seguito da STARTTLS per avviare la connessione TLS.

Poi per fare in modo che more sia 1, inviamo in pipeline un comando, e l'ultimo sarà la metà di un NOOP.

Chiudiamo la connessione TLS e inviamo il resto del comando NOOP.

Ora inviamo di nuovo EHLO, che farà chiamare smtp_reset e libererà il nostro buffer.

Ora dobbiamo avviare un'altra connessione TLS per poter usare di nuovo tls_write().

Inviamo STARTTLS.

Ora l'invio di qualsiasi comando al server finirà per chiamare tls_write() per restituire una risposta.

Ma... server_corked contiene ancora un puntatore a qualche punto nella memoria liberata.

E quei dati potrebbero essere usati da altre funzioni mentre sono liberati...quindi la nostra struttura gstring verrà corrotta con dati binari casuali.

Questo è il risultato dell'attivazione della UAF:

Scarica lo strumento