उजागर .env फ़ाइलें और लीक हुई कुंजियाँ

उजागर .env फ़ाइल एक कॉन्फ़िगरेशन फ़ाइल है — वही जिसमें आपका डेटाबेस पासवर्ड, आपके मेल क्रेडेंशियल और आपकी API कुंजियाँ हैं — जिसे आपका वेब सर्वर नाम बताने वाले किसी भी व्यक्ति को सौंप देता है, और उजागर .git फ़ोल्डर आपके पूरे सोर्स इतिहास के साथ वही दुर्घटना है। दोनों में से किसी के लिए भी हमलावर को कुछ तोड़ने की ज़रूरत नहीं है: फ़ाइल बस उस जगह पर पड़ी है जिसे सर्वर प्रकाशित करता है, और एक साधारण GET अनुरोध उसे डाउनलोड कर लेता है। यह लेख बताता है कि यह कैसे होता है — दस्तावेज़ रूट की गलतियाँ, स्वयं रिपॉज़िटरी को परोसने वाले स्टैटिक होस्ट, ऐसे बिल्ड आर्टिफ़ैक्ट जिनका किसी ने ऑडिट नहीं किया —, खोजने वाला पहले घंटे में कुंजियों के साथ क्या करता है, और बाद में फ़ाइल हटाना प्रतिक्रिया का सबसे छोटा हिस्सा क्यों है। अपनी साइट अभी जांचने के लिए, लीक हुए सीक्रेट स्कैनर चलाएँ और अपने परिणामों के साथ पढ़ें।

निजी फ़ाइल सार्वजनिक कैसे बनती है: दस्तावेज़ रूट

हर वेब सर्वर के पास एक दस्तावेज़ रूट होता है: वह निर्देशिका जिसकी सामग्री परिभाषा के अनुसार सार्वजनिक है। उसमें रखी गई हर चीज़ — जानबूझकर या दुर्घटनावश — URL द्वारा अनुरोध की जा सकती है, चाहे कोई पेज उससे लिंक करता हो या नहीं। क्लासिक दुर्घटना वह प्रोजेक्ट है जिसे पूरे कार्य निर्देशिका को सर्वर पर कॉपी करके परिनियोजित किया जाता है: एप्लिकेशन कोड, जो वहाँ होना चाहिए, उसके बगल वाली .env फ़ाइल, उसके अंदर वाले .git फ़ोल्डर, संपादक बैकअप प्रतियों, माइग्रेशन से पहले किसी के बनाए डेटाबेस डंप, और पिछले महीने के संस्करण के आर्काइव के साथ आता है। सर्वर इनमें भेद नहीं कर सकता। वह फ़ाइलें परोसता है; निजी वाली भी फ़ाइलें हैं।

फ़्रेमवर्क परंपराएँ जाल में फँसना आसान बनाती हैं। .env फ़ाइल दस्तावेज़ रूट से एक स्तर ऊपर, या परिनियोजित ट्री से पूरी तरह बाहर होनी चाहिए, और एप्लिकेशन को उसे डिस्क से पढ़ना चाहिए — कभी वेब सर्वर के माध्यम से नहीं। लेकिन विकास सर्वर खुशी से प्रोजेक्ट रूट परोसते हैं, छोटे परिनियोजन सब कुछ public_html में खींच ले जाते हैं, और ट्यूटोरियल से कॉपी किया गया कॉन्फ़िगरेशन दस्तावेज़ रूट को स्वयं प्रोजेक्ट की ओर इंगित कर सकता है। जब यह होता है तो कुछ भी दिखाई देने लायक नहीं टूटता, और ठीक यही समस्या है: साइट पूरी तरह काम करती है, फ़ाइल सार्वजनिक है, और सबसे पहले ध्यान देने वाला वह है जो /.env का अनुरोध करता है — वह अनुरोध जो स्वचालित स्कैनर इंटरनेट की हर साइट के विरुद्ध लगातार भेजते हैं।

स्टैटिक होस्ट, परोसी गई रिपॉज़िटरी और बिल्ड आर्टिफ़ैक्ट

