
केवल एडमिन के लिए टर्मिनल बूटस्ट्रैप रूट्स जो केवल लॉगिन स्थिति के लिए जाँचे जाते हैं, जो एक सामान्य टीम सदस्य को Coolify के रियलटाइम टर्मिनल बैकएंड को चलाने और टीम सर्वर पर कमांड निष्पादित करने देते हैं।
केवल-प्रशासक टर्मिनल बूटस्ट्रैप रूट्स ने केवल लॉगिन स्थिति की जाँच की, जिससे एक सामान्य टीम सदस्य Coolify के रियलटाइम टर्मिनल बैकएंड को चला सकता था और टीम सर्वर पर कमांड निष्पादित कर सकता था।
मुझे यह समस्या Coolify की समीक्षा करते हुए मिली, जो एक ओपन-सोर्स स्वयं-होस्टेड PaaS है, जिसमें एक बहुत ही सीधा सुरक्षा प्रश्न था:
क्या टर्मिनल एक्सेस वास्तव में बैकएंड ट्रस्ट बाउंड्री पर लागू किया गया है, या केवल UI में?
इस मामले में, उत्तर बुरा था।
Coolify का इरादा टर्मिनल एक्सेस को टीम प्रशासकों और मालिकों तक सीमित रखना था, लेकिन रियलटाइम टर्मिनल बूटस्ट्रैप रूट्स ने केवल यह जाँचा कि उपयोगकर्ता लॉगिन है या नहीं। इसने कम-विशेषाधिकार वाले टीम सदस्य को वेबसॉकेट टर्मिनल ट्रस्ट चेक को संतुष्ट करने और टीम सर्वर पर कमांड निष्पादन तक पहुँचने देता था।
मैंने इसे एक स्थानीय लैब में एंड-टू-एंड मान्य किया, जो कमजोर संस्करण से बनाई गई थी, और बाद में इसे निजी तौर पर रिपोर्ट किया। इस समस्या को CVE-2026-34048 के रूप में असाइन किया गया, जिसमें:
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H
Coolify: GitHub पर Coolify
CVE: CVE-2026-34048
यह Coolify को प्रभावित करता है, जो एक ओपन-सोर्स स्वयं-होस्टेड PaaS है। अपनी आधिकारिक साइट पर, Coolify बताता है कि इसके 3,641+ क्लाउड ग्राहक हैं, और यह वेबसाइटों, डेटाबेस, वेब एप्लिकेशन और 280+ वन-क्लिक सेवाओं को तैनात करने के लिए एक प्लेटफॉर्म के रूप में प्रस्तुत करता है। इसके आधिकारिक v4.0 चेंजलॉग में यह भी कहा गया है कि हजारों कंपनियों और लोगों ने 1-2 वर्षों से प्रोडक्शन में Coolify का उपयोग किया है।
photo0
कम-विशेषाधिकार वाले टीम सदस्य का सत्र -> /terminal/auth और /terminal/auth/ips केवल लॉगिन स्थिति की जाँच करते हैं -> रियलटाइम वेबसॉकेट उन प्रतिक्रियाओं पर भरोसा करता है -> सदस्य टीम सर्वर और दृश्य SSH कुंजी UUID को एनुमरेट करता है -> /terminal/ws सत्र स्वीकार करता है -> SSH-समर्थित PTY स्पॉन होता है -> टीम सर्वर पर शेल एक्सेस
Coolify एक स्वयं-होस्टेड PaaS और डिप्लॉयमेंट प्लेटफॉर्म है।
यह प्रबंधित करता है:
वह अंतिम क्षमता यहाँ महत्वपूर्ण है।
एक बार जब कोई प्लेटफॉर्म प्रबंधित होस्ट पर टर्मिनल खोल सकता है, तो उसका प्राधिकरण मॉडल सिर्फ एप्लिकेशन लॉजिक नहीं रह जाता। यह एक बुनियादी ढाँचे की ट्रस्ट बाउंड्री बन जाता है।
महत्वपूर्ण प्रश्न यह नहीं था कि क्या /terminal पेज केवल-प्रशासक दिखता है।
असली प्रश्न था:
क्या बैकएंड टर्मिनल पथ वास्तव में उसी प्राधिकरण सीमा को लागू करता है जब वेबसॉकेट सत्र बनाया जाता है?
इस मामले में, ऐसा नहीं हुआ।
टर्मिनल सुविधाएँ बुनियादी ढाँचे सॉफ्टवेयर में सबसे मूल्यवान सतहों में से एक हैं।
क्यों?
क्योंकि इनके बीच कोई भी बेमेल:
एक सामान्य एप्लिकेशन उपयोगकर्ता को शेल-सक्षम ऑपरेटर में बदल सकता है।
यही कारण है कि यह सतह परीक्षण के लायक थी।
मैं यादृच्छिक क्रैश या कॉस्मेटिक अनुमति बग की तलाश में नहीं था।
मैं एक मजबूत वर्ग की विफलता की तलाश में था:
क्या केवल-प्रशासक सुविधा UI द्वारा सुझाए गए की तुलना में कमजोर बैकएंड ट्रस्ट चेक पर निर्भर करती है?
यह सही प्रश्न था।
मैंने Coolify तक यादृच्छिक एंडपॉइंट को फज करके और कुछ दिलचस्प की उम्मीद करके नहीं पहुँचा।
मजबूत पथ पहले उच्चतम जोखिम वाली सीमा की पहचान करना था।
Coolify के लिए, वह सीमा टर्मिनल वर्कफ़्लो थी:
इसने बूटस्ट्रैप रूट्स को देखने के लिए सही स्थान बना दिया।
और वहीं समस्या थी।
मूल कारण टर्मिनल UI और टर्मिनल वेबसॉकेट बूटस्ट्रैप रूट्स के बीच एक प्राधिकरण बेमेल था।
कमजोर संशोधन पर:
GET /terminal को can.access.terminal द्वारा संरक्षित किया गया थाPOST /terminal/auth ने केवल auth()->check() की जाँच कीPOST /terminal/auth/ips ने केवल auth()->check() की जाँच कीइसका मतलब है कि UI टर्मिनल प्राधिकरण द्वारा गेटेड था, लेकिन बैकएंड ट्रस्ट बाउंड्री सरल प्रमाणित-सत्र उपस्थिति द्वारा गेटेड थी।
रियलटाइम सेवा ने तब उन दो रूट्स पर पूरी तरह से भरोसा किया।
docker/coolify-realtime/terminal-server.js में:
verifyClient() ने /terminal/auth पर POST किया/terminal/auth/ips पर POST कियायह पूरी बग श्रृंखला है।
क्योंकि एक सामान्य टीम सदस्य नियमित एप्लिकेशन सतह से आवश्यक इनपुट बना सकता था:
/servers ने दृश्य सर्वर UUID को उजागर किया/server/{uuid} ने प्रस्तुत फ़ॉर्म फ़ील्ड में ip, user, और port को उजागर किया/security/private-key ने दृश्य टीम प्राइवेट कुंजी UUID को उजागर किया/var/www/html/storage/app/ssh/keys/ssh_key@<uuid>
तो शोषण पथ सीधा था:
/terminal/auth कॉल करें/terminal/auth/ips कॉल करें/terminal/ws से कनेक्ट करेंयह कोई सैद्धांतिक बेमेल नहीं है। यह एक व्यावहारिक बैकएंड प्राधिकरण विफलता है।
महत्वपूर्ण अंतर बैकएंड ट्रस्ट और कमांड निष्पादन है।
कई बग ऐसे दिखते हैं:
अकेले यह पर्याप्त नहीं है।
असली प्रश्न है:
क्या कम-विशेषाधिकार वाला उपयोगकर्ता अभी भी उन बैकएंड ट्रस्ट चेक को संतुष्ट कर सकता है जो मायने रखते हैं?
यहाँ, उत्तर हाँ था।
यह नहीं था:
यह था:
इसलिए यह एक वास्तविक सुरक्षा समस्या थी।
मैंने इसे एक नियंत्रित स्थानीय लैब में मान्य किया, जो इससे बनाई गई थी:
06f60c9a98bead0c932c6adf7fd43a45d9149048
लैब ने उपयोग किया:
http://127.0.0.1:18000[email protected]localhost -> coolify-testing-host:22 root के रूप मेंsshws://127.0.0.1:6002/terminal/wsसदस्य खाते का इरादा सामान्य प्रशासक-उन्मुख UI के माध्यम से टर्मिनल एक्सेस नहीं था।
इसने अपेक्षित सुरक्षा सीमा स्थापित की।
सदस्य सत्र का उपयोग करके, मैंने भेजा:
POST /terminal/authPOST /terminal/auth/ipsदोनों सफल हुए।
/terminal/auth/ips ने टर्मिनल-अधिकृत होस्ट लौटाए जिनमें शामिल थे:
coolify-testing-host
host.docker.internal
localhost
127.0.0.1
इसने साबित किया कि बैकएंड बूटस्ट्रैप रूट्स ने सदस्य सत्र पर भरोसा किया।
सामान्य प्रमाणित पृष्ठों से, वही सदस्य एनुमरेट कर सकता था:
यह गुप्त कुंजी सामग्री के प्रकटीकरण के बिना टर्मिनल पथ चलाने के लिए पर्याप्त था।
उसी प्रमाणित सत्र और XSRF टोकन का उपयोग करके, मैंने कनेक्ट किया:
ws://127.0.0.1:6002/terminal/ws
पेलोड ने वही कमांड प्रारूप उपयोग किया जो टर्मिनल बैकएंड को उम्मीद थी:
{"command":["timeout 30 ssh -i /var/www/html/storage/app/ssh/keys/ssh_key@ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o PasswordAuthentication=no -o ConnectTimeout=10 -o ServerAliveInterval=5 -o RequestTTY=no -o LogLevel=ERROR -p '22' 'root'@'coolify-testing-host' 'bash -se' << \\P0C\nprintf '__COOLIFY_POC_BEGIN__\\n'; id; whoami; hostname; printf '__COOLIFY_POC_END__\\n'\nP0C"]}