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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
CVE-2018-6789 — استغلال لثغرة CVE-2018-6789، وهي تجاوز سعة المخزن المؤقت في الكومة (heap buffer overflow) في فك ترميز base64 في Exim، ما يحقق تنفيذًا عن بُعد للتعليمات البرمجية عبر تداخل الكتل (chunk overlap) ومعالجة سلاسل ACL. | Kitploit
أدوات/GitHubGitHub/beraphin/cve-2018-6789
تحليل الثغرات الأمنيةالاستغلالCTFالتعلم والتعليماستغلال الملفات الثنائيةمختبرات وتدريب عملي
GitHubberaphin/cve-2018-6789

CVE-2018-6789

استغلال لثغرة CVE-2018-6789، وهي تجاوز سعة المخزن المؤقت في الكومة (heap buffer overflow) في فك ترميز base64 في Exim، ما يحقق تنفيذًا عن بُعد للتعليمات البرمجية عبر تداخل الكتل (chunk overlap) ومعالجة سلاسل ACL.

عرض المستودع
316منذ 6 سنواتلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

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

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

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

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

CVE-2018-6789

إعداد البيئة

تثبيت التبعيات

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

تنزيل نسخة قديمة من 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

ثم عدّل Local/Makefile لتسهيل الأمر، تشير جميع المجلدات إلى الدليل الحالي

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

هذا يسهّل التصحيح ثم قم بالترجمة والتثبيت

make install

عدّل ./configure واستبدل محتواه بما يلي مباشرة

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

التشغيل

./bin/exim -bd -d-receive

تحليل الثغرة

أولًا، لنحلل التصحيح (patch) الموجود في base64.c: 1 حيث إن result هو المخزن المؤقت الذي تُحفظ فيه نتيجة فك ترميز base64، ويتم الحصول عليه عبر الدالة store_get.

يمكن ملاحظة أن حساب size قبل التصحيح كان معيبًا؛ فعندما يقع size ضمن النطاق 4n~4n+3 يكون الطول المحسوب متساويًا، لكن b64decode عند فك ترميز مدخلات ليست من مضاعفات الرقم 4 ينتج بايتًا أو بايتين إضافيين.

على سبيل المثال، إذا أرسلنا مباشرة

auth_md5('Hf'*42)

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 00  │....│....│....│....│
+0040 0x711da0  20 61 61 61  61 61 61 61  61 61 61 61  61 61 61 61  │.aaa│aaaa│aaaa│aaaa│

لنجرّب أيضًا

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│

حدث تجاوز بمقدار بايتين.

آلية إدارة الذاكرة في Exim

لتحسين الأداء، نفّذ Exim آلية إدارة ذاكرة خاصة به فوق آلية إدارة الكومة (heap) الأصلية، وهو بمثابة مخزن مؤقت وسيط بين الكود وglibc، بهدف تقليل عدد مرات استدعاء malloc وfree. 2 في Exim، تُسمى كتلة الكومة الواحدة storeblock، وفي كل مرة يُستخدم فيها المخزن، تُقتطع منه منطقة بحجم مناسب. وعندما تنفد storeblock، يتم استدعاء malloc لإنشاء storeblock جديدة.

بالنسبة لكل storeblock، بنيتها عبارة عن قائمة مرتبطة أحادية بسيطة:

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

أهم واجهات برمجة التطبيقات (API) التي يستخدمها البرنامج عند التعامل مع الكومة موجودة في store.c:

store_get
store_release
store_extend
store_reset

من بينها، تُستخدم store_get للحصول على المخزن المؤقت، وهذا هو الكود الأساسي:

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

يمكن ملاحظة أن الحد الأدنى لطول store_block المطلوب هو STORE_BLOCK_SIZE، أي 8192.

لذلك، فإن store_block بحجم 8192، بعد إضافة ترويسة بنيتها وترويسة كتلة الكومة، يصبح حجمها الإجمالي 0x2020. 3

عندما ينفّذ Exim أمرًا مرسلًا من العميل، إذا نجح التنفيذ، يستدعي store_reset لتحرير المخازن المؤقتة غير الضرورية وكتل store_block الزائدة. ويُقصد بـ«نجاح التنفيذ» هنا أن تنسيق الأمر صحيح، وأن البريد لا يحتوي على أحرف غير قانونية، وما إلى ذلك؛ وإلا فلن يتم استدعاء store_reset.

فكرة الاستغلال

هذه الثغرة هي خطأ off-by-one كلاسيكي (رغم أنه يمكن تجاوز بايتين في الواقع)، لكن لأن عدد البايتات المُتجاوزة صغير، لا يمكن الكتابة مباشرة فوق البنى الحساسة داخل كتل الكومة. لذلك نستغل بعض خصائص ptmalloc لتوسيع تأثير الثغرة وتحويلها إلى تجاوز (overflow) أو تداخل (overlap) أوسع نطاقًا. بالنسبة لثغرات off-by-one، هناك طريقة استغلال كلاسيكية هي chunk enlarge -> chunk overlap، عبر تكبير size كتلة الكومة ثم تزييف ترويسة كتلة لتجاوز فحوصات glibc السليمة، ما يؤدي إلى تداخل الكتل ويتيح تغطية نطاق أوسع.

العملية الرئيسية هنا هي chunk enlarge -> chunk overlap -> corrupt next pointer in storeblock، ثم تشغيل store_reset للتسبب في تحرير كتلة كومة عشوائية (free)، وعندما نتمكن من استعادة نفس الكتلة يمكننا تعديل محتوياتها (type confusion).

أوصى meh في مقالته بتعديل كتلة الكومة التي تحتوي على سلسلة ACL، لأن معالجة سلاسل ACL تتضمن وظيفة تنفيذ أوامر.

سلاسل ACL كثيرة جدًا، لكن معظمها NULL (ربما يعود ذلك إلى ملف الإعدادات). هنا اخترت سلسلة acl_smtp_mail، وصيغة تنفيذ الأوامر فيها هي:

${run{command}}

التوزيع التقريبي للكومة كما يلي: 4

الكتلة الأولى هي ناتج فك ترميز base64، وتُستخدم لخطأ off-by-one، لذا يجب أن تكون في نهاية storeblock. لتسهيل الأمر، نطلب مباشرة كتلة أكبر من 0x2020 لتخزين نتيجة فك ترميز base64.

الكتلة الثانية هي sender_helo_name، وتُستخدم لتغطية الكتلة التالية. إن sender_helo_name لا تُخزَّن داخل storeblock، بل تُحجز مباشرة عبر malloc:

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

لذا يمكن أن يكون حجمها حسب الرغبة.

الكتلة الثالثة هي أيضًا ناتج فك ترميز base64، وتُستخدم أساسًا لتزييف الترويسة وتتعرض للتغطية، لذا يجب أن تكون في بداية storeblock. ولتسهيل الأمر، نطلب كتلة بحجم 0x2020 مباشرة.

الاستغلال

استغلالي (exp) بُني خطوة بخطوة بناءً على تحليلات الآخرين على الإنترنت؛ الفكرة العامة لم تتغير، لكن تخطيط الكومة يختلف قليلًا عن الآخرين، لذا تختلف بعض المعاملات الصغيرة.

أولًا، سننشئ unsortedbin بحجم 0x6060، ويمكن تحقيق ذلك بالأمر التالي فقط:

ehlo('a'*0x1000)

عندما يستقبل Exim «EHLO » + 'a'*0x1000، فإنه يولّد السلاسل الثلاث التالية داخل الدالة match_check_list في match.c:

*name* in helo_lookup_domains? no (end of list)
sender_fullhost = (*name*) [127.0.0.1]
sender_rcvhost = [127.0.0.1] (helo=*name*)
其中*name*为'a'*0x1000

بما أن طول name هو 0x1000، فإن كل سلسلة تشغل storeblock مستقلًا، وبالتالي ستكون هذه السلاسل الثلاث في ثلاث كتل storeblock متتالية.

تنزيل الأداة