
Consul Template का writeToFile सहायक, ऑपरेटर द्वारा आपूर्ति किए गए गंतव्य को सीधे खोलता था और लिंक किए गए पथ घटकों का अनुसरण करता था, जिससे रेंडर किया गया आउटपुट इच्छित निर्देशिका से बाहर निकलकर किसी पहले से मौजूद फ़ाइल को अधिलेखित कर सकता था।
Consul Template का writeToFile हेल्पर ऑपरेटर-आपूर्ति किए गए गंतव्य को सीधे खोलता था और लिंक किए गए पथ घटकों का अनुसरण करता था, जिससे रेंडर किया गया आउटपुट इच्छित निर्देशिका से बाहर निकलकर किसी पूर्व-मौजूदा फ़ाइल को अधिलेखित कर सकता था।
मुझे यह समस्या HashiCorp Consul Template की समीक्षा करते समय मिली, जिसमें एक सीधा फाइलसिस्टम सुरक्षा प्रश्न ध्यान में था:
यदि writeToFile को ऐसा पथ मिलता है जो इच्छित निर्देशिका के अंदर प्रतीत होता है, तो क्या यह सत्यापित करता है कि फाइलसिस्टम वास्तव में डेटा कहाँ लिखेगा?
इस मामले में, उत्तर नहीं था।
writeToFile टेम्पलेट हेल्पर ने अंतिम उपयोगकर्ता-आपूर्ति पथ को os.Create() या os.OpenFile() के माध्यम से सीधे खोला।
वे ऑपरेशन गंतव्य पथ में पहले से मौजूद प्रतीकात्मक लिंक, डायरेक्टरी जंक्शन और समकक्ष फाइलसिस्टम पुनर्निर्देशन का अनुसरण करते थे।
इसका मतलब था कि पथ स्ट्रिंग ऑपरेटर के इच्छित रूट के अंतर्गत बनी रह सकती थी जबकि वास्तविक लेखन कहीं और होता था।
मेरे नियंत्रित प्रमाण-की-अवधारणा में, एक लिंक किए गए पैरेंट निर्देशिका ने रेंडर किए गए आउटपुट को इच्छित ट्री के बाहर पुनर्निर्देशित किया और एक पूर्व-मौजूदा लक्ष्य फ़ाइल को नष्ट कर दिया।
वह समस्या CVE-2026-14361 बन गई।
HashiCorp बुलेटिन: HCSEC-2026-20
IBM बुलेटिन: CVE-2026-14361 security bulletin
CVE: CVE-2026-14361
इसमें ठीक हुआ: 0.42.1
photo0
ऑपरेटर-आपूर्ति किया गया गंतव्य इच्छित रूट के अंदर दिखाई देता है -> हमलावर लिंक किए गए पैरेंट या अंतिम पथ घटक को पूर्व-स्थित करता है -> writeToFile पथ को सीधे खोलता है -> फाइलसिस्टम लेखन को इच्छित निर्देशिका के बाहर हल करता है -> रेंडर किया गया रहस्य पुनर्निर्देशित हो जाता है -> पूर्व-मौजूदा लक्ष्य अधिलेखित हो सकता है
Consul Template Consul और Vault जैसे स्रोतों से डेटा रेंडर करता है।
writeToFile हेल्पर एक टेम्पलेट को चयनित सामग्री को एक अलग स्थानीय फ़ाइल में लिखने देता है, साथ ही अनुरोधित स्वामी, समूह और अनुमति मोड लागू करता है।
HashiCorp का प्रलेखन विशेष रूप से PKI सामग्री के साथ हेल्पर को प्रदर्शित करता है:
private key -> writeToFile /my/path/to/cert.key
certificate authority -> writeToFile /my/path/to/cert.pem
certificate -> append to /my/path/to/cert.pem
यह इसे एक सामान्य आउटपुट हेल्पर से अधिक बनाता है।
इस सीमा को पार करने वाली सामग्री में शामिल हो सकते हैं:
महत्वपूर्ण प्रश्न यह नहीं था कि क्या writeToFile अनुरोधित फ़ाइलनाम बना सकता है।
वास्तविक प्रश्न यह था:
क्या प्रक्रिया ऑपरेटर के इच्छित फाइलसिस्टम स्थान पर लिखती है, या केवल उस ऑब्जेक्ट पर जिसे पथ open के समय हल करता है?
भेद्य संस्करणों में, इसने बाद वाले पर भरोसा किया।
लेखन हेल्पर उच्च-मूल्य वाली सुरक्षा सतहें हैं क्योंकि वे अनुप्रयोग डेटा से फाइलसिस्टम परिवर्तन में प्रवेश करती हैं।
दिलचस्प विफलताएँ अक्सर क्लासिक ../ ट्रैवर्सल नहीं होती हैं।
वे समाधान विफलताएँ हैं:
यह विशेष रूप से महत्वपूर्ण है जब प्रक्रिया हमलावर की तुलना में अधिक फाइलसिस्टम विशेषाधिकारों के साथ चलती है।
एक कम-विशेषाधिकार वाला स्थानीय हमलावर सीधे संवेदनशील फ़ाइल को अधिलेखित करने में सक्षम नहीं हो सकता है।
लेकिन यदि वे इच्छित लेखन निर्देशिका के अंतर्गत एक पथ घटक को प्रभावित कर सकते हैं, तो एक अधिक विशेषाधिकार प्राप्त Consul Template प्रक्रिया उनके लिए लेखन कर सकती है।
यही वह सीमा थी जिस पर मैंने ध्यान केंद्रित किया।
मैंने इसे एक सामान्य पथ ट्रैवर्सल समीक्षा के रूप में नहीं देखा।
आपूर्ति किए गए पथ को .. खंडों की आवश्यकता नहीं थी।
यह पूरे समय शाब्दिक रूप से इच्छित रूट के अंदर रह सकता था।
अधिक मजबूत प्रश्न यह था:
क्या संवेदनशील सामग्री लिखे जाने से पहले लिंक किए गए गंतव्य घटकों को अस्वीकार कर दिया जाता है?
वह प्रश्न दोनों के लिए मायने रखता है:
दूसरा मामला विशेष रूप से उपयोगी है क्योंकि लॉग और कॉन्फ़िगरेशन अभी भी अपेक्षित निर्देशिका के अंतर्गत एक निर्दोष-दिखने वाला पथ दिखाते हैं।
फाइलसिस्टम इसे कहीं और हल करता है।
मूल कारण लिंक-जागरूक सत्यापन के बिना प्रत्यक्ष पथ-आधारित फ़ाइल निर्माण था।
परीक्षण किए गए रिवीज़न पर, writeToFile() ने दो open पथों में से एक का चयन किया।
अपेंड मोड उपयोग करता था:
f, err = os.OpenFile(
path,
os.O_APPEND|os.O_WRONLY|os.O_CREATE,
perm,
)
सामान्य लेखन मोड उपयोग करता था:
dirPath := filepath.Dir(path)
if _, err := os.Stat(dirPath); err != nil {
err := os.MkdirAll(dirPath, os.ModePerm)
if err != nil {
return "", err
}
}
f, err = os.Create(path)
फ़ाइल खोले जाने से पहले किसी भी पथ ने लिंक किए गए गंतव्य घटकों को अस्वीकार नहीं किया।
यह मायने रखता है क्योंकि:
os.Create(path) मौजूदा फाइलसिस्टम पुनर्निर्देशन का अनुसरण करता है और हल की गई फ़ाइल को छोटा करता हैos.OpenFile(path, ...) अपेंड मोड के दौरान लिंक किए गए पथ घटकों का अनुसरण करता हैवही पथ-आधारित धारणा लेखन के बाद भी जारी रही।
स्वामित्व और अनुमतियाँ फिर से पथ का उपयोग करके लागू की गईं:
err = os.Chown(path, uid, gid)
err = os.Chmod(path, perm)
इसका मतलब था कि मेटाडेटा संचालन भी पहले से खुले फ़ाइल डिस्क्रिप्टर के बजाय एक परिवर्तनीय पथ नाम से बंधे थे।
क्योंकि हमलावर writeToFile चलने से पहले पुनर्निर्देशन तैयार कर सकता है।
मूल आक्रमण के लिए किसी संभाव्य दौड़ की आवश्यकता नहीं है।
अनुक्रम सीधा है:
writeToFile इसे सीधे खोलता हैयही पूरी भेद्यता है।
यह सत्य है कि ऑपरेटिंग सिस्टम सामान्यतः पथ-आधारित फ़ाइल खोलने के दौरान सिमलिंक का अनुसरण करते हैं।
इससे यह सुरक्षित अनुप्रयोग व्यवहार नहीं बन जाता।
सुरक्षा प्रश्न यह नहीं है:
"क्या Go ने प्रलेखित अनुसार व्यवहार किया?"
वास्तविक प्रश्न यह है:
क्या संवेदनशील रेंडर किए गए डेटा को लिखने वाले हेल्पर ने सत्यापित किया कि हल किया गया गंतव्य ऑपरेटर के इच्छित स्थान से मेल खाता है?
भेद्य संस्करणों में, उसने नहीं किया।
यह अंतर मायने रखता है क्योंकि Consul Template चल सकता है:
उस संदर्भ में हमलावर-स्थित फाइलसिस्टम पुनर्निर्देशन का अनुसरण करना एक वास्तविक विशेषाधिकार और विश्वास-सीमा समस्या पैदा करता है।
मैंने परीक्षण किए गए कमिट पर सटीक writeToFile व्यवहार के आसपास एक स्टैंडअलोन रिप्रोड्यूसर बनाया।
नियंत्रित सेटअप में उपयोग किया गया:
writeToFile को दी गई नियंत्रित गुप्त सामग्रीपुनरुत्पादन प्रवाह था:
अवलोकित व्यवहार था:
writeToFile ने पुनर्निर्देशन का अनुसरण कियाइसने दावे के दोनों हिस्सों की स्थापना की:
एक अंतिम-घटक सिमलिंक पहले से ही असुरक्षित लिंक अनुसरण प्रदर्शित करेगा।
लेकिन एक लिंक किया गया पैरेंट घटक एक अधिक मजबूत परिचालन बिंदु साबित करता है:
पूर्व-मौजूदा लक्ष्य भी मायने रखता था।
इसके बिना, PoC केवल अप्रत्याशित फ़ाइल निर्माण दिखाएगा।
एक मौजूदा फ़ाइल के साथ शुरू करके और उसके अंतिम हैश को सत्यापित करके, पुनरुत्पादन ने अधिलेखन व्यवहार को सीधे सिद्ध किया।
इसने परिणाम को केवल-स्रोत दावे की तुलना में अधिक ठोस बना दिया।
इस समस्या के लिए स्थानीय फाइलसिस्टम प्रभाव की आवश्यकता होती है।
एक हमलावर को इच्छित लेखन स्थान के अंदर या उसके अंतर्गत सिमलिंक, डायरेक्टरी जंक्शन या समकक्ष पुनर्निर्देशन बनाने या संशोधित करने के लिए पर्याप्त पहुँच की आवश्यकता होती है।
Consul Template प्रक्रिया को फिर उस पथ के माध्यम से लिखना होता है।
प्रभाव काफी हद तक प्रक्रिया के विशेषाधिकारों और रेंडर की गई सामग्री पर निर्भर करता है।
व्यावहारिक परिणामों में शामिल हैं:
यह डिफ़ॉल्ट इंस्टॉलेशन से दूरस्थ अनधिकृत मनमाना लेखन नहीं था।
लेकिन यह विशेषाधिकार प्राप्त या साझा-फाइलसिस्टम परिनियोजनों में सार्थक प्रभाव के साथ एक स्पष्ट स्थानीय विश्वास-सीमा विफलता थी।
HashiCorp ने समस्या को इस प्रकार वर्गीकृत किया:
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:N/A:N
प्रकाशित आधार स्कोर है:
4.7 / मध्यम
वह वेक्टर दर्शाता है:
आधिकारिक बुलेटिन भी स्पष्ट रूप से प्रलेखित करते हैं कि पुनर्निर्देशित लेखन एक पूर्व-मौजूदा फ़ाइल को अधिलेखित कर सकता है।
स्कोर मध्यम है क्योंकि शोषण स्थानीय पथ-नियंत्रण स्थितियों पर निर्भर करता है, इसलिए नहीं कि फाइलसिस्टम प्रभाव सैद्धांतिक है।
HashiCorp बुलेटिन सूचीबद्ध करता है:
Affected: consul-template up to and including 0.42.0
Fixed: consul-template 0.42.1
सुधार 0.42.1 रिलीज़ में 8 जुलाई 2026 को जारी किया गया।
0.42.1 पैच ने कई परतों पर लेखन पथ को सुदृढ़ किया।
पैच किया गया हेल्पर निरीक्षण के लिए os.Lstat() का उपयोग करता है:
और जब वे घटक लिंक होते हैं तो उन्हें अस्वीकार कर देता है।
यह रिपोर्ट और रिग्रेशन परीक्षणों द्वारा कवर किए गए प्रत्यक्ष पैरेंट-पुनर्निर्देशन और अंतिम-फ़ाइल-सिमलिंक मामलों को बंद करता है।
समर्थित Unix प्लेटफ़ॉर्म पर, गंतव्य को O_NOFOLLOW के साथ खोला जाता है।
यह open को स्वयं विफल कर देता है यदि अंतिम घटक पूर्व-जाँच और open के बीच सिमलिंक बन जाता है।
यह महत्वपूर्ण है क्योंकि अकेले पूर्व-जाँच एक और TOCTOU विंडो बना सकती है।
प्लेटफ़ॉर्म-विशिष्ट कार्यान्वयन Windows पर no-op है, जहाँ O_NOFOLLOW उसी तंत्र के माध्यम से उपलब्ध नहीं है।
पैच ने पथ-आधारित स्वामित्व और मोड संचालन को डिस्क्रिप्टर-आधारित संचालन से बदल दिया:
f.Chown(uid, gid)
f.Chmod(perm)
यह मेटाडेटा परिवर्तनों को उस फ़ाइल से बाँधता है जो वास्तव में खोली गई थी, बाद में पथ को फिर से हल करने के बजाय।
हेल्पर अब पैरेंट निर्देशिका केवल तभी बनाता है जब stat विफलता वास्तव में os.IsNotExist होती है।
अन्य त्रुटियाँ, जैसे अनुमति विफलताएँ, लेखन पथ में जारी रखने के बजाय लौटा दी जाती हैं।
पैच ने इसके लिए केंद्रित परीक्षण जोड़े:
सार्वजनिक पैच चर्चा एक महत्वपूर्ण सीमा को स्पष्ट रूप से प्रलेखित करती है।
नया सत्यापन जाँचता है:
यह प्रत्येक उच्च पूर्वज घटक को चलकर अस्वीकार नहीं करता।
अनुरक्षकों ने वह सीमा इसलिए चुनी क्योंकि writeToFile के पास पूर्ण कंटेनमेंट जाँच को आधार देने के लिए कोई कॉन्फ़िगर किया गया सैंडबॉक्स रूट नहीं है, और सामान्य ऑपरेटिंग सिस्टम में पथ उपसर्गों में वैध प्रबंधित लिंक शामिल हो सकते हैं, जैसे macOS पर /var -> /private/var।
O_NOFOLLOW भी अंतिम घटक की सुरक्षा करता है, हर पूर्वज निर्देशिका की नहीं।
यह रिपोर्ट की गई भेद्यता की स्थिति या आधिकारिक स्थिर संस्करण को नहीं बदलता।
यह पैच द्वारा प्रदान की गई सटीक सुरक्षा संपत्ति को स्पष्ट करता है:
वह अंतर एक तकनीकी लेखन में संरक्षित करने योग्य है।
मैंने इस समस्या को 21 मार्च 2026 को HashiCorp Security को निजी रूप से दूसरे स्वतंत्र Consul Template निष्कर्ष के रूप में रिपोर्ट किया।
रिपोर्ट में शामिल था:
मूल अनुवर्ती ईमेल सुरक्षा टीम की रिपोर्ट कतार में मौजूद नहीं था, संभवतः क्योंकि यह मेलिंग-सूची स्पैम फ़िल्टर द्वारा पकड़ लिया गया था।
मेरे द्वारा पूर्ण रिपोर्ट को पुनः अग्रेषित करने के बाद, HashiCorp ने इंजीनियरिंग टीम से संपर्क किया और पहली Consul Template समस्या से अलग इसकी जाँच की।
HashiCorp ने 0.42.1 में भेद्यता को ठीक किया और 8 जुलाई 2026 को HCSEC-2026-20 प्रकाशित किया।
IBM ने उसी CVE के लिए एक संगत सुरक्षा बुलेटिन प्रकाशित किया।
दोनों आधिकारिक बुलेटिनों ने रिपोर्ट को इस प्रकार स्वीकार किया:
Mohamed Abdelaal (0xmrma)
मुख्य सबक सरल है:
एक पथ स्ट्रिंग उस फाइलसिस्टम ऑब्जेक्ट के समान नहीं है जिसका वह नाम लेती है
यह अंतर तब महत्वपूर्ण होता है जब विशेषाधिकार प्राप्त कोड हमलावर-प्रभावित पथ लिखता है।
यह जाँचना कि एक स्ट्रिंग इच्छित निर्देशिका से शुरू होती है, पर्याप्त नहीं है।
ट्रैवर्सल अनुक्रमों के बिना भी एक साफ पथ इसके माध्यम से कहीं और हल हो सकता है:
संवेदनशील ऑपरेशन एक ऐसे गंतव्य से बंधा होना चाहिए जिसकी पहचान सही सीमा पर सत्यापित की गई हो।
यह समस्या एक व्यापक नियम को भी सुदृढ़ करती है:
जब आपके पास पहले से एक खुला फ़ाइल डिस्क्रिप्टर हो, तो पथ को फिर से हल करने के बजाय उस डिस्क्रिप्टर के माध्यम से सुरक्षा-संवेदनशील ऑपरेशन लागू करें
यही कारण है कि डिस्क्रिप्टर-आधारित Chown और Chmod परिवर्तन मायने रखते हैं।
writeToFile प्रमाणपत्र और निजी कुंजियों जैसी संवेदनशील सामग्री के लिए प्रलेखित हैos.Create या os.OpenFile के साथ सीधे खोलाChown और Chmod ने अतिरिक्त परिवर्तनीय-पथ विश्वास पेश किया0.42.1 ने लिंक जाँच, जहाँ समर्थित हो O_NOFOLLOW, डिस्क्रिप्टर-आधारित मेटाडेटा संचालन और रिग्रेशन परीक्षण जोड़ेयह भेद्यता ../ ट्रैवर्सल के बारे में नहीं थी।
पथ स्ट्रिंग सही दिखती थी।
फाइलसिस्टम गंतव्य सही नहीं था।
Consul Template ने ऑपरेटर के इच्छित पथ को स्वीकार किया, एक हमलावर-स्थित पुनर्निर्देशन का अनुसरण किया, और रेंडर की गई सामग्री को एक अलग फ़ाइल में लिखा।
इसीलिए यह CVE-2026-14361 बन गई।
consul-template 0.42.1 में ठीक किया गया।