## https://sploitus.com/exploit?id=KITPLOIT:TOOLS-GITHUB-ZR0TT-CVE-2020-28018
# PoC CVE-2020-28018
## Введение
Команда Qualys обнаружила и опубликовала 21 критическую уязвимость в почтовом сервере Exim4.
https://blog.qualys.com/vulnerabilities-research/2021/05/04/21nails-multiple-vulnerabilities-in-exim-mail-server
По следующей ссылке предоставлена подробная техническая информация об уязвимостях и их эксплуатации.
https://www.qualys.com/2021/05/04/21nails/21nails.txt
В этом репозитории мы сосредоточимся на CVE-2020-28018, которая позволяет удаленно выполнять код, эксплуатируя уязвимость Use-after-free.
## Требования
* STARTTLS включен (по умолчанию)
* PIPELINING включен (по умолчанию)
* X_PIPE_CONNECT отключен (по умолчанию до Exim 4.94)
* Exim4 скомпилирован с библиотекой OpenSSL. (Требуется перекомпиляция, объяснено ниже)
* Все тесты проводились с Exim 4-4.93 из репозитория исходных кодов Ubuntu 20.04.
## Уязвимость
Уязвимость находится в функции tls_write() в файле tls-openssl.c
root@kitploit:~
/*************************************************
* 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)
{
size_t olen = len;
int outbytes, error;
SSL * ssl = ct_ctx
? ((exim_openssl_client_tls_ctx *)ct_ctx)->ssl : server_ssl;
static gstring * server_corked = NULL;
gstring ** corkedp = ct_ctx
? &((exim_openssl_client_tls_ctx *)ct_ctx)->corked : &server_corked;
gstring * corked = *corkedp;
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.
We support callouts done by the server process by using a separate client
context for the stashed information. */
/* + if PIPE_COMMAND, banner & ehlo-resp for smmtp-on-connect. Suspect there's
a store reset there, so use POOL_PERM. */
/* + if CHUNKING, cmds EHLO,MAIL,RCPT(s),BDAT */
if ((more || corked))
{
#ifdef SUPPORT_PIPE_CONNECT
int save_pool = store_pool;
store_pool = POOL_PERM;
#endif
corked = string_catn(corked, buff, len);
#ifdef SUPPORT_PIPE_CONNECT
store_pool = save_pool;
#endif
if (more)
{
*corkedp = corked;
return len;
}
buff = CUS corked->s;
len = corked->ptr;
*corkedp = NULL;
}
for (int 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 olen;
}