
Docker लैब जो FOSSBilling pre-auth RCE श्रृंखला (CVE-2026-27604 auth bypass + CVE-2026-28496 Twig SSTI) को Python PoC और patched comparison target के साथ पुनरुत्पादित करती है।
इस रिपॉजिटरी में FOSSBilling प्री-ऑथ RCE चेन को पुनरुत्पादित और सत्यापित करने के लिए एक स्थानीय Docker लैब शामिल है, जो दो श्रृंखलाबद्ध कमजोरियों से बनी है:
| CVE | प्रकार | CVSS v4 | GHSA | विवरण |
|---|---|---|---|---|
| CVE-2026-27604 | ऑथ बायपास | 10.0 | GHSA-78x5-c8gw-8279 | API रोल चेकर में throw की कमी, एडमिन एंडपॉइंट्स को अनऑथेंटिकेटेड कॉलर्स के लिए उजागर करती है |
| CVE-2026-28496 | SSTI | 9.4 | GHSA-57mv-jm88-66jc | string_render API के माध्यम से अनसैंडबॉक्स्ड Twig टेम्पलेट रेंडरिंग |
FOSSBilling एक मुफ्त और ओपन-सोर्स बिलिंग और क्लाइंट मैनेजमेंट प्लेटफॉर्म है। संस्करण 0.5.4 से 0.7.2 प्रभावित हैं। FOSSBilling 0.8.0 दोनों कमजोरियों को पैच करता है।
यह लैब दो FOSSBilling संस्करणों की तुलना करती है:
| सेवा | FOSSBilling संस्करण | उद्देश्य | URL |
|---|---|---|---|
| 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, malware, persistence, external callbacks, database dumping, या destructive payloads शामिल नहीं हैं।
Pre-Auth RCE के लिए दोनों vulnerabilities का एक साथ काम करना आवश्यक है:```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 }}` का उपयोग करके श्रृंखला को प्रदर्शित करती है। `getDi()` के माध्यम से पूर्ण RCE पथ प्रदर्शित नहीं किया गया है।
## सत्यापित तथ्य
| दावा | प्रमाण | सत्यापन कैसे करें |
| ----- | -------- | ------------- |
| CVE-2026-27604 FOSSBilling API भूमिका प्रबंधन में एक प्रमाणीकरण बायपास है। | GHSA-78x5-c8gw-8279: भूमिका जाँचकर्ता में अनुपस्थित throw /api/system/ को व्यवस्थापक के रूप में हल करने की अनुमति देता है। | PoC चलाएँ: अतिथि पथ अस्वीकृत है, सिस्टम पथ व्यवस्थापक परिणाम लौटाता है। |
| CVE-2026-28496 FOSSBilling Twig रेंडरिंग में एक SSTI है। | GHSA-57mv-jm88-66jc: string_render _tpl को बिना सैंडबॉक्स के Twig createTemplate() में पास करता है। | PoC चलाएँ: सर्वर {{ 7*7 }} का मूल्यांकन करता है और 49 लौटाता है। |
| दोनों भेद्यताएँ FOSSBilling 0.5.4 से 0.7.2 को प्रभावित करती हैं। | सार्वजनिक सलाहकार प्रभावित संस्करण सीमा की पहचान करते हैं। | भेद्य (0.7.2) और पैच किए गए (0.8.0) लक्ष्यों की तुलना करें। |
| FOSSBilling 0.8.0 दोनों भेद्यताओं को पैच करता है। | पैच किया गया लक्ष्य परीक्षण किए गए एंडपॉइंट के लिए "Unknown API call" लौटाता है। | पोर्ट 8082 के विरुद्ध PoC चलाएँ। |
| प्रमाणीकरण बायपास अनधिकृत व्यवस्थापक पहुँच देता है। | /api/guest/ string_render को अस्वीकार करता है; /api/system/ बिना प्रमाणीकरण के परिणाम लौटाता है। | PoC का चरण 1 चलाएँ। |
| SSTI हमलावर-नियंत्रित टेम्पलेट्स का मूल्यांकन करता है। | {{ 7*7 }} भेद्य पथ के माध्यम से 49 लौटाता है। | PoC का चरण 2 चलाएँ। |
| श्रृंखला 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
The role checker यह सत्यापित करता है कि अनुरोधित role की अनुमति है या नहीं। हालाँकि, vulnerable संस्करणों में, अस्वीकृत roles के लिए exception instantiated होता है लेकिन कभी thrown नहीं होता:```php // Simplified vulnerable pattern if (!in_array($role, $allowed_roles)) { new \Exception("Role not allowed"); // BUG: missing "throw" }
क्योंकि अपवाद कभी नहीं फेंका जाता, सत्यापन चुपचाप पास हो जाता है। भूमिका `system` क्रॉन एडमिन पहचान में परिवर्तित हो जाती है, जिससे किसी भी अप्रमाणित कॉलर को पूर्ण एडमिन API पहुँच प्रदान हो जाती है।
सुरक्षा प्रभाव:```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 role आंतरिक cron admin identity से मैप होता है, जिसके पास पूर्ण प्रशासनिक विशेषाधिकार होते हैं।
string_render admin API method request data से _tpl प्राप्त करता है और इसे बिना sandbox enforcement के Twig template rendering pipeline में पास करता है:```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 प्रतिबंधों के रेंडर करता है। टेम्पलेट के पास टेम्पलेट संदर्भ में मौजूद ऑब्जेक्ट्स तक पहुंच होती है, जिसमें guest API handler भी शामिल है जो 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"