स्टैटिक होस्टिंग सर्वर कॉन्फ़िगरेशन को समीकरण से हटा देती है और उसे एक सरल नियम से बदल देती है: प्रकाशन निर्देशिका में जो है वह प्रकाशित होता है। किसी रिपॉज़िटरी को आउटपुट निर्देशिका को प्रोजेक्ट रूट पर सेट करके स्टैटिक होस्ट पर परिनियोजित करें और होस्ट उस रिपॉज़िटरी को वफ़ादारी से परोसेगा — यदि वह आउटपुट में कॉपी हुआ था तो .git सहित। उजागर .git दिखने से बदतर है: HEAD फ़ाइल और कॉन्फ़िगरेशन संरचना साबित करते हैं, ऑब्जेक्ट फ़ाइलों में हर कभी कमिट किया गया blob होता है, और साधारण Git टूलिंग से पूरा इतिहास पुनर्निर्मित किया जा सकता है — उन सीक्रेट सहित जो एक बार कमिट किए गए और बाद के कमिट में "हटाए" गए, जो उन्हें कार्य ट्री से हटाता है और कहीं और से नहीं।

बिल्ड आर्टिफ़ैक्ट उजागर की दूसरी, शांत श्रेणी बनाते हैं। JavaScript बंडलर कोड द्वारा संदर्भित चीज़ों को इनलाइन करते हैं, इसलिए बिल्ड समय पर पर्यावरण चर से पढ़ी गई API कुंजी भेजे गए बंडल के अंदर एक शाब्दिक स्ट्रिंग के रूप में समाप्त हो सकती है — डिज़ाइन द्वारा सार्वजनिक, हर आगंतुक द्वारा पठनीय, और किसी अनुमति जांच द्वारा कभी चिह्नित नहीं, क्योंकि वह फ़ाइल सार्वजनिक होनी ही थी। सोर्स मैप मूल सोर्स को बंडल के बगल में भेजकर इसे और बढ़ा देते हैं। इनमें से किसी के लिए भी गलत कॉन्फ़िगर किए गए सर्वर की ज़रूरत नहीं है; बस एक ऐसे बिल्ड की ज़रूरत है जिसका बाहर से कभी निरीक्षण न हुआ हो।

तीसरा पैटर्न बचा हुआ हिस्सा है: परिनियोजन स्क्रिप्ट जो आर्काइव को वेब रूट में खोलती हैं और आर्काइव को वहीं छोड़ देती हैं, बैकअप प्लगइन जो डंप को वेब-सुलभ फ़ोल्डर में लिखते हैं, संपादक द्वारा सहेजा गया config.php.bak — जिसे कई सर्वर ठीक इसलिए सादे पाठ के रूप में परोसते हैं क्योंकि एक्सटेंशन अब PHP हैंडलर से मेल नहीं खाता। हर बचा हुआ हिस्सा किसी निजी चीज़ की पूरी प्रति है, एक पूर्वानुमानित पते पर।

हमलावर पहले घंटे में क्या करते हैं

खोज स्वचालित और निरंतर है। स्कैनर विशाल पता श्रेणियों में ज्ञात पथों — env फ़ाइलें, Git के आंतरिक भाग, कॉन्फ़िगरेशन नाम, बैकअप एक्सटेंशन — को गिनते हैं, और ताज़ा उजागर आमतौर पर घंटों के भीतर, अक्सर उससे तेज़, मिल जाता है। आपके सर्वर पर जो आता है वह 200 लौटाने वाला एक साधारण GET अनुरोध है; कोई अलार्म नहीं है, क्योंकि सर्वर के दृष्टिकोण से कुछ भी असामान्य नहीं हुआ। इसलिए मान लें कि जो फ़ाइल एक दिन भी सार्वजनिक रही वह डाउनलोड हो गई, और सबूत का भार उल्टी दिशा में चलता है।

छँटाई भी स्वचालित है। डाउनलोड की गई .env सेकंडों में पार्स होती है: डेटाबेस क्रेडेंशियल किसी भी पहुँच योग्य डेटाबेस पोर्ट पर आज़माए जाते हैं, क्लाउड कुंजियाँ एक हानिरहित API कॉल से सत्यापित होती हैं जो बताती है कि वे जीवित हैं या नहीं, मेल क्रेडेंशियल भेजने के लिए आज़माए जाते हैं, और भुगतान कुंजियों का मोड जांचा जाता है — लाइव-मोड भुगतान कुंजी और उत्पादन डेटाबेस क्रेडेंशियल जैकपॉट हैं, क्योंकि हर एक सीधे पैसे या डेटा में बदलता है। मान्य कुंजियाँ तेज़ी से उपयोग, व्यापार या रखी जाती हैं, क्योंकि उनके मालिक किसी भी समय उन्हें रोटेट कर सकते हैं; पहला घंटा वह समय है जब उजागर कुंजी सबसे अधिक मूल्यवान होती है, और वह कुशलता से बिताया जाता है।

फ़ाइल हटाना पर्याप्त क्यों नहीं

फ़ाइल हटाने से नए डाउनलोड रुक जाते हैं। यह उन प्रतियों के लिए कुछ नहीं करता जो पहले से मौजूद हैं: खोजने वाले की प्रति, ज़ाहिर है, लेकिन वे भी जो आपने स्वयं बनाईं — आपके CDN या कॉर्पोरेट प्रॉक्सी द्वारा कैश की गई प्रतिक्रिया, खोज इंजन या आर्काइव सेवा के क्रॉल में स्नैपशॉट, वह बंडल जो ब्राउज़र पहले ही डाउनलोड कर चुका है। जब तक हर कैश साफ़ और समाप्त न हो जाए, "हटाई गई" फ़ाइल अभी भी उस बुनियादी ढाँचे द्वारा परोसी जा सकती है जिसे आप नियंत्रित करते हैं लेकिन साफ़ करना भूल गए, और आपके नियंत्रण से बाहर वाला संस्करण हमेशा के लिए बाहर है।

इसीलिए पुष्ट उजागर की पहली प्रतिक्रिया हटाना नहीं, रोटेशन है: उजागर क्रेडेंशियल को रद्द करें और नया जारी करें, ताकि दुनिया की हर प्रति उसी क्षण बेकार हो जाए। रोटेशन का एक क्रम है — प्रतिस्थापन जारी करें, उसे परिनियोजित करें, सत्यापित करें कि सेवा काम करती है, फिर पुराने क्रेडेंशियल को रद्द करें — और यह हर उस चीज़ तक फैलता है जिसे उजागर सामग्री खोल सकती है: .git उजागर का अर्थ है इतिहास में कभी प्रकट हुए हर सीक्रेट को रोटेट करना, केवल वर्तमान वालों को नहीं, क्योंकि जो खुला है वह इतिहास ही है। उसके बाद, उजागर पथों के लिए अपने एक्सेस लॉग पढ़ें: वे बताते हैं कि क्या आप सबसे पहले जानने वाले थे, और पहले की प्राप्तियाँ कॉन्फ़िगरेशन घटना को एक बहुत अलग चेकलिस्ट वाली भंग जाँच में बदल देती हैं।

जांच सूची की व्याख्या — और रोकथाम चेकलिस्ट

लीक हुए सीक्रेट स्कैनर जैसा स्कैनर फ़ाइलों को केवल नाम से मांग सकता है, इसलिए उसकी सूची ज्ञात समूह है: /.env और उसके पर्यावरण प्रकार, /.git/HEAD और /.git/config, परिचित कॉन्फ़िगरेशन फ़ाइल नाम, बैकअप और आर्काइव एक्सटेंशन, और कुंजी फ़ाइल नाम — साथ ही पेज की अपनी स्क्रिप्ट, कुंजी-आकार की स्ट्रिंग के लिए खोजी गईं। ईमानदार सीमा दोनों ओर काटती है: स्कैनर केवल वही खोजता है जो वह मांगता है, और इसीलिए वह निष्कर्ष की पुष्टि स्थिति कोड से नहीं, सामग्री से करता है। आपके मुखपृष्ठ को लौटाने वाला 200 सब कुछ पकड़ने वाला मार्ग है, लीक नहीं, और कोई भी रिपोर्ट जो उसे लीक गिनती है वह स्वयं को फुला रही है। संबंधित आपूर्ति-श्रृंखला जोखिम — वे स्क्रिप्ट जो आप जानबूझकर दूसरों से लोड करते हैं — तृतीय-पक्ष स्क्रिप्ट और आपूर्ति-श्रृंखला जोखिम में शामिल है।

रोकथाम ज़्यादातर स्थान और इनकार की एक परत है। सीक्रेट को दस्तावेज़ रूट से बाहर और रिपॉज़िटरी के प्रकाशन आउटपुट से बाहर रखें; सर्वर को खतरनाक नामों को तब भी इनकार करने पर मजबूर करें जब वे वहाँ आ गिरें — डॉटफ़ाइलों, env और कॉन्फ़िगरेशन एक्सटेंशन, आर्काइव और कुंजी सामग्री के लिए इनकार नियम, उन्हें अनुरोध करके परीक्षित —; परिनियोजन आर्टिफ़ैक्ट से .git हटाएँ या उसे सीधे अवरुद्ध करें। पाइपलाइन में, CI में सीक्रेट स्कैनिंग जोड़ें — कमिट पर, ताकि कुंजी भेजे जाने से पहले रुक जाए, और निर्मित आर्टिफ़ैक्ट पर, ताकि बंडल की गई कुंजी किसी अजनबी के बजाय आउटपुट में पकड़ी जाए। अंत में, स्वयं नियमित रूप से और हर परिनियोजन परिवर्तन के बाद स्कैन करें: इस लेख के उजागर सभी मूक हैं, और किसी और से पहले अपने उजागर के बारे में जानने का एकमात्र तरीका है अपने ही सर्वर से वही प्रश्न पूछना जो स्कैनर पूछते हैं।

स्रोत और आगे की पठन सामग्री

अक्सर पूछे जाने वाले प्रश्न

मैंने अपनी उजागर .env फ़ाइल हटा दी। क्या अब मैं सुरक्षित हूँ?

अभी नहीं। हटाने से नए डाउनलोड रुकते हैं, लेकिन प्रतियाँ खोजने वाले के हाथों में, CDN और प्रॉक्सी कैश में, और क्रॉल व आर्काइव में मौजूद हो सकती हैं। फ़ाइल में मौजूद हर क्रेडेंशियल को रोटेट करें — पुरानी कुंजियाँ रद्द करें और नई जारी करें —, अपने कैश साफ़ करें, और उस पथ के एक्सेस लॉग जांचें। केवल रोटेशन प्रतियों को बेकार बनाता है।

मेरी साइट /.env के लिए 200 लौटाती है। क्या फ़ाइल उजागर है?

ज़रूरी नहीं। कई साइटें हर अज्ञात पथ पर 200 और अपने मुखपृष्ठ या ऐप खोल से जवाब देती हैं — सब कुछ पकड़ने वाला फ़ॉलबैक। मायने सामग्री रखती है: यदि प्रतिक्रिया का मुख्य भाग आपका पेज है, तो कुछ भी उजागर नहीं है; यदि वह वास्तविक मानों वाली कुंजी–मान पंक्तियाँ हैं, तो है। भरोसेमंद स्कैनर सामग्री से पुष्टि करता है और नंगे 200 को अपुष्ट के रूप में अलग सूचीबद्ध करता है।

यह दोबारा न हो इसके लिए CI में क्या चलना चाहिए?

दो क्षणों में दो जांचें: कमिट पर सीक्रेट स्कैनर, जो कुंजी को रिपॉज़िटरी में प्रवेश करने से रोकता है, और निर्मित आर्टिफ़ैक्ट व परिनियोजित आउटपुट निर्देशिका की जांच, जो बिल्ड द्वारा इनलाइन की गई और परिनियोजन द्वारा कॉपी की गई चीज़ों को पकड़ती है। अंतिम परत के रूप में डॉटफ़ाइलों और कुंजी सामग्री के लिए सर्वर इनकार नियम जोड़ें, और परिनियोजन परिवर्तनों के बाद बाहरी जांच दोबारा चलाएँ।