
مستودع PoC لـ CVE-2025-68147: تخزين نص برمجي عبر المواقع (XSS) في OpenSourcePOS. تسمح الثغرة بتصعيد الامتيازات عبر حقن جافاسكربت خبيث في وحدة إعدادات المتجر (Store Config). يتضمن تفاصيل الحمولة والتحقق من التصحيح (v3.4.0). باحث أمني: Aditya Singh (Nixon-H).
| البيانات الوصفية | التفاصيل |
|---|
| معرّف CVE | CVE-2025-68147 |
| الخطورة | عالية CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:C/C:H/I:H/A:N |
| نوع الثغرة | البرمجة النصية عبر المواقع المخزّنة (CWE-79) |
| الإصدارات المتأثرة | OpenSourcePOS v3.4.0, v3.4.1 |
| الإصدار المُصحَّح | v3.4.2 |
| المكوّن المعرّض للثغرة | وحدة إعدادات المتجر (حقل Return Policy) |
| المُبلِّغ | Aditya Singh (Nixon-H) |
تم اكتشاف ثغرة البرمجة النصية عبر المواقع المخزّنة (XSS) في وحدة إعدادات المتجر في OpenSourcePOS. فشل التطبيق في تنظيف المدخلات المقدمة من المستخدم بشكل صحيح في حقل "سياسة الإرجاع" قبل تخزينها في جدول قاعدة البيانات ospos_app_config.
سمح هذا العيب لمهاجم مصادَق يتمتع بصلاحيات التكوين (أو مهاجم يستغل سلسلة هجمات CSRF منفصلة) بحقن حمولات JavaScript عشوائية. ونظرًا لأن "سياسة الإرجاع" تُعرض ديناميكيًا على كل إيصال بيع، فإن الحمولة المحقونة تُنفَّذ تلقائيًا في متصفح أي مستخدم—بما في ذلك أمناء الصندوق ذوو الصلاحيات المنخفضة، أو المسؤولون الآخرون، أو العملاء—كلما تم إنشاء إيصال أو عرضه.
تكمن الثغرة في قالب عرض الإيصال: app/Views/sales/receipt_default.php.
يسترجع التطبيق سلسلة "سياسة الإرجاع" من مصفوفة التكوين العامة ($this->config['return_policy']) ويجهزها للعرض.
nl2br() لتحويل الأسطر الجديدة إلى فواصل أسطر HTML (<br>).nl2br() لا تنظّف الأحرف الخاصة في HTML. فهي تترك وسومًا مثل <script> و`` وخصائص onload سليمة تمامًا.الكود المعرّض للثغرة (قبل التصحيح):
<div id="sale_return_policy">
<?php echo nl2br($this->config['return_policy']); ?>
</div>
عندما يحفظ المسؤول التكوين، تُخزَّن الحمولة خام في قاعدة البيانات.
ospos_app_configreturn_policyPolicy Text... <script>alert('XSS')</script>نظرًا لعدم وجود تنظيف للمدخلات في جانب وحدة التحكم (Config.php) ولا هروب للمخرجات في جانب العرض (receipt_default.php)، فإن التطبيق معرّض لثغرة XSS المخزّنة.
يستهدف الهجوم لوحة إعدادات المتجر لكنه يؤثر على وحدة المبيعات/الإيصالات.
http://[TARGET]/config (طلب POST لحفظ التكوين)http://[TARGET]/sales/receipt/[SALE_ID]الخطوة 1: الحقن
قمنا بتسجيل الدخول كمسؤول وانتقلنا إلى إعدادات المتجر -> عام. في منطقة النص الخاصة بـ "سياسة الإرجاع"، حقنّا الحمولة المحددة التالية:
Standard Return Policy: No Refunds.
<script>alert('XSS_BY_NIXON_SUCCESSFUL')</script>
الخطوة 2: الاستمرارية
عند النقر على "إرسال"، أرسل التطبيق طلب POST إلى /config/save. تم حفظ الحمولة بنجاح في قاعدة البيانات.
الخطوة 3: التشغيل
للتحقق من التأثير على المستخدمين الآخرين:
http://localhost/sales/receipt/1). يحلّل المتصفح عنصر return_policy div، ويصادف وسم <script>، وينفّذ JavaScript فورًا.النتيجة الملاحظة:
ظهرت نافذة تنبيه في المتصفح تحمل الرسالة: XSS_BY_NIXON_SUCCESSFUL.
لقطة الشاشة 1: تشغيل التنبيه
لقطة الشاشة 2: الحمولة في التكوين
🎥 عرض فيديو توضيحي: انقر للتحميل / مشاهدة فيديو PoC
هذه ثغرة تغيير النطاق (S:C) لأن الهجوم يُخزَّن على الخادم لكنه يُنفَّذ في سياق متصفح الضحية.
/sales/receipt/105). يُنفَّذ السكربت بصمت، ويرسل document.cookie (الذي يحتوي على معرّف ospos_session) إلى خادم المهاجم./employees/save.hacker / password123) فورًا في الخلفية. لا يرى الضحية سوى الإيصال، بينما يحصل المهاجم على باب خلفي دائم.تم إصلاح الثغرة في OpenSourcePOS v3.4.2.
طبّق القائم على الصيانة تصحيحًا ينفّذ ترميز المخرجات المراعي للسياق (Context-Aware Output Encoding). أصبحت قيمة التكوين الآن مغلّفة في دالة المساعدة العامة esc() الخاصة بـ CodeIgniter قبل تمريرها إلى nl2br().
التصحيح (Commit 22297a):
<div id="sale_return_policy">
<?php echo nl2br(esc($this->config['return_policy'])); ?>
</div>
التحقق: بعد الترقية إلى v3.4.2، يتم عرض نفس الحمولة كنص غير ضار:
Standard Return Policy: No Refunds. <script>alert('XSS_BY_NIXON_SUCCESSFUL')</script>
22297a) والتحقق منه من قبل الباحث.