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.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2018-6789 — Exploit per CVE-2018-6789, un heap buffer overflow nella decodifica base64 di Exim, che consente l'esecuzione remota di codice tramite chunk overlap e manipolazione delle stringhe ACL. | Kitploit
Strumenti/GitHubGitHub/beraphin/cve-2018-6789
Analisi delle VulnerabilitàExploitCTFApprendimento e FormazioneBinary ExploitationLab e Pratica
GitHubberaphin/cve-2018-6789

CVE-2018-6789

Exploit per CVE-2018-6789, un heap buffer overflow nella decodifica base64 di Exim, che consente l'esecuzione remota di codice tramite chunk overlap e manipolazione delle stringhe ACL.

Vedi Repository
3166 anni faNon ancora revisionato

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

CVE-2018-6789

Setup dell'ambiente

Installa le dipendenze

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

Scarica la vecchia versione di 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

Poi modifica Local/Makefile Per comodità, tutte le cartelle puntano alla directory corrente

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

Questo facilita il debug Poi compila e installa

make install

Modifica ./configure, sovrascrivendolo direttamente con il seguente contenuto

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

Esecuzione

./bin/exim -bd -d-receive

Analisi della vulnerabilità

Prima analizziamo la patch in base64.c: 1 Qui result è il buffer che contiene il risultato della decodifica base64, ottenuto tramite la funzione store_get. Si può notare che il calcolo di size prima della patch è errato: quando size rientra nell'intervallo 4n~4n+3, la lunghezza calcolata è identica, ma b64decode, decodificando un input la cui lunghezza non è multipla di 4, produce uno o due byte in più.

Ad esempio, se inviamo direttamente

auth_md5('Hf'*42)

size=0x40
La distribuzione della memoria è:

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│

Proviamo anche

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│

Si ha un overflow di due byte.

Meccanismo di gestione della memoria di Exim

Per migliorare le prestazioni, exim ha implementato un proprio meccanismo di gestione della memoria sopra quello dell'heap originale; funge da buffer intermedio tra il codice e glibc, con l'obiettivo di ridurre il numero di chiamate a malloc e free. 2 Per exim, un singolo chunk dell'heap è chiamato storeblock; ogni volta che viene usato, da esso viene ricavato un buffer di dimensione adeguata. Quando uno storeblock è esaurito, viene allocato un nuovo storeblock con malloc. Per ogni storeblock, la sua struttura è una semplice lista concatenata singola:

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

Le principali API usate dal programma per l'heap si trovano in store.c:

store_get
store_release
store_extend
store_reset

Tra queste, store_get è usata per ottenere il buffer; il codice chiave è il seguente:

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   if (!newblock)
163     {
164     pool_malloc += mlength;           /* Used in pools */
165     nonpool_malloc -= mlength;        /* Exclude from overall total */
166     newblock = store_malloc(mlength);
...

Si può notare che la lunghezza minima di ogni store_block richiesto è STORE_BLOCK_SIZE, cioè 8192.

Quindi uno store_block di dimensione 8192, aggiungendo l'header della struttura e l'header del chunk dell'heap, ha una dimensione totale di 0x2020. 3

Ogni volta che exim esegue un comando inviato dal client, se il comando ha successo, viene chiamata store_reset per liberare le cache non necessarie e gli store_block in eccesso.
Qui "eseguito con successo" significa che il formato del comando è corretto, l'indirizzo email non contiene caratteri non validi, ecc.; altrimenti store_reset non viene chiamata.

Strategia di exploit

Questa vulnerabilità è un classico off-by-one (anche se in realtà si può eccedere di due byte), ma poiché i byte di overflow sono pochi, non è possibile sovrascrivere direttamente le strutture sensibili nel chunk. Quindi è necessario sfruttare alcune caratteristiche di ptmalloc per amplificare l'impatto di questa vulnerabilità, trasformandola in un overflow su un'area più vasta, o meglio in un overlap.
Per le vulnerabilità off-by-one, esiste un classico metodo di sfruttamento: chunk enlarge -> chunk overlap. Ingrandendo la size del chunk e falsificando un header del chunk per bypassare i sanity check di glibc, si ottiene l'overlap dei chunk, consentendo una copertura su un'area più ampia. Qui il processo principale è: chunk enlarge -> chunk overlap -> corruzione del puntatore next nello storeblock, quindi innescare store_reset per causare la free di un chunk arbitrario; una volta riallocato questo chunk, si può modificarne il contenuto (type confusion). meh nel suo articolo consiglia di modificare il chunk in cui si trova la stringa ACL, perché nella gestione delle stringhe ACL esiste una funzionalità di esecuzione comandi. Le stringhe ACL sono moltissime, ma la maggior parte sono NULL (probabilmente a causa del file di configurazione). Qui ho scelto la stringa acl_smtp_mail; la sintassi per eseguire comandi è:

${run{command}}

Il layout dell'heap è più o meno il seguente: 4

Il primo chunk è quello ottenuto dalla decodifica base64, usato per l'off-by-one; quindi deve trovarsi alla fine di uno storeblock. Per comodità, qui si alloca direttamente un chunk più grande di 0x2020 per contenere il risultato della decodifica base64;
Il secondo chunk è sender_helo_name, usato per sovrascrivere il chunk successivo. sender_helo_name non è memorizzato in uno storeblock, ma viene allocato direttamente con malloc:

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

Quindi la sua dimensione è arbitraria;
Il terzo chunk è ottenuto dalla decodifica base64, usato principalmente per falsificare l'header e venire sovrascritto; quindi deve trovarsi all'inizio di uno storeblock. Per comodità, si alloca anch'esso direttamente con dimensione 0x2020.

Scarica lo strumento