Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2020-28018 — استغلال لـ Exim4 4.93 CVE-2020-28018 | Kitploit
أدوات/GitHubGitHub/zr0tt/cve-2020-28018
تحليل الثغرات الأمنيةالاستغلالأمن الويباختبار الاختراقأمان البريد الإلكترونياستغلال الملفات الثنائية
GitHubzr0tt/cve-2020-28018

CVE-2020-28018

استغلال لـ Exim4 4.93 CVE-2020-28018

عرض المستودع
3منذ 5 سنواتلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

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 من مستودع المصادر لأوبونتو 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;
}

يتيح SMTP إرسال أوامر "PIPELINED" (rfc2920) وهي القدرة على تجميع عدة أوامر وإرسالها إلى الخادم معًا بدلاً من واحد تلو الآخر لتحسين زمن الانتظار. يتم تسلسل الأوامر مفصولة بـ \n. وبالمثل، يقوم الخادم بتجميع الردود وإرسالها بعد الأمر الأخير الذي ينتهي بـ \r\n.

تحتوي الدالة tls_write على متغير محلي وثابت، server_corked، من النوع gstring *. هذه البنية هي المسؤولة عن تسلسل الردود على أوامر PIPELINED.

البنية gstring، المُعرَّفة في structs.h، تسمح بإنشاء سلاسل ديناميكية.

root@kitploit:~
 /* Growable-string */
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;

لكل أمر PIPELINED، سيتم استدعاء tls_write مع more=1. في الأمر الأول، corked هو NULL وبالتالي سيتم حجز ذاكرة لتخزين الرد المتسلسل. في buff يوجد الرد الجديد، وفي corked الرد المتراكم ويكون في البداية NULL.

root@kitploit:~
corked = string_catn(corked, buff, len);

يحتوي Exim4 على مدير ذاكرة ديناميكي خاص به (allocator) سيتم شرحه لاحقًا. تقوم الدالة string_catn بتسلسل الردود السابقة والجديدة. إذا كانت السلسلة الجديدة لا تتسع في المساحة المحجوزة، تحاول توسيعها أو إذا لم يكن ذلك ممكنًا، يتم حجز كتلة جديدة يتم نسخ السلسلة السابقة إليها.

تقوم الأوامر RST, STARTTLS, MAIL, EHLO بتنفيذ الدالة smtp_reset(). تعيد هذه الدالة تعيين جلسة SMTP عن طريق مسح متغيرات الحالة وتحرير كتل الذاكرة حتى reset_point. المشكلة تكمن في أن المتغير الثابت والمحلي server_corked في tls_write() لا يُعاد تعيينه إلى NULL، بحيث في التنفيذ التالي للدالة، نظرًا لأن corked ليس NULL، سيتم تسلسل هذه البنية المحررة بالفعل مع الرد الجديد.

التجميع باستخدام OpenSSL

حزم Debian/Ubuntu تأتي مُجمَّعة مع مكتبة GnuTLS. قم بتشغيل الملف exim_openssl_build.sh لتجميع Exim باستخدام OpenSSL.

تشغيل الخدمة

sudo /usr/sbin/exim -bd -d -v

  • -bd تشغيل exim كخفيّ (daemon).
  • -d تصحيح الأخطاء (debugging)
  • -v مطوّل (verbose)

مدير الذاكرة لـ Exim4

TODO

الاستغلال

TODO

تنزيل الأداة