मैंने इसे क्रिस-डाउन के उत्कृष्ट उत्तर के ट्यूटोरियल-स्टाइल के रूप में लिखा है।
बैश में आप इस तरह से शेल वैरिएबल रख सकते हैं
$ t="hi there"
$ echo $t
hi there
$
डिफ़ॉल्ट रूप से, ये चर बच्चे प्रक्रियाओं द्वारा विरासत में नहीं मिले हैं।
$ bash
$ echo $t
$ exit
लेकिन अगर आप उन्हें निर्यात के लिए चिह्नित करते हैं, तो बैश एक ध्वज सेट करेगा जिसका अर्थ है कि वे उपप्रकारों के वातावरण में जाएंगे (हालांकि envp
पैरामीटर बहुत अधिक नहीं देखा गया है, main
आपके सी प्रोग्राम में तीन पैरामीटर हैं: main(int argc, char *argv[], char *envp[])
जहां अंतिम व्यूअर बिंदु एक सरणी है उनकी परिभाषाओं के साथ शैल चर)।
तो चलो निर्यात t
इस प्रकार है:
$ echo $t
hi there
$ export t
$ bash
$ echo $t
hi there
$ exit
जबकि उपर्युक्त t
उपधारा में अपरिभाषित था, अब यह हमारे द्वारा निर्यात किए जाने के बाद प्रकट होता है ( export -n t
यदि आप इसका निर्यात रोकना चाहते हैं तो इसका उपयोग करें )।
लेकिन बाश में कार्य एक अलग जानवर हैं। आप उन्हें इस तरह घोषित करते हैं:
$ fn() { echo "test"; }
और अब आप इसे कॉल करके फ़ंक्शन को आमंत्रित कर सकते हैं जैसे कि यह एक और शेल कमांड था:
$ fn
test
$
एक बार फिर, यदि आप एक सब-टाइम स्पॉन करते हैं, तो हमारा फ़ंक्शन निर्यात नहीं किया जाता है:
$ bash
$ fn
fn: command not found
$ exit
हम एक समारोह के साथ निर्यात कर सकते हैं export -f
:
$ export -f fn
$ bash
$ fn
test
$ exit
यहाँ मुश्किल हिस्सा है: एक निर्यात समारोह की तरह fn
एक पर्यावरण चर में बदल जाता है, जैसे कि शेल चर t
का हमारा निर्यात ऊपर था। fn
स्थानीय चर होने पर ऐसा नहीं होता है , लेकिन निर्यात के बाद हम इसे शेल चर के रूप में देख सकते हैं। हालाँकि, आप एक ही नाम के साथ एक नियमित (यानी, गैर फ़ंक्शन) शेल चर भी कर सकते हैं । बैश चर की सामग्री के आधार पर अलग होता है:
$ echo $fn
$ # See, nothing was there
$ export fn=regular
$ echo $fn
regular
$
अब हम env
निर्यात के लिए चिन्हित सभी शेल चरों को दिखाने के लिए उपयोग कर सकते हैं और नियमित fn
और फंक्शन दोनों fn
दिखा सकते हैं:
$ env
.
.
.
fn=regular
fn=() { echo "test"
}
$
एक उप-शेल दोनों परिभाषाओं को निगलेगा: एक नियमित चर के रूप में और एक फ़ंक्शन के रूप में:
$ bash
$ echo $fn
regular
$ fn
test
$ exit
fn
जैसा कि हमने ऊपर या सीधे एक नियमित चर असाइनमेंट के रूप में किया था, आप इसे परिभाषित कर सकते हैं :
$ fn='() { echo "direct" ; }'
ध्यान दें कि यह एक उच्च असामान्य बात है! आम तौर पर हम फ़ंक्शन fn
को परिभाषित करेंगे जैसा कि हमने fn() {...}
सिंटैक्स के साथ किया था । लेकिन चूंकि बैश इसे पर्यावरण के माध्यम से निर्यात करता है, इसलिए हम उपरोक्त नियमित परिभाषा के लिए सीधे "शॉर्ट कट" कर सकते हैं। ध्यान दें कि (अपने अंतर्ज्ञान के लिए काउंटर, शायद) यह वर्तमान शेल में उपलब्ध एक नए फ़ंक्शन के परिणामस्वरूप नहीं हैfn
। लेकिन अगर आप एक ** उप ** शेल को स्पॉन करते हैं, तो यह होगा।
आइए फ़ंक्शन के निर्यात को रद्द करें fn
और नए नियमित fn
(जैसा कि ऊपर दिखाया गया है) बरकरार छोड़ दें ।
$ export -nf fn
अब फ़ंक्शन fn
निर्यात नहीं किया जाता है, लेकिन नियमित चर fn
है, और इसमें यह शामिल () { echo "direct" ; }
है।
अब जब एक उप-संस्करण एक नियमित चर को देखता है जो ()
इसके साथ शुरू होता है तो बाकी को फ़ंक्शन परिभाषा के रूप में व्याख्या करता है। लेकिन यह केवल तब होता है जब एक नया शेल शुरू होता है। जैसा कि हमने ऊपर देखा, बस एक नियमित शेल चर को परिभाषित करने से ()
यह एक फ़ंक्शन की तरह व्यवहार करने का कारण नहीं बनता है। आपको एक सब-आरंभ करना होगा।
और अब "शंख" बग:
जैसा कि हमने अभी देखा, जब एक नया शेल एक नियमित चर की परिभाषा को शुरू करता है, जिसके साथ शुरू होने से ()
यह एक फ़ंक्शन के रूप में व्याख्या करता है। हालांकि, यदि फ़ंक्शन को परिभाषित करने वाले समापन ब्रेस के बाद अधिक दिया जाता है, तो यह जो कुछ भी है उसे निष्पादित करता है।
ये आवश्यकताएं हैं, एक बार और:
- नए बैश का प्रचार किया जाता है
- एक पर्यावरण चर का प्रवेश होता है
- यह पर्यावरण चर "()" से शुरू होता है और फिर ब्रेसिज़ के अंदर एक फ़ंक्शन बॉडी होता है, और फिर बाद में कमांड होता है
इस मामले में, एक कमजोर बैश बाद के आदेशों को निष्पादित करेगा।
उदाहरण:
$ export ex='() { echo "function ex" ; }; echo "this is bad"; '
$ bash
this is bad
$ ex
function ex
$
नियमित रूप से निर्यात किया ex
गया चर उपसमूह में पारित किया गया था जिसे एक फ़ंक्शन के रूप में व्याख्या किया गया था ex
लेकिन अनुगामी आदेशों को निष्पादित किया गया था ( this is bad
) उपधारा के रूप में पैदा किया गया था।
स्लीक वन-लाइन टेस्ट की व्याख्या करते हुए
शेलशॉक भेद्यता के परीक्षण के लिए एक लोकप्रिय वन-लाइनर @ जिप्पी के प्रश्न में उद्धृत है:
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
यहाँ एक ब्रेक-डाउन है: पहले :
बैश में सिर्फ एक शॉर्टहैंड है true
। true
और :
दोनों का मूल्यांकन (आप यह अनुमान लगाते हैं) सच है, बाश में:
$ if true; then echo yes; fi
yes
$ if :; then echo yes; fi
yes
$
दूसरा, env
कमांड (बाश में भी बनाया गया) पर्यावरण चर (जैसा कि हमने ऊपर देखा था) को प्रिंट करता है, लेकिन उस कमांड को दिए गए निर्यात चर (या चर) के साथ एक ही कमांड को चलाने के लिए भी इस्तेमाल किया जा सकता है, और bash -c
इसके से एक कमांड चलाता है कमांड लाइन:
$ bash -c 'echo hi'
hi
$ bash -c 'echo $t'
$ env t=exported bash -c 'echo $t'
exported
$
इसलिए इस सभी सामान को एक साथ सिलाई करके, हम एक कमांड के रूप में बैश चला सकते हैं, इसे करने के लिए कुछ डमी चीज़ दे सकते हैं (जैसे bash -c echo this is a test
) और एक चर निर्यात करें जो कि ()
उपधारा के साथ शुरू होता है, इसे एक फ़ंक्शन के रूप में व्याख्या करेगा। यदि शेलशॉक मौजूद है, तो यह तुरंत उप-क्रम में किसी भी अनुगामी आदेश को निष्पादित करेगा। चूंकि हम जिस समारोह से गुजरते हैं, वह हमारे लिए अप्रासंगिक है (लेकिन पार्स करना चाहिए!) हम सबसे कम वैध फ़ंक्शन का उपयोग कल्पना करते हैं:
$ f() { :;}
$ f
$
यहां फ़ंक्शन f
केवल :
कमांड निष्पादित करता है , जो सच लौटाता है और बाहर निकलता है। अब उस कुछ "बुराई" कमांड के लिए अपील करें और एक उपधारा के लिए एक नियमित चर निर्यात करें और आप जीतें। यहाँ फिर से एक लाइनर है:
$ env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
तो x
एक साधारण वैध फ़ंक्शन के साथ एक नियमित चर के रूप में निर्यात किया जाता echo vulnerable
है, जो अंत में से निपटने के साथ होता है। इसे बैश करने के लिए पास किया जाता है, और बैश x
एक फ़ंक्शन के रूप में व्याख्या करता है (जिसे हम परवाह नहीं करते हैं) तो शायद echo vulnerable
शेलशॉक मौजूद है।
हम this is a test
संदेश को हटाकर एक-लाइनर को थोड़ा छोटा कर सकते हैं :
$ env x='() { :;}; echo vulnerable' bash -c :
यह परेशान नहीं करता है, this is a test
लेकिन :
फिर से मूक कमांड चलाता है । (यदि आप बंद हो जाते हैं -c :
तो आप उपधारा में बैठते हैं और मैन्युअल रूप से बाहर निकलना पड़ता है।) शायद सबसे उपयोगकर्ता के अनुकूल संस्करण यह होगा:
$ env x='() { :;}; echo vulnerable' bash -c "echo If you see the word vulnerable above, you are vulnerable to shellshock